summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/area_3d.cpp173
-rw-r--r--scene/3d/area_3d.h19
-rw-r--r--scene/3d/audio_stream_player_3d.cpp135
-rw-r--r--scene/3d/audio_stream_player_3d.h4
-rw-r--r--scene/3d/baked_lightmap.cpp1624
-rw-r--r--scene/3d/baked_lightmap.h257
-rw-r--r--scene/3d/bone_attachment_3d.cpp23
-rw-r--r--scene/3d/bone_attachment_3d.h3
-rw-r--r--scene/3d/camera_3d.cpp172
-rw-r--r--scene/3d/camera_3d.h9
-rw-r--r--scene/3d/collision_object_3d.cpp63
-rw-r--r--scene/3d/collision_object_3d.h4
-rw-r--r--scene/3d/collision_polygon_3d.cpp43
-rw-r--r--scene/3d/collision_polygon_3d.h3
-rw-r--r--scene/3d/collision_shape_3d.cpp76
-rw-r--r--scene/3d/collision_shape_3d.h5
-rw-r--r--scene/3d/cpu_particles_3d.cpp173
-rw-r--r--scene/3d/cpu_particles_3d.h12
-rw-r--r--scene/3d/decal.cpp16
-rw-r--r--scene/3d/decal.h4
-rw-r--r--scene/3d/gi_probe.cpp49
-rw-r--r--scene/3d/gi_probe.h11
-rw-r--r--scene/3d/gpu_particles_3d.cpp151
-rw-r--r--scene/3d/gpu_particles_3d.h30
-rw-r--r--scene/3d/gpu_particles_collision_3d.cpp901
-rw-r--r--scene/3d/gpu_particles_collision_3d.h342
-rw-r--r--scene/3d/immediate_geometry_3d.cpp20
-rw-r--r--scene/3d/immediate_geometry_3d.h5
-rw-r--r--scene/3d/light_3d.cpp98
-rw-r--r--scene/3d/light_3d.h27
-rw-r--r--scene/3d/lightmap_probe.cpp34
-rw-r--r--scene/3d/lightmap_probe.h42
-rw-r--r--scene/3d/lightmapper.cpp67
-rw-r--r--scene/3d/lightmapper.h120
-rw-r--r--scene/3d/listener_3d.cpp35
-rw-r--r--scene/3d/listener_3d.h1
-rw-r--r--scene/3d/mesh_instance_3d.cpp88
-rw-r--r--scene/3d/mesh_instance_3d.h6
-rw-r--r--scene/3d/multimesh_instance_3d.cpp15
-rw-r--r--scene/3d/multimesh_instance_3d.h4
-rw-r--r--scene/3d/navigation_3d.cpp8
-rw-r--r--scene/3d/navigation_3d.h1
-rw-r--r--scene/3d/navigation_agent_3d.cpp51
-rw-r--r--scene/3d/navigation_agent_3d.h20
-rw-r--r--scene/3d/navigation_obstacle_3d.cpp28
-rw-r--r--scene/3d/navigation_obstacle_3d.h4
-rw-r--r--scene/3d/navigation_region_3d.cpp59
-rw-r--r--scene/3d/navigation_region_3d.h13
-rw-r--r--scene/3d/node_3d.cpp201
-rw-r--r--scene/3d/node_3d.h14
-rw-r--r--scene/3d/path_3d.cpp166
-rw-r--r--scene/3d/path_3d.h11
-rw-r--r--scene/3d/physics_body_3d.cpp473
-rw-r--r--scene/3d/physics_body_3d.h212
-rw-r--r--scene/3d/physics_joint_3d.cpp163
-rw-r--r--scene/3d/physics_joint_3d.h20
-rw-r--r--scene/3d/position_3d.h1
-rw-r--r--scene/3d/proximity_group_3d.cpp35
-rw-r--r--scene/3d/proximity_group_3d.h11
-rw-r--r--scene/3d/ray_cast_3d.cpp144
-rw-r--r--scene/3d/ray_cast_3d.h7
-rw-r--r--scene/3d/reflection_probe.cpp102
-rw-r--r--scene/3d/reflection_probe.h30
-rw-r--r--scene/3d/remote_transform_3d.cpp45
-rw-r--r--scene/3d/remote_transform_3d.h2
-rw-r--r--scene/3d/skeleton_3d.cpp201
-rw-r--r--scene/3d/skeleton_3d.h22
-rw-r--r--scene/3d/skeleton_ik_3d.cpp93
-rw-r--r--scene/3d/skeleton_ik_3d.h56
-rw-r--r--scene/3d/soft_body_3d.cpp104
-rw-r--r--scene/3d/soft_body_3d.h23
-rw-r--r--scene/3d/spring_arm_3d.cpp19
-rw-r--r--scene/3d/spring_arm_3d.h12
-rw-r--r--scene/3d/sprite_3d.cpp234
-rw-r--r--scene/3d/sprite_3d.h21
-rw-r--r--scene/3d/vehicle_body_3d.cpp115
-rw-r--r--scene/3d/vehicle_body_3d.h6
-rw-r--r--scene/3d/velocity_tracker_3d.cpp13
-rw-r--r--scene/3d/visibility_notifier_3d.cpp68
-rw-r--r--scene/3d/visibility_notifier_3d.h6
-rw-r--r--scene/3d/visual_instance_3d.cpp136
-rw-r--r--scene/3d/visual_instance_3d.h40
-rw-r--r--scene/3d/voxelizer.cpp277
-rw-r--r--scene/3d/voxelizer.h1
-rw-r--r--scene/3d/world_environment.cpp77
-rw-r--r--scene/3d/world_environment.h5
-rw-r--r--scene/3d/xr_nodes.cpp114
-rw-r--r--scene/3d/xr_nodes.h59
88 files changed, 4878 insertions, 3509 deletions
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index b72483d71b..b1ffe76662 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -35,27 +35,24 @@
#include "servers/physics_server_3d.h"
void Area3D::set_space_override_mode(SpaceOverride p_mode) {
-
space_override = p_mode;
PhysicsServer3D::get_singleton()->area_set_space_override_mode(get_rid(), PhysicsServer3D::AreaSpaceOverrideMode(p_mode));
}
-Area3D::SpaceOverride Area3D::get_space_override_mode() const {
+Area3D::SpaceOverride Area3D::get_space_override_mode() const {
return space_override;
}
void Area3D::set_gravity_is_point(bool p_enabled) {
-
gravity_is_point = p_enabled;
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT, p_enabled);
}
-bool Area3D::is_gravity_a_point() const {
+bool Area3D::is_gravity_a_point() const {
return gravity_is_point;
}
void Area3D::set_gravity_distance_scale(real_t p_scale) {
-
gravity_distance_scale = p_scale;
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale);
}
@@ -65,57 +62,51 @@ real_t Area3D::get_gravity_distance_scale() const {
}
void Area3D::set_gravity_vector(const Vector3 &p_vec) {
-
gravity_vec = p_vec;
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, p_vec);
}
-Vector3 Area3D::get_gravity_vector() const {
+Vector3 Area3D::get_gravity_vector() const {
return gravity_vec;
}
void Area3D::set_gravity(real_t p_gravity) {
-
gravity = p_gravity;
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY, p_gravity);
}
-real_t Area3D::get_gravity() const {
+real_t Area3D::get_gravity() const {
return gravity;
}
-void Area3D::set_linear_damp(real_t p_linear_damp) {
+void Area3D::set_linear_damp(real_t p_linear_damp) {
linear_damp = p_linear_damp;
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, p_linear_damp);
}
-real_t Area3D::get_linear_damp() const {
+real_t Area3D::get_linear_damp() const {
return linear_damp;
}
void Area3D::set_angular_damp(real_t p_angular_damp) {
-
angular_damp = p_angular_damp;
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, p_angular_damp);
}
real_t Area3D::get_angular_damp() const {
-
return angular_damp;
}
void Area3D::set_priority(real_t p_priority) {
-
priority = p_priority;
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_PRIORITY, p_priority);
}
-real_t Area3D::get_priority() const {
+real_t Area3D::get_priority() const {
return priority;
}
void Area3D::_body_enter_tree(ObjectID p_id) {
-
Object *obj = ObjectDB::get_instance(p_id);
Node *node = Object::cast_to<Node>(obj);
ERR_FAIL_COND(!node);
@@ -127,13 +118,11 @@ void Area3D::_body_enter_tree(ObjectID p_id) {
E->get().in_tree = true;
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
-
emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
}
}
void Area3D::_body_exit_tree(ObjectID p_id) {
-
Object *obj = ObjectDB::get_instance(p_id);
Node *node = Object::cast_to<Node>(obj);
ERR_FAIL_COND(!node);
@@ -143,13 +132,11 @@ void Area3D::_body_exit_tree(ObjectID p_id) {
E->get().in_tree = false;
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
-
emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
}
}
void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape) {
-
bool body_in = p_status == PhysicsServer3D::AREA_BODY_ADDED;
ObjectID objid = p_instance;
@@ -166,7 +153,6 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
if (body_in) {
if (!E) {
-
E = body_map.insert(objid, BodyState());
E->get().rc = 0;
E->get().in_tree = node && node->is_inside_tree();
@@ -179,46 +165,41 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
}
}
E->get().rc++;
- if (node)
+ if (node) {
E->get().shapes.insert(ShapePair(p_body_shape, p_area_shape));
+ }
if (E->get().in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_area_shape);
}
} else {
-
E->get().rc--;
- if (node)
+ if (node) {
E->get().shapes.erase(ShapePair(p_body_shape, p_area_shape));
+ }
- bool eraseit = false;
-
+ bool in_tree = E->get().in_tree;
if (E->get().rc == 0) {
-
+ body_map.erase(E);
if (node) {
node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree));
node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree));
- if (E->get().in_tree)
+ if (in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_exited, obj);
+ }
}
-
- eraseit = true;
}
- if (node && E->get().in_tree) {
+ if (node && in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_area_shape);
}
-
- if (eraseit)
- body_map.erase(E);
}
locked = false;
}
void Area3D::_clear_monitoring() {
-
ERR_FAIL_COND_MSG(locked, "This function can't be used during the in/out signal.");
{
@@ -227,77 +208,75 @@ void Area3D::_clear_monitoring() {
//disconnect all monitored stuff
for (Map<ObjectID, BodyState>::Element *E = bmcopy.front(); E; E = E->next()) {
-
Object *obj = ObjectDB::get_instance(E->key());
Node *node = Object::cast_to<Node>(obj);
- if (!node) //node may have been deleted in previous frame or at other legiminate point
+ if (!node) { //node may have been deleted in previous frame or at other legiminate point
continue;
+ }
//ERR_CONTINUE(!node);
- if (!E->get().in_tree)
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree));
+
+ if (!E->get().in_tree) {
continue;
+ }
for (int i = 0; i < E->get().shapes.size(); i++) {
-
emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->key(), node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
}
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
-
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree));
}
}
{
-
Map<ObjectID, AreaState> bmcopy = area_map;
area_map.clear();
//disconnect all monitored stuff
for (Map<ObjectID, AreaState>::Element *E = bmcopy.front(); E; E = E->next()) {
-
Object *obj = ObjectDB::get_instance(E->key());
Node *node = Object::cast_to<Node>(obj);
- if (!node) //node may have been deleted in previous frame or at other legiminate point
+ if (!node) { //node may have been deleted in previous frame or at other legiminate point
continue;
+ }
//ERR_CONTINUE(!node);
- if (!E->get().in_tree)
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree));
+
+ if (!E->get().in_tree) {
continue;
+ }
for (int i = 0; i < E->get().shapes.size(); i++) {
-
emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->key(), node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
}
emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
-
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree));
}
}
}
-void Area3D::_notification(int p_what) {
+void Area3D::_notification(int p_what) {
if (p_what == NOTIFICATION_EXIT_TREE) {
_clear_monitoring();
}
}
void Area3D::set_monitoring(bool p_enable) {
-
ERR_FAIL_COND_MSG(locked, "Function blocked during in/out signal. Use set_deferred(\"monitoring\", true/false).");
- if (p_enable == monitoring)
+ if (p_enable == monitoring) {
return;
+ }
monitoring = p_enable;
if (monitoring) {
-
PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout);
PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout);
} else {
@@ -308,7 +287,6 @@ void Area3D::set_monitoring(bool p_enable) {
}
void Area3D::_area_enter_tree(ObjectID p_id) {
-
Object *obj = ObjectDB::get_instance(p_id);
Node *node = Object::cast_to<Node>(obj);
ERR_FAIL_COND(!node);
@@ -320,13 +298,11 @@ void Area3D::_area_enter_tree(ObjectID p_id) {
E->get().in_tree = true;
emit_signal(SceneStringNames::get_singleton()->area_entered, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
-
emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
}
}
void Area3D::_area_exit_tree(ObjectID p_id) {
-
Object *obj = ObjectDB::get_instance(p_id);
Node *node = Object::cast_to<Node>(obj);
ERR_FAIL_COND(!node);
@@ -336,13 +312,11 @@ void Area3D::_area_exit_tree(ObjectID p_id) {
E->get().in_tree = false;
emit_signal(SceneStringNames::get_singleton()->area_exited, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
-
emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
}
}
void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape) {
-
bool area_in = p_status == PhysicsServer3D::AREA_BODY_ADDED;
ObjectID objid = p_instance;
@@ -359,7 +333,6 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
if (area_in) {
if (!E) {
-
E = area_map.insert(objid, AreaState());
E->get().rc = 0;
E->get().in_tree = node && node->is_inside_tree();
@@ -372,52 +345,45 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
}
}
E->get().rc++;
- if (node)
+ if (node) {
E->get().shapes.insert(AreaShapePair(p_area_shape, p_self_shape));
+ }
if (!node || E->get().in_tree) {
emit_signal(SceneStringNames::get_singleton()->area_shape_entered, objid, node, p_area_shape, p_self_shape);
}
} else {
-
E->get().rc--;
- if (node)
+ if (node) {
E->get().shapes.erase(AreaShapePair(p_area_shape, p_self_shape));
+ }
- bool eraseit = false;
-
+ bool in_tree = E->get().in_tree;
if (E->get().rc == 0) {
-
+ area_map.erase(E);
if (node) {
node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree));
node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree));
- if (E->get().in_tree) {
+ if (in_tree) {
emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
}
}
-
- eraseit = true;
}
- if (!node || E->get().in_tree) {
+ if (!node || in_tree) {
emit_signal(SceneStringNames::get_singleton()->area_shape_exited, objid, obj, p_area_shape, p_self_shape);
}
-
- if (eraseit)
- area_map.erase(E);
}
locked = false;
}
bool Area3D::is_monitoring() const {
-
return monitoring;
}
TypedArray<Node3D> Area3D::get_overlapping_bodies() const {
-
ERR_FAIL_COND_V(!monitoring, Array());
Array ret;
ret.resize(body_map.size());
@@ -435,11 +401,11 @@ TypedArray<Node3D> Area3D::get_overlapping_bodies() const {
}
void Area3D::set_monitorable(bool p_enable) {
-
ERR_FAIL_COND_MSG(locked || (is_inside_tree() && PhysicsServer3D::get_singleton()->is_flushing_queries()), "Function blocked during in/out signal. Use set_deferred(\"monitorable\", true/false).");
- if (p_enable == monitorable)
+ if (p_enable == monitorable) {
return;
+ }
monitorable = p_enable;
@@ -447,12 +413,10 @@ void Area3D::set_monitorable(bool p_enable) {
}
bool Area3D::is_monitorable() const {
-
return monitorable;
}
TypedArray<Area3D> Area3D::get_overlapping_areas() const {
-
ERR_FAIL_COND_V(!monitoring, Array());
Array ret;
ret.resize(area_map.size());
@@ -470,89 +434,82 @@ TypedArray<Area3D> Area3D::get_overlapping_areas() const {
}
bool Area3D::overlaps_area(Node *p_area) const {
-
ERR_FAIL_NULL_V(p_area, false);
const Map<ObjectID, AreaState>::Element *E = area_map.find(p_area->get_instance_id());
- if (!E)
+ if (!E) {
return false;
+ }
return E->get().in_tree;
}
bool Area3D::overlaps_body(Node *p_body) const {
-
ERR_FAIL_NULL_V(p_body, false);
const Map<ObjectID, BodyState>::Element *E = body_map.find(p_body->get_instance_id());
- if (!E)
+ if (!E) {
return false;
+ }
return E->get().in_tree;
}
-void Area3D::set_collision_mask(uint32_t p_mask) {
+void Area3D::set_collision_mask(uint32_t p_mask) {
collision_mask = p_mask;
PhysicsServer3D::get_singleton()->area_set_collision_mask(get_rid(), p_mask);
}
uint32_t Area3D::get_collision_mask() const {
-
return collision_mask;
}
-void Area3D::set_collision_layer(uint32_t p_layer) {
+void Area3D::set_collision_layer(uint32_t p_layer) {
collision_layer = p_layer;
PhysicsServer3D::get_singleton()->area_set_collision_layer(get_rid(), p_layer);
}
uint32_t Area3D::get_collision_layer() const {
-
return collision_layer;
}
void Area3D::set_collision_mask_bit(int p_bit, bool p_value) {
-
uint32_t mask = get_collision_mask();
- if (p_value)
+ if (p_value) {
mask |= 1 << p_bit;
- else
+ } else {
mask &= ~(1 << p_bit);
+ }
set_collision_mask(mask);
}
bool Area3D::get_collision_mask_bit(int p_bit) const {
-
return get_collision_mask() & (1 << p_bit);
}
void Area3D::set_collision_layer_bit(int p_bit, bool p_value) {
-
uint32_t layer = get_collision_layer();
- if (p_value)
+ if (p_value) {
layer |= 1 << p_bit;
- else
+ } else {
layer &= ~(1 << p_bit);
+ }
set_collision_layer(layer);
}
bool Area3D::get_collision_layer_bit(int p_bit) const {
-
return get_collision_layer() & (1 << p_bit);
}
void Area3D::set_audio_bus_override(bool p_override) {
-
audio_bus_override = p_override;
}
bool Area3D::is_overriding_audio_bus() const {
-
return audio_bus_override;
}
void Area3D::set_audio_bus(const StringName &p_audio_bus) {
-
audio_bus = p_audio_bus;
}
-StringName Area3D::get_audio_bus() const {
+StringName Area3D::get_audio_bus() const {
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
if (AudioServer::get_singleton()->get_bus_name(i) == audio_bus) {
return audio_bus;
@@ -562,20 +519,18 @@ StringName Area3D::get_audio_bus() const {
}
void Area3D::set_use_reverb_bus(bool p_enable) {
-
use_reverb_bus = p_enable;
}
-bool Area3D::is_using_reverb_bus() const {
+bool Area3D::is_using_reverb_bus() const {
return use_reverb_bus;
}
void Area3D::set_reverb_bus(const StringName &p_audio_bus) {
-
reverb_bus = p_audio_bus;
}
-StringName Area3D::get_reverb_bus() const {
+StringName Area3D::get_reverb_bus() const {
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
if (AudioServer::get_singleton()->get_bus_name(i) == reverb_bus) {
return reverb_bus;
@@ -585,31 +540,28 @@ StringName Area3D::get_reverb_bus() const {
}
void Area3D::set_reverb_amount(float p_amount) {
-
reverb_amount = p_amount;
}
-float Area3D::get_reverb_amount() const {
+float Area3D::get_reverb_amount() const {
return reverb_amount;
}
void Area3D::set_reverb_uniformity(float p_uniformity) {
-
reverb_uniformity = p_uniformity;
}
-float Area3D::get_reverb_uniformity() const {
+float Area3D::get_reverb_uniformity() const {
return reverb_uniformity;
}
void Area3D::_validate_property(PropertyInfo &property) const {
-
if (property.name == "audio_bus_name" || property.name == "reverb_bus_name") {
-
String options;
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
- if (i > 0)
+ if (i > 0) {
options += ",";
+ }
String name = AudioServer::get_singleton()->get_bus_name(i);
options += name;
}
@@ -729,7 +681,6 @@ void Area3D::_bind_methods() {
Area3D::Area3D() :
CollisionObject3D(PhysicsServer3D::get_singleton()->area_create(), true) {
-
space_override = SPACE_OVERRIDE_DISABLED;
set_gravity(9.8);
locked = false;
diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h
index f6503c6d2d..7d1f030baf 100644
--- a/scene/3d/area_3d.h
+++ b/scene/3d/area_3d.h
@@ -31,11 +31,10 @@
#ifndef AREA_3D_H
#define AREA_3D_H
-#include "core/vset.h"
+#include "core/templates/vset.h"
#include "scene/3d/collision_object_3d.h"
class Area3D : public CollisionObject3D {
-
GDCLASS(Area3D, CollisionObject3D);
public:
@@ -68,14 +67,14 @@ private:
void _body_exit_tree(ObjectID p_id);
struct ShapePair {
-
int body_shape;
int area_shape;
bool operator<(const ShapePair &p_sp) const {
- if (body_shape == p_sp.body_shape)
+ if (body_shape == p_sp.body_shape) {
return area_shape < p_sp.area_shape;
- else
+ } else {
return body_shape < p_sp.body_shape;
+ }
}
ShapePair() {}
@@ -86,7 +85,6 @@ private:
};
struct BodyState {
-
int rc;
bool in_tree;
VSet<ShapePair> shapes;
@@ -100,14 +98,14 @@ private:
void _area_exit_tree(ObjectID p_id);
struct AreaShapePair {
-
int area_shape;
int self_shape;
bool operator<(const AreaShapePair &p_sp) const {
- if (area_shape == p_sp.area_shape)
+ if (area_shape == p_sp.area_shape) {
return self_shape < p_sp.self_shape;
- else
+ } else {
return area_shape < p_sp.area_shape;
+ }
}
AreaShapePair() {}
@@ -118,7 +116,6 @@ private:
};
struct AreaState {
-
int rc;
bool in_tree;
VSet<AreaShapePair> shapes;
@@ -135,7 +132,7 @@ private:
float reverb_amount;
float reverb_uniformity;
- void _validate_property(PropertyInfo &property) const;
+ void _validate_property(PropertyInfo &property) const override;
protected:
void _notification(int p_what);
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 097368853e..b093788d75 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -30,7 +30,7 @@
#include "audio_stream_player_3d.h"
-#include "core/engine.h"
+#include "core/config/engine.h"
#include "scene/3d/area_3d.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/listener_3d.h"
@@ -138,7 +138,6 @@ void AudioStreamPlayer3D::_calc_output_vol(const Vector3 &source_dir, real_t tig
}
void AudioStreamPlayer3D::_mix_audio() {
-
if (!stream_playback.is_valid() || !active ||
(stream_paused && !stream_paused_fade_out)) {
return;
@@ -162,7 +161,6 @@ void AudioStreamPlayer3D::_mix_audio() {
// Mix if we're not paused or we're fading out
if ((output_count > 0 || out_of_range_mode == OUT_OF_RANGE_MIX)) {
-
float output_pitch_scale = 0.0;
if (output_count) {
//used for doppler, not realistic but good enough
@@ -179,7 +177,6 @@ void AudioStreamPlayer3D::_mix_audio() {
//write all outputs
for (int i = 0; i < output_count; i++) {
-
Output current = outputs[i];
//see if current output exists, to keep volume ramp
@@ -216,8 +213,9 @@ void AudioStreamPlayer3D::_mix_audio() {
AudioFrame vol_inc = (target_volume - vol_prev) / float(buffer_size);
AudioFrame vol = vol_prev;
- if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.bus_index, k))
+ if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.bus_index, k)) {
continue; //may have been deleted, will be updated on process
+ }
AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, k);
current.filter.set_mode(AudioFilterSW::HIGHSHELF);
@@ -228,7 +226,6 @@ void AudioStreamPlayer3D::_mix_audio() {
current.filter.set_gain(current.filter_gain);
if (interpolate_filter) {
-
current.filter_process[k * 2 + 0] = prev_outputs[i].filter_process[k * 2 + 0];
current.filter_process[k * 2 + 1] = prev_outputs[i].filter_process[k * 2 + 1];
@@ -238,7 +235,6 @@ void AudioStreamPlayer3D::_mix_audio() {
current.filter_process[k * 2 + 0].update_coeffs(buffer_size);
current.filter_process[k * 2 + 1].update_coeffs(buffer_size);
for (int j = 0; j < buffer_size; j++) {
-
AudioFrame f = buffer[j] * vol;
current.filter_process[k * 2 + 0].process_one_interp(f.l);
current.filter_process[k * 2 + 1].process_one_interp(f.r);
@@ -253,7 +249,6 @@ void AudioStreamPlayer3D::_mix_audio() {
current.filter_process[k * 2 + 0].update_coeffs();
current.filter_process[k * 2 + 1].update_coeffs();
for (int j = 0; j < buffer_size; j++) {
-
AudioFrame f = buffer[j] * vol;
current.filter_process[k * 2 + 0].process_one(f.l);
current.filter_process[k * 2 + 1].process_one(f.r);
@@ -264,9 +259,9 @@ void AudioStreamPlayer3D::_mix_audio() {
}
if (current.reverb_bus_index >= 0) {
-
- if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.reverb_bus_index, k))
+ if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.reverb_bus_index, k)) {
continue; //may have been deleted, will be updated on process
+ }
AudioFrame *rtarget = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.reverb_bus_index, k);
@@ -275,15 +270,12 @@ void AudioStreamPlayer3D::_mix_audio() {
AudioFrame rvol = prev_outputs[i].reverb_vol[k];
for (int j = 0; j < buffer_size; j++) {
-
rtarget[j] += buffer[j] * rvol;
rvol += rvol_inc;
}
} else {
-
AudioFrame rvol = current.reverb_vol[k];
for (int j = 0; j < buffer_size; j++) {
-
rtarget[j] += buffer[j] * rvol;
}
}
@@ -306,7 +298,6 @@ void AudioStreamPlayer3D::_mix_audio() {
}
float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const {
-
float att = 0;
switch (attenuation_model) {
case ATTENUATION_INVERSE_DISTANCE: {
@@ -320,7 +311,8 @@ float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const {
case ATTENUATION_LOGARITHMIC: {
att = -20 * Math::log(p_distance / unit_size + CMP_EPSILON);
} break;
- case ATTENUATION_DISABLED: break;
+ case ATTENUATION_DISABLED:
+ break;
default: {
ERR_PRINT("Unknown attenuation type");
break;
@@ -339,9 +331,7 @@ void _update_sound() {
}
void AudioStreamPlayer3D::_notification(int p_what) {
-
if (p_what == NOTIFICATION_ENTER_TREE) {
-
velocity_tracker->reset(get_global_transform().origin);
AudioServer::get_singleton()->add_callback(_mix_audios, this);
if (autoplay && !Engine::get_singleton()->is_editor_hint()) {
@@ -350,7 +340,6 @@ void AudioStreamPlayer3D::_notification(int p_what) {
}
if (p_what == NOTIFICATION_EXIT_TREE) {
-
AudioServer::get_singleton()->remove_callback(_mix_audios, this);
}
@@ -366,18 +355,15 @@ void AudioStreamPlayer3D::_notification(int p_what) {
}
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
-
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
velocity_tracker->update_position(get_global_transform().origin);
}
}
if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
-
//update anything related to position first, if possible of course
if (!output_ready) {
-
Vector3 linear_velocity;
//compute linear velocity for doppler
@@ -385,8 +371,8 @@ void AudioStreamPlayer3D::_notification(int p_what) {
linear_velocity = velocity_tracker->get_tracked_linear_velocity();
}
- Ref<World3D> world = get_world();
- ERR_FAIL_COND(world.is_null());
+ Ref<World3D> world_3d = get_world_3d();
+ ERR_FAIL_COND(world_3d.is_null());
int new_output_count = 0;
@@ -396,7 +382,7 @@ void AudioStreamPlayer3D::_notification(int p_what) {
//check if any area is diverting sound into a bus
- PhysicsDirectSpaceState3D *space_state = PhysicsServer3D::get_singleton()->space_get_direct_state(world->get_space());
+ PhysicsDirectSpaceState3D *space_state = PhysicsServer3D::get_singleton()->space_get_direct_state(world_3d->get_space());
PhysicsDirectSpaceState3D::ShapeResult sr[MAX_INTERSECT_AREAS];
@@ -404,29 +390,32 @@ void AudioStreamPlayer3D::_notification(int p_what) {
Area3D *area = nullptr;
for (int i = 0; i < areas; i++) {
- if (!sr[i].collider)
+ if (!sr[i].collider) {
continue;
+ }
Area3D *tarea = Object::cast_to<Area3D>(sr[i].collider);
- if (!tarea)
+ if (!tarea) {
continue;
+ }
- if (!tarea->is_overriding_audio_bus() && !tarea->is_using_reverb_bus())
+ if (!tarea->is_overriding_audio_bus() && !tarea->is_using_reverb_bus()) {
continue;
+ }
area = tarea;
break;
}
List<Camera3D *> cameras;
- world->get_camera_list(&cameras);
+ world_3d->get_camera_list(&cameras);
for (List<Camera3D *>::Element *E = cameras.front(); E; E = E->next()) {
-
Camera3D *camera = E->get();
Viewport *vp = camera->get_viewport();
- if (!vp->is_audio_listener())
+ if (!vp->is_audio_listener()) {
continue;
+ }
bool listener_is_camera = true;
Node3D *listener_node = camera;
@@ -450,7 +439,6 @@ void AudioStreamPlayer3D::_notification(int p_what) {
}
if (max_distance > 0) {
-
float total_max = max_distance;
if (area && area->is_using_reverb_bus() && area->get_reverb_uniformity() > 0) {
@@ -477,8 +465,9 @@ void AudioStreamPlayer3D::_notification(int p_what) {
Vector3 listenertopos = global_pos - listener_node->get_global_transform().origin;
float c = listenertopos.normalized().dot(get_global_transform().basis.get_axis(2).normalized()); //it's z negative
float angle = Math::rad2deg(Math::acos(c));
- if (angle > emission_angle)
+ if (angle > emission_angle) {
db_att -= -emission_angle_filter_attenuation_db;
+ }
}
output.filter_gain = Math::db2linear(db_att);
@@ -496,7 +485,6 @@ void AudioStreamPlayer3D::_notification(int p_what) {
int vol_index_max = AudioServer::get_singleton()->get_speaker_mode() + 1;
if (area) {
-
if (area->is_overriding_audio_bus()) {
//override audio bus
StringName bus_name = area->get_audio_bus();
@@ -504,7 +492,6 @@ void AudioStreamPlayer3D::_notification(int p_what) {
}
if (area->is_using_reverb_bus()) {
-
filled_reverb = true;
StringName bus_name = area->get_reverb_bus();
output.reverb_bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus_name);
@@ -513,7 +500,6 @@ void AudioStreamPlayer3D::_notification(int p_what) {
float area_send = area->get_reverb_amount();
if (uniformity > 0.0) {
-
float distance = listener_area_pos.length();
float attenuation = Math::db2linear(_get_attenuation_db(distance));
@@ -555,26 +541,21 @@ void AudioStreamPlayer3D::_notification(int p_what) {
}
for (int i = 0; i < vol_index_max; i++) {
-
- output.reverb_vol[i] = output.reverb_vol[i].linear_interpolate(center_frame, attenuation);
+ output.reverb_vol[i] = output.reverb_vol[i].lerp(center_frame, attenuation);
}
} else {
for (int i = 0; i < vol_index_max; i++) {
-
output.reverb_vol[i] = center_frame;
}
}
for (int i = 0; i < vol_index_max; i++) {
-
- output.reverb_vol[i] = output.vol[i].linear_interpolate(output.reverb_vol[i] * attenuation, uniformity);
+ output.reverb_vol[i] = output.vol[i].lerp(output.reverb_vol[i] * attenuation, uniformity);
output.reverb_vol[i] *= area_send;
}
} else {
-
for (int i = 0; i < vol_index_max; i++) {
-
output.reverb_vol[i] = output.vol[i] * area_send;
}
}
@@ -582,7 +563,6 @@ void AudioStreamPlayer3D::_notification(int p_what) {
}
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
-
Vector3 listener_velocity;
if (listener_is_camera) {
@@ -607,17 +587,16 @@ void AudioStreamPlayer3D::_notification(int p_what) {
}
if (!filled_reverb) {
-
for (int i = 0; i < vol_index_max; i++) {
-
output.reverb_vol[i] = AudioFrame(0, 0);
}
}
outputs[new_output_count] = output;
new_output_count++;
- if (new_output_count == MAX_OUTPUTS)
+ if (new_output_count == MAX_OUTPUTS) {
break;
+ }
}
output_count = new_output_count;
@@ -644,7 +623,6 @@ void AudioStreamPlayer3D::_notification(int p_what) {
}
void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) {
-
AudioServer::get_singleton()->lock();
mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size());
@@ -669,34 +647,30 @@ void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) {
}
Ref<AudioStream> AudioStreamPlayer3D::get_stream() const {
-
return stream;
}
void AudioStreamPlayer3D::set_unit_db(float p_volume) {
-
unit_db = p_volume;
}
-float AudioStreamPlayer3D::get_unit_db() const {
+float AudioStreamPlayer3D::get_unit_db() const {
return unit_db;
}
void AudioStreamPlayer3D::set_unit_size(float p_volume) {
-
unit_size = p_volume;
}
-float AudioStreamPlayer3D::get_unit_size() const {
+float AudioStreamPlayer3D::get_unit_size() const {
return unit_size;
}
void AudioStreamPlayer3D::set_max_db(float p_boost) {
-
max_db = p_boost;
}
-float AudioStreamPlayer3D::get_max_db() const {
+float AudioStreamPlayer3D::get_max_db() const {
return max_db;
}
@@ -704,11 +678,16 @@ void AudioStreamPlayer3D::set_pitch_scale(float p_pitch_scale) {
ERR_FAIL_COND(p_pitch_scale <= 0.0);
pitch_scale = p_pitch_scale;
}
+
float AudioStreamPlayer3D::get_pitch_scale() const {
return pitch_scale;
}
void AudioStreamPlayer3D::play(float p_from_pos) {
+ if (!is_playing()) {
+ // Reset the prev_output_count if the stream is stopped
+ prev_output_count = 0;
+ }
if (stream_playback.is_valid()) {
active = true;
@@ -719,14 +698,12 @@ void AudioStreamPlayer3D::play(float p_from_pos) {
}
void AudioStreamPlayer3D::seek(float p_seconds) {
-
if (stream_playback.is_valid()) {
setseek = p_seconds;
}
}
void AudioStreamPlayer3D::stop() {
-
if (stream_playback.is_valid()) {
active = false;
set_physics_process_internal(false);
@@ -735,7 +712,6 @@ void AudioStreamPlayer3D::stop() {
}
bool AudioStreamPlayer3D::is_playing() const {
-
if (stream_playback.is_valid()) {
return active; // && stream_playback->is_playing();
}
@@ -744,7 +720,6 @@ bool AudioStreamPlayer3D::is_playing() const {
}
float AudioStreamPlayer3D::get_playback_position() {
-
if (stream_playback.is_valid()) {
return stream_playback->get_playback_position();
}
@@ -753,14 +728,13 @@ float AudioStreamPlayer3D::get_playback_position() {
}
void AudioStreamPlayer3D::set_bus(const StringName &p_bus) {
-
//if audio is active, must lock this
AudioServer::get_singleton()->lock();
bus = p_bus;
AudioServer::get_singleton()->unlock();
}
-StringName AudioStreamPlayer3D::get_bus() const {
+StringName AudioStreamPlayer3D::get_bus() const {
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
if (AudioServer::get_singleton()->get_bus_name(i) == bus) {
return bus;
@@ -770,34 +744,32 @@ StringName AudioStreamPlayer3D::get_bus() const {
}
void AudioStreamPlayer3D::set_autoplay(bool p_enable) {
-
autoplay = p_enable;
}
-bool AudioStreamPlayer3D::is_autoplay_enabled() {
+bool AudioStreamPlayer3D::is_autoplay_enabled() {
return autoplay;
}
void AudioStreamPlayer3D::_set_playing(bool p_enable) {
-
- if (p_enable)
+ if (p_enable) {
play();
- else
+ } else {
stop();
+ }
}
-bool AudioStreamPlayer3D::_is_active() const {
+bool AudioStreamPlayer3D::_is_active() const {
return active;
}
void AudioStreamPlayer3D::_validate_property(PropertyInfo &property) const {
-
if (property.name == "bus") {
-
String options;
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
- if (i > 0)
+ if (i > 0) {
options += ",";
+ }
String name = AudioServer::get_singleton()->get_bus_name(i);
options += name;
}
@@ -807,28 +779,23 @@ void AudioStreamPlayer3D::_validate_property(PropertyInfo &property) const {
}
void AudioStreamPlayer3D::_bus_layout_changed() {
-
_change_notify();
}
void AudioStreamPlayer3D::set_max_distance(float p_metres) {
-
ERR_FAIL_COND(p_metres < 0.0);
max_distance = p_metres;
}
float AudioStreamPlayer3D::get_max_distance() const {
-
return max_distance;
}
void AudioStreamPlayer3D::set_area_mask(uint32_t p_mask) {
-
area_mask = p_mask;
}
uint32_t AudioStreamPlayer3D::get_area_mask() const {
-
return area_mask;
}
@@ -853,30 +820,26 @@ float AudioStreamPlayer3D::get_emission_angle() const {
}
void AudioStreamPlayer3D::set_emission_angle_filter_attenuation_db(float p_angle_attenuation_db) {
-
emission_angle_filter_attenuation_db = p_angle_attenuation_db;
}
float AudioStreamPlayer3D::get_emission_angle_filter_attenuation_db() const {
-
return emission_angle_filter_attenuation_db;
}
void AudioStreamPlayer3D::set_attenuation_filter_cutoff_hz(float p_hz) {
-
attenuation_filter_cutoff_hz = p_hz;
}
-float AudioStreamPlayer3D::get_attenuation_filter_cutoff_hz() const {
+float AudioStreamPlayer3D::get_attenuation_filter_cutoff_hz() const {
return attenuation_filter_cutoff_hz;
}
void AudioStreamPlayer3D::set_attenuation_filter_db(float p_db) {
-
attenuation_filter_db = p_db;
}
-float AudioStreamPlayer3D::get_attenuation_filter_db() const {
+float AudioStreamPlayer3D::get_attenuation_filter_db() const {
return attenuation_filter_db;
}
@@ -890,20 +853,18 @@ AudioStreamPlayer3D::AttenuationModel AudioStreamPlayer3D::get_attenuation_model
}
void AudioStreamPlayer3D::set_out_of_range_mode(OutOfRangeMode p_mode) {
-
ERR_FAIL_INDEX((int)p_mode, 2);
out_of_range_mode = p_mode;
}
AudioStreamPlayer3D::OutOfRangeMode AudioStreamPlayer3D::get_out_of_range_mode() const {
-
return out_of_range_mode;
}
void AudioStreamPlayer3D::set_doppler_tracking(DopplerTracking p_tracking) {
-
- if (doppler_tracking == p_tracking)
+ if (doppler_tracking == p_tracking) {
return;
+ }
doppler_tracking = p_tracking;
@@ -919,12 +880,10 @@ void AudioStreamPlayer3D::set_doppler_tracking(DopplerTracking p_tracking) {
}
AudioStreamPlayer3D::DopplerTracking AudioStreamPlayer3D::get_doppler_tracking() const {
-
return doppler_tracking;
}
void AudioStreamPlayer3D::set_stream_paused(bool p_pause) {
-
if (p_pause != stream_paused) {
stream_paused = p_pause;
stream_paused_fade_in = !stream_paused;
@@ -933,7 +892,6 @@ void AudioStreamPlayer3D::set_stream_paused(bool p_pause) {
}
bool AudioStreamPlayer3D::get_stream_paused() const {
-
return stream_paused;
}
@@ -942,7 +900,6 @@ Ref<AudioStreamPlayback> AudioStreamPlayer3D::get_stream_playback() {
}
void AudioStreamPlayer3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer3D::set_stream);
ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer3D::get_stream);
@@ -1048,7 +1005,6 @@ void AudioStreamPlayer3D::_bind_methods() {
}
AudioStreamPlayer3D::AudioStreamPlayer3D() {
-
unit_db = 0;
unit_size = 1;
attenuation_model = ATTENUATION_INVERSE_DISTANCE;
@@ -1078,5 +1034,6 @@ AudioStreamPlayer3D::AudioStreamPlayer3D() {
AudioServer::get_singleton()->connect("bus_layout_changed", callable_mp(this, &AudioStreamPlayer3D::_bus_layout_changed));
set_disable_scale(true);
}
+
AudioStreamPlayer3D::~AudioStreamPlayer3D() {
}
diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h
index 13e08339e2..339475b469 100644
--- a/scene/3d/audio_stream_player_3d.h
+++ b/scene/3d/audio_stream_player_3d.h
@@ -39,7 +39,6 @@
class Camera3D;
class AudioStreamPlayer3D : public Node3D {
-
GDCLASS(AudioStreamPlayer3D, Node3D);
public:
@@ -69,7 +68,6 @@ private:
};
struct Output {
-
AudioFilterSW filter;
AudioFilterSW::Processor filter_process[8];
AudioFrame vol[4];
@@ -143,7 +141,7 @@ private:
float _get_attenuation_db(float p_distance) const;
protected:
- void _validate_property(PropertyInfo &property) const;
+ void _validate_property(PropertyInfo &property) const override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp
index 6bde56104e..38c9e96fbc 100644
--- a/scene/3d/baked_lightmap.cpp
+++ b/scene/3d/baked_lightmap.cpp
@@ -28,94 +28,49 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#if 0
#include "baked_lightmap.h"
+
#include "core/io/config_file.h"
#include "core/io/resource_saver.h"
+#include "core/math/camera_matrix.h"
+#include "core/math/delaunay_3d.h"
#include "core/os/dir_access.h"
+#include "core/os/file_access.h"
#include "core/os/os.h"
-#include "voxel_light_baker.h"
-
-void BakedLightmapData::set_bounds(const AABB &p_bounds) {
-
- bounds = p_bounds;
- RS::get_singleton()->lightmap_capture_set_bounds(baked_light, p_bounds);
-}
-
-AABB BakedLightmapData::get_bounds() const {
-
- return bounds;
-}
-
-void BakedLightmapData::set_octree(const Vector<uint8_t> &p_octree) {
-
- RS::get_singleton()->lightmap_capture_set_octree(baked_light, p_octree);
-}
-
-Vector<uint8_t> BakedLightmapData::get_octree() const {
-
- return RS::get_singleton()->lightmap_capture_get_octree(baked_light);
-}
-
-void BakedLightmapData::set_cell_space_transform(const Transform &p_xform) {
-
- cell_space_xform = p_xform;
- RS::get_singleton()->lightmap_capture_set_octree_cell_transform(baked_light, p_xform);
-}
-
-Transform BakedLightmapData::get_cell_space_transform() const {
- return cell_space_xform;
-}
-
-void BakedLightmapData::set_cell_subdiv(int p_cell_subdiv) {
- cell_subdiv = p_cell_subdiv;
- RS::get_singleton()->lightmap_capture_set_octree_cell_subdiv(baked_light, p_cell_subdiv);
-}
-
-int BakedLightmapData::get_cell_subdiv() const {
- return cell_subdiv;
-}
+#include "core/templates/sort_array.h"
+#include "lightmap_probe.h"
-void BakedLightmapData::set_energy(float p_energy) {
-
- energy = p_energy;
- RS::get_singleton()->lightmap_capture_set_energy(baked_light, energy);
-}
-
-float BakedLightmapData::get_energy() const {
-
- return energy;
-}
-
-void BakedLightmapData::add_user(const NodePath &p_path, const Ref<Texture2D> &p_lightmap, int p_instance) {
-
- ERR_FAIL_COND_MSG(p_lightmap.is_null(), "It's not a reference to a valid Texture object.");
+void BakedLightmapData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) {
User user;
user.path = p_path;
- user.lightmap = p_lightmap;
- user.instance_index = p_instance;
+ user.uv_scale = p_uv_scale;
+ user.slice_index = p_slice_index;
+ user.sub_instance = p_sub_instance;
users.push_back(user);
}
int BakedLightmapData::get_user_count() const {
-
return users.size();
}
-NodePath BakedLightmapData::get_user_path(int p_user) const {
+NodePath BakedLightmapData::get_user_path(int p_user) const {
ERR_FAIL_INDEX_V(p_user, users.size(), NodePath());
return users[p_user].path;
}
-Ref<Texture2D> BakedLightmapData::get_user_lightmap(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), Ref<Texture2D>());
- return users[p_user].lightmap;
+int32_t BakedLightmapData::get_user_sub_instance(int p_user) const {
+ ERR_FAIL_INDEX_V(p_user, users.size(), -1);
+ return users[p_user].sub_instance;
}
-int BakedLightmapData::get_user_instance(int p_user) const {
+Rect2 BakedLightmapData::get_user_lightmap_uv_scale(int p_user) const {
+ ERR_FAIL_INDEX_V(p_user, users.size(), Rect2());
+ return users[p_user].uv_scale;
+}
+int BakedLightmapData::get_user_lightmap_slice_index(int p_user) const {
ERR_FAIL_INDEX_V(p_user, users.size(), -1);
- return users[p_user].instance_index;
+ return users[p_user].slice_index;
}
void BakedLightmapData::clear_users() {
@@ -123,539 +78,1122 @@ void BakedLightmapData::clear_users() {
}
void BakedLightmapData::_set_user_data(const Array &p_data) {
+ ERR_FAIL_COND((p_data.size() % 4) != 0);
- ERR_FAIL_COND((p_data.size() % 3) != 0);
-
- for (int i = 0; i < p_data.size(); i += 3) {
- add_user(p_data[i], p_data[i + 1], p_data[i + 2]);
+ for (int i = 0; i < p_data.size(); i += 4) {
+ add_user(p_data[i + 0], p_data[i + 1], p_data[i + 2], p_data[i + 3]);
}
}
Array BakedLightmapData::_get_user_data() const {
-
Array ret;
for (int i = 0; i < users.size(); i++) {
ret.push_back(users[i].path);
- ret.push_back(users[i].lightmap);
- ret.push_back(users[i].instance_index);
+ ret.push_back(users[i].uv_scale);
+ ret.push_back(users[i].slice_index);
+ ret.push_back(users[i].sub_instance);
}
return ret;
}
RID BakedLightmapData::get_rid() const {
- return baked_light;
+ return lightmap;
}
-void BakedLightmapData::_bind_methods() {
-
- ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &BakedLightmapData::_set_user_data);
- ClassDB::bind_method(D_METHOD("_get_user_data"), &BakedLightmapData::_get_user_data);
- ClassDB::bind_method(D_METHOD("set_bounds", "bounds"), &BakedLightmapData::set_bounds);
- ClassDB::bind_method(D_METHOD("get_bounds"), &BakedLightmapData::get_bounds);
-
- ClassDB::bind_method(D_METHOD("set_cell_space_transform", "xform"), &BakedLightmapData::set_cell_space_transform);
- ClassDB::bind_method(D_METHOD("get_cell_space_transform"), &BakedLightmapData::get_cell_space_transform);
-
- ClassDB::bind_method(D_METHOD("set_cell_subdiv", "cell_subdiv"), &BakedLightmapData::set_cell_subdiv);
- ClassDB::bind_method(D_METHOD("get_cell_subdiv"), &BakedLightmapData::get_cell_subdiv);
-
- ClassDB::bind_method(D_METHOD("set_octree", "octree"), &BakedLightmapData::set_octree);
- ClassDB::bind_method(D_METHOD("get_octree"), &BakedLightmapData::get_octree);
-
- ClassDB::bind_method(D_METHOD("set_energy", "energy"), &BakedLightmapData::set_energy);
- ClassDB::bind_method(D_METHOD("get_energy"), &BakedLightmapData::get_energy);
+void BakedLightmapData::clear() {
+ users.clear();
+}
- ClassDB::bind_method(D_METHOD("add_user", "path", "lightmap", "instance"), &BakedLightmapData::add_user);
- ClassDB::bind_method(D_METHOD("get_user_count"), &BakedLightmapData::get_user_count);
- ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &BakedLightmapData::get_user_path);
- ClassDB::bind_method(D_METHOD("get_user_lightmap", "user_idx"), &BakedLightmapData::get_user_lightmap);
- ClassDB::bind_method(D_METHOD("clear_users"), &BakedLightmapData::clear_users);
+void BakedLightmapData::set_light_texture(const Ref<TextureLayered> &p_light_texture) {
+ light_texture = p_light_texture;
+ RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics);
+}
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "cell_space_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_space_transform", "get_cell_space_transform");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_subdiv", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_subdiv", "get_cell_subdiv");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
- ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "octree", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_octree", "get_octree");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data");
+Ref<TextureLayered> BakedLightmapData::get_light_texture() const {
+ return light_texture;
}
-BakedLightmapData::BakedLightmapData() {
+void BakedLightmapData::set_uses_spherical_harmonics(bool p_enable) {
+ uses_spherical_harmonics = p_enable;
+ RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics);
+}
- baked_light = RS::get_singleton()->lightmap_capture_create();
- energy = 1;
- cell_subdiv = 1;
+bool BakedLightmapData::is_using_spherical_harmonics() const {
+ return uses_spherical_harmonics;
}
-BakedLightmapData::~BakedLightmapData() {
+void BakedLightmapData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
+ if (p_points.size()) {
+ int pc = p_points.size();
+ ERR_FAIL_COND(pc * 9 != p_point_sh.size());
+ ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);
+ ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);
+ RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, p_points, p_point_sh, p_tetrahedra, p_bsp_tree);
+ RS::get_singleton()->lightmap_set_probe_bounds(lightmap, p_bounds);
+ RS::get_singleton()->lightmap_set_probe_interior(lightmap, p_interior);
+ } else {
+ RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, PackedVector3Array(), PackedColorArray(), PackedInt32Array(), PackedInt32Array());
+ RS::get_singleton()->lightmap_set_probe_bounds(lightmap, AABB());
+ RS::get_singleton()->lightmap_set_probe_interior(lightmap, false);
+ }
+ interior = p_interior;
+ bounds = p_bounds;
+}
- RS::get_singleton()->free(baked_light);
+PackedVector3Array BakedLightmapData::get_capture_points() const {
+ return RS::get_singleton()->lightmap_get_probe_capture_points(lightmap);
}
-///////////////////////////
+PackedColorArray BakedLightmapData::get_capture_sh() const {
+ return RS::get_singleton()->lightmap_get_probe_capture_sh(lightmap);
+}
-BakedLightmap::BakeBeginFunc BakedLightmap::bake_begin_function = nullptr;
-BakedLightmap::BakeStepFunc BakedLightmap::bake_step_function = nullptr;
-BakedLightmap::BakeEndFunc BakedLightmap::bake_end_function = nullptr;
+PackedInt32Array BakedLightmapData::get_capture_tetrahedra() const {
+ return RS::get_singleton()->lightmap_get_probe_capture_tetrahedra(lightmap);
+}
-void BakedLightmap::set_bake_cell_size(float p_cell_size) {
- bake_cell_size = p_cell_size;
+PackedInt32Array BakedLightmapData::get_capture_bsp_tree() const {
+ return RS::get_singleton()->lightmap_get_probe_capture_bsp_tree(lightmap);
}
-float BakedLightmap::get_bake_cell_size() const {
- return bake_cell_size;
+AABB BakedLightmapData::get_capture_bounds() const {
+ return bounds;
}
-void BakedLightmap::set_capture_cell_size(float p_cell_size) {
- capture_cell_size = p_cell_size;
+bool BakedLightmapData::is_interior() const {
+ return interior;
}
-float BakedLightmap::get_capture_cell_size() const {
- return capture_cell_size;
+void BakedLightmapData::_set_probe_data(const Dictionary &p_data) {
+ ERR_FAIL_COND(!p_data.has("bounds"));
+ ERR_FAIL_COND(!p_data.has("points"));
+ ERR_FAIL_COND(!p_data.has("tetrahedra"));
+ ERR_FAIL_COND(!p_data.has("bsp"));
+ ERR_FAIL_COND(!p_data.has("sh"));
+ ERR_FAIL_COND(!p_data.has("interior"));
+ set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"]);
}
-void BakedLightmap::set_extents(const Vector3 &p_extents) {
- extents = p_extents;
- update_gizmo();
- _change_notify("bake_extents");
+Dictionary BakedLightmapData::_get_probe_data() const {
+ Dictionary d;
+ d["bounds"] = get_capture_bounds();
+ d["points"] = get_capture_points();
+ d["tetrahedra"] = get_capture_tetrahedra();
+ d["bsp"] = get_capture_bsp_tree();
+ d["sh"] = get_capture_sh();
+ d["interior"] = is_interior();
+ return d;
}
-Vector3 BakedLightmap::get_extents() const {
- return extents;
+void BakedLightmapData::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &BakedLightmapData::_set_user_data);
+ ClassDB::bind_method(D_METHOD("_get_user_data"), &BakedLightmapData::_get_user_data);
+
+ ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &BakedLightmapData::set_light_texture);
+ ClassDB::bind_method(D_METHOD("get_light_texture"), &BakedLightmapData::get_light_texture);
+
+ ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &BakedLightmapData::set_uses_spherical_harmonics);
+ ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &BakedLightmapData::is_using_spherical_harmonics);
+
+ ClassDB::bind_method(D_METHOD("add_user", "path", "lightmap", "offset"), &BakedLightmapData::add_user);
+ ClassDB::bind_method(D_METHOD("get_user_count"), &BakedLightmapData::get_user_count);
+ ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &BakedLightmapData::get_user_path);
+ ClassDB::bind_method(D_METHOD("clear_users"), &BakedLightmapData::clear_users);
+
+ ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &BakedLightmapData::_set_probe_data);
+ ClassDB::bind_method(D_METHOD("_get_probe_data"), &BakedLightmapData::_get_probe_data);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered"), "set_light_texture", "get_light_texture");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data");
}
-void BakedLightmap::set_bake_default_texels_per_unit(const float &p_bake_texels_per_unit) {
- bake_default_texels_per_unit = p_bake_texels_per_unit;
- update_gizmo();
+BakedLightmapData::BakedLightmapData() {
+ lightmap = RS::get_singleton()->lightmap_create();
}
-float BakedLightmap::get_bake_default_texels_per_unit() const {
- return bake_default_texels_per_unit;
+BakedLightmapData::~BakedLightmapData() {
+ RS::get_singleton()->free(lightmap);
}
-void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, List<PlotMesh> &plot_meshes, List<PlotLight> &plot_lights) {
+///////////////////////////
- MeshInstance *mi = Object::cast_to<MeshInstance>(p_at_node);
- if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) {
+void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights, Vector<Vector3> &probes) {
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
+ if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) {
Ref<Mesh> mesh = mi->get_mesh();
if (mesh.is_valid()) {
-
- bool all_have_uv2 = true;
+ bool all_have_uv2_and_normal = true;
+ bool surfaces_found = false;
for (int i = 0; i < mesh->get_surface_count(); i++) {
+ if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
+ continue;
+ }
if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_TEX_UV2)) {
- all_have_uv2 = false;
+ all_have_uv2_and_normal = false;
+ break;
+ }
+ if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_NORMAL)) {
+ all_have_uv2_and_normal = false;
break;
}
+ surfaces_found = true;
}
- if (all_have_uv2) {
+ if (surfaces_found && all_have_uv2_and_normal) {
//READY TO BAKE! size hint could be computed if not found, actually..
- AABB aabb = mesh->get_aabb();
-
- Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform();
-
- if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) {
- PlotMesh pm;
- pm.local_xform = xf;
- pm.mesh = mesh;
- pm.path = get_path_to(mi);
- pm.instance_idx = -1;
- for (int i = 0; i < mesh->get_surface_count(); i++) {
- pm.instance_materials.push_back(mi->get_surface_material(i));
+ MeshesFound mf;
+ mf.xform = get_global_transform().affine_inverse() * mi->get_global_transform();
+ mf.node_path = get_path_to(mi);
+ mf.subindex = -1;
+ mf.mesh = mesh;
+
+ static const int lightmap_scale[GeometryInstance3D::LIGHTMAP_SCALE_MAX] = { 1, 2, 4, 8 };
+ mf.lightmap_scale = lightmap_scale[mi->get_lightmap_scale()];
+
+ Ref<Material> all_override = mi->get_material_override();
+ for (int i = 0; i < mesh->get_surface_count(); i++) {
+ if (all_override.is_valid()) {
+ mf.overrides.push_back(all_override);
+ } else {
+ mf.overrides.push_back(mi->get_surface_material(i));
}
- pm.override_material = mi->get_material_override();
- plot_meshes.push_back(pm);
}
+
+ meshes.push_back(mf);
}
}
}
- Spatial *s = Object::cast_to<Spatial>(p_at_node);
+ Node3D *s = Object::cast_to<Node3D>(p_at_node);
if (!mi && s) {
- Array meshes = p_at_node->call("get_bake_meshes");
- if (meshes.size() && (meshes.size() & 1) == 0) {
+ Array bmeshes = p_at_node->call("get_bake_bmeshes");
+ if (bmeshes.size() && (bmeshes.size() & 1) == 0) {
Transform xf = get_global_transform().affine_inverse() * s->get_global_transform();
- for (int i = 0; i < meshes.size(); i += 2) {
- PlotMesh pm;
- Transform mesh_xf = meshes[i + 1];
- pm.local_xform = xf * mesh_xf;
- pm.mesh = meshes[i];
- pm.instance_idx = i / 2;
- if (!pm.mesh.is_valid())
+ for (int i = 0; i < bmeshes.size(); i += 2) {
+ Ref<Mesh> mesh = bmeshes[i];
+ if (!mesh.is_valid()) {
continue;
- pm.path = get_path_to(s);
- plot_meshes.push_back(pm);
+ }
+
+ MeshesFound mf;
+
+ Transform mesh_xf = bmeshes[i + 1];
+ mf.xform = xf * mesh_xf;
+ mf.node_path = get_path_to(s);
+ mf.subindex = i / 2;
+ mf.lightmap_scale = 1;
+ mf.mesh = mesh;
+
+ meshes.push_back(mf);
}
}
}
- Light *light = Object::cast_to<Light>(p_at_node);
+ Light3D *light = Object::cast_to<Light3D>(p_at_node);
- if (light && light->get_bake_mode() != Light::BAKE_DISABLED) {
- PlotLight pl;
- Transform xf = get_global_transform().affine_inverse() * light->get_global_transform();
+ if (light && light->get_bake_mode() != Light3D::BAKE_DISABLED) {
+ LightsFound lf;
+ lf.xform = get_global_transform().affine_inverse() * light->get_global_transform();
+ lf.light = light;
+ lights.push_back(lf);
+ }
+
+ LightmapProbe *probe = Object::cast_to<LightmapProbe>(p_at_node);
- pl.local_xform = xf;
- pl.light = light;
- plot_lights.push_back(pl);
+ if (probe) {
+ Transform xf = get_global_transform().affine_inverse() * probe->get_global_transform();
+ probes.push_back(xf.origin);
}
- for (int i = 0; i < p_at_node->get_child_count(); i++) {
+ for (int i = 0; i < p_at_node->get_child_count(); i++) {
Node *child = p_at_node->get_child(i);
- if (!child->get_owner())
+ if (!child->get_owner()) {
continue; //maybe a helper
+ }
- _find_meshes_and_lights(child, plot_meshes, plot_lights);
+ _find_meshes_and_lights(child, meshes, lights, probes);
}
}
-void BakedLightmap::set_hdr(bool p_enable) {
- hdr = p_enable;
-}
+int BakedLightmap::_bsp_get_simplex_side(const Vector<Vector3> &p_points, const LocalVector<BSPSimplex> &p_simplices, const Plane &p_plane, uint32_t p_simplex) const {
+ int over = 0;
+ int under = 0;
+ int coplanar = 0;
+ const BSPSimplex &s = p_simplices[p_simplex];
+ for (int i = 0; i < 4; i++) {
+ const Vector3 v = p_points[s.vertices[i]];
+ if (p_plane.has_point(v)) { //coplanar
+ coplanar++;
+ } else if (p_plane.is_point_over(v)) {
+ over++;
+ } else {
+ under++;
+ }
+ }
-bool BakedLightmap::is_hdr() const {
- return hdr;
+ ERR_FAIL_COND_V(under == 0 && over == 0, -2); //should never happen, we discarded flat simplices before, but in any case drop it from the bsp tree and throw an error
+ if (under == 0) {
+ return 1; // all over
+ } else if (over == 0) {
+ return -1; // all under
+ } else {
+ return 0; // crossing
+ }
}
-bool BakedLightmap::_bake_time(void *ud, float p_secs, float p_progress) {
+//#define DEBUG_BSP
- uint64_t time = OS::get_singleton()->get_ticks_usec();
- BakeTimeData *btd = (BakeTimeData *)ud;
+int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const LocalVector<Plane> &p_planes, LocalVector<int32_t> &planes_tested, const LocalVector<BSPSimplex> &p_simplices, const LocalVector<int32_t> &p_simplex_indices, LocalVector<BSPNode> &bsp_nodes) {
+ //if we reach here, it means there is more than one simplex
+ int32_t node_index = (int32_t)bsp_nodes.size();
+ bsp_nodes.push_back(BSPNode());
- if (time - btd->last_step > 1000000) {
+ //test with all the simplex planes
+ Plane best_plane;
+ float best_plane_score = -1.0;
- int mins_left = p_secs / 60;
- int secs_left = Math::fmod(p_secs, 60.0f);
- int percent = p_progress * 100;
- bool abort = bake_step_function(btd->pass + percent, btd->text + " " + vformat(RTR("%d%%"), percent) + " " + vformat(RTR("(Time Left: %d:%02d s)"), mins_left, secs_left));
- btd->last_step = time;
- if (abort)
- return true;
- }
+ for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
+ const BSPSimplex &s = p_simplices[p_simplex_indices[i]];
+ for (int j = 0; j < 4; j++) {
+ uint32_t plane_index = s.planes[j];
+ if (planes_tested[plane_index] == node_index) {
+ continue; //tested this plane already
+ }
- return false;
-}
+ planes_tested[plane_index] = node_index;
+
+ static const int face_order[4][3] = {
+ { 0, 1, 2 },
+ { 0, 2, 3 },
+ { 0, 1, 3 },
+ { 1, 2, 3 }
+ };
+
+ // despite getting rid of plane duplicates, we should still use here the actual plane to avoid numerical error
+ // from thinking this same simplex is intersecting rather than on a side
+ Vector3 v0 = p_points[s.vertices[face_order[j][0]]];
+ Vector3 v1 = p_points[s.vertices[face_order[j][1]]];
+ Vector3 v2 = p_points[s.vertices[face_order[j][2]]];
+
+ Plane plane(v0, v1, v2);
+
+ //test with all the simplices
+ int over_count = 0;
+ int under_count = 0;
+
+ for (uint32_t k = 0; k < p_simplex_indices.size(); k++) {
+ int side = _bsp_get_simplex_side(p_points, p_simplices, plane, p_simplex_indices[k]);
+ if (side == -2) {
+ continue; //this simplex is invalid, skip for now
+ } else if (side < 0) {
+ under_count++;
+ } else if (side > 0) {
+ over_count++;
+ }
+ }
-BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_visual_debug) {
+ if (under_count == 0 && over_count == 0) {
+ continue; //most likely precision issue with a flat simplex, do not try this plane
+ }
- String save_path;
+ if (under_count > over_count) { //make sure under is always less than over, so we can compute the same ratio
+ SWAP(under_count, over_count);
+ }
- if (image_path.begins_with("res://")) {
- save_path = image_path;
- } else {
- if (get_filename() != "") {
- save_path = get_filename().get_base_dir();
- } else if (get_owner() && get_owner()->get_filename() != "") {
- save_path = get_owner()->get_filename().get_base_dir();
+ float score = 0; //by default, score is 0 (worst)
+ if (over_count > 0) {
+ //give score mainly based on ratio (under / over), this means that this plane is splitting simplices a lot, but its balanced
+ score = float(under_count) / over_count;
+ }
+
+ //adjusting priority over least splits, probably not a great idea
+ //score *= Math::sqrt(float(over_count + under_count) / p_simplex_indices.size()); //also multiply score
+
+ if (score > best_plane_score) {
+ best_plane = plane;
+ best_plane_score = score;
+ }
}
+ }
- if (save_path == "") {
- return BAKE_ERROR_NO_SAVE_PATH;
+ LocalVector<int32_t> indices_over;
+ LocalVector<int32_t> indices_under;
+
+ //split again, but add to list
+ for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
+ uint32_t index = p_simplex_indices[i];
+ int side = _bsp_get_simplex_side(p_points, p_simplices, best_plane, index);
+
+ if (side == -2) {
+ continue; //simplex sits on the plane, does not make sense to use it
}
- if (image_path != "") {
- save_path.plus_file(image_path);
+ if (side <= 0) {
+ indices_under.push_back(index);
}
- }
- {
- //check for valid save path
- DirAccessRef d = DirAccess::open(save_path);
- if (!d) {
- ERR_PRINT("Invalid Save Path '" + save_path + "'.");
- return BAKE_ERROR_NO_SAVE_PATH;
+
+ if (side >= 0) {
+ indices_over.push_back(index);
}
}
- Ref<BakedLightmapData> new_light_data;
- new_light_data.instance();
+#ifdef DEBUG_BSP
+ print_line("node " + itos(node_index) + " found plane: " + best_plane + " score:" + rtos(best_plane_score) + " - over " + itos(indices_over.size()) + " under " + itos(indices_under.size()) + " intersecting " + itos(intersecting));
+#endif
+
+ if (best_plane_score < 0.0 || indices_over.size() == p_simplex_indices.size() || indices_under.size() == p_simplex_indices.size()) {
+ ERR_FAIL_COND_V(p_simplex_indices.size() <= 1, 0); //should not happen, this is a bug
- Voxelizer baker;
+ // Failed to separate the tetrahedrons using planes
+ // this means Delaunay borked at some point.
+ // Luckily, because we are using tetrahedrons, we can resort to
+ // less precise but still working ways to generate the separating plane
+ // this will most likely look bad when interpolating, but at least it will not crash.
+ // and the arctifact will most likely also be very small, so too difficult to notice.
- int bake_subdiv;
- int capture_subdiv;
- AABB bake_bounds;
- {
- bake_bounds = AABB(-extents, extents * 2.0);
- int subdiv = nearest_power_of_2_templated(int(bake_bounds.get_longest_axis_size() / bake_cell_size));
- bake_bounds.size[bake_bounds.get_longest_axis_index()] = subdiv * bake_cell_size;
- bake_subdiv = nearest_shift(subdiv) + 1;
+ //find the longest axis
+
+ WARN_PRINT("Inconsistency found in triangulation while building BSP, probe interpolation quality may degrade a bit.");
+
+ LocalVector<Vector3> centers;
+ AABB bounds_all;
+ for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
+ AABB bounds;
+ for (uint32_t j = 0; j < 4; j++) {
+ Vector3 p = p_points[p_simplices[p_simplex_indices[i]].vertices[j]];
+ if (j == 0) {
+ bounds.position = p;
+ } else {
+ bounds.expand_to(p);
+ }
+ }
+ if (i == 0) {
+ centers.push_back(bounds.position + bounds.size * 0.5);
+ } else {
+ bounds_all.merge_with(bounds);
+ }
+ }
+ Vector3::Axis longest_axis = Vector3::Axis(bounds_all.get_longest_axis_index());
+
+ //find the simplex that will go under
+ uint32_t min_d_idx = 0xFFFFFFFF;
+ float min_d_dist = 1e20;
+
+ for (uint32_t i = 0; i < centers.size(); i++) {
+ if (centers[i][longest_axis] < min_d_dist) {
+ min_d_idx = i;
+ min_d_dist = centers[i][longest_axis];
+ }
+ }
+ //rebuild best_plane and over/under arrays
+ best_plane = Plane();
+ best_plane.normal[longest_axis] = 1.0;
+ best_plane.d = min_d_dist;
- capture_subdiv = bake_subdiv;
- float css = bake_cell_size;
- while (css < capture_cell_size && capture_subdiv > 2) {
- capture_subdiv--;
- css *= 2.0;
+ indices_under.clear();
+ indices_under.push_back(min_d_idx);
+
+ indices_over.clear();
+
+ for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
+ if (i == min_d_idx) {
+ continue;
+ }
+ indices_over.push_back(p_simplex_indices[i]);
}
}
- baker.begin_bake(bake_subdiv, bake_bounds);
+ BSPNode node;
+ node.plane = best_plane;
+
+ if (indices_under.size() == 0) {
+ //noting to do here
+ node.under = BSPNode::EMPTY_LEAF;
+ } else if (indices_under.size() == 1) {
+ node.under = -(indices_under[0] + 1);
+ } else {
+ node.under = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_under, bsp_nodes);
+ }
+
+ if (indices_over.size() == 0) {
+ //noting to do here
+ node.over = BSPNode::EMPTY_LEAF;
+ } else if (indices_over.size() == 1) {
+ node.over = -(indices_over[0] + 1);
+ } else {
+ node.over = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_over, bsp_nodes);
+ }
- List<PlotMesh> mesh_list;
- List<PlotLight> light_list;
+ bsp_nodes[node_index] = node;
- _find_meshes_and_lights(p_from_node ? p_from_node : get_parent(), mesh_list, light_list);
+ return node_index;
+}
- if (bake_begin_function) {
- bake_begin_function(mesh_list.size() + light_list.size() + 1 + mesh_list.size() * 100);
+bool BakedLightmap::_lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh) {
+ BakeStepUD *bsud = (BakeStepUD *)ud;
+ bool ret = false;
+ if (bsud->func) {
+ ret = bsud->func(bsud->from_percent + p_completion * (bsud->to_percent - bsud->from_percent), p_text, bsud->ud, p_refresh);
}
+ return ret;
+}
- int step = 0;
+void BakedLightmap::_plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle) {
+ for (int i = 0; i < 8; i++) {
+ Vector3i pos = p_cell->offset;
+ uint32_t half_size = p_cell->size / 2;
+ if (i & 1) {
+ pos.x += half_size;
+ }
+ if (i & 2) {
+ pos.y += half_size;
+ }
+ if (i & 4) {
+ pos.z += half_size;
+ }
- int pmc = 0;
+ AABB subcell;
+ subcell.position = Vector3(pos) * p_cell_size;
+ subcell.size = Vector3(half_size, half_size, half_size) * p_cell_size;
- for (List<PlotMesh>::Element *E = mesh_list.front(); E; E = E->next()) {
+ if (!Geometry3D::triangle_box_overlap(subcell.position + subcell.size * 0.5, subcell.size * 0.5, p_triangle)) {
+ continue;
+ }
- if (bake_step_function) {
- bake_step_function(step++, RTR("Plotting Meshes: ") + " (" + itos(pmc + 1) + "/" + itos(mesh_list.size()) + ")");
+ if (p_cell->children[i] == nullptr) {
+ GenProbesOctree *child = memnew(GenProbesOctree);
+ child->offset = pos;
+ child->size = half_size;
+ p_cell->children[i] = child;
}
- pmc++;
- baker.plot_mesh(E->get().local_xform, E->get().mesh, E->get().instance_materials, E->get().override_material);
+ if (half_size > 1) {
+ //still levels missing
+ _plot_triangle_into_octree(p_cell->children[i], p_cell_size, p_triangle);
+ }
}
+}
+
+void BakedLightmap::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector<Vector3> &probe_positions, LocalVector<Vector3> &new_probe_positions, HashMap<Vector3i, bool, Vector3iHash> &positions_used, const AABB &p_bounds) {
+ for (int i = 0; i < 8; i++) {
+ Vector3i pos = p_cell->offset;
+ if (i & 1) {
+ pos.x += p_cell->size;
+ }
+ if (i & 2) {
+ pos.y += p_cell->size;
+ }
+ if (i & 4) {
+ pos.z += p_cell->size;
+ }
+
+ if (p_cell->size == 1 && !positions_used.has(pos)) {
+ //new position to insert!
+ Vector3 real_pos = p_bounds.position + Vector3(pos) * p_cell_size;
+ //see if a user submitted probe is too close
+ int ppcount = probe_positions.size();
+ const Vector3 *pp = probe_positions.ptr();
+ bool exists = false;
+ for (int j = 0; j < ppcount; j++) {
+ if (pp[j].distance_to(real_pos) < CMP_EPSILON) {
+ exists = true;
+ break;
+ }
+ }
- pmc = 0;
- baker.begin_bake_light(Voxelizer::BakeQuality(bake_quality), Voxelizer::BakeMode(bake_mode), propagation, energy);
+ if (!exists) {
+ new_probe_positions.push_back(real_pos);
+ }
- for (List<PlotLight>::Element *E = light_list.front(); E; E = E->next()) {
+ positions_used[pos] = true;
+ }
- if (bake_step_function) {
- bake_step_function(step++, RTR("Plotting Lights:") + " (" + itos(pmc + 1) + "/" + itos(light_list.size()) + ")");
+ if (p_cell->children[i] != nullptr) {
+ _gen_new_positions_from_octree(p_cell->children[i], p_cell_size, probe_positions, new_probe_positions, positions_used, p_bounds);
}
+ }
+}
- pmc++;
- PlotLight pl = E->get();
- switch (pl.light->get_light_type()) {
- case RS::LIGHT_DIRECTIONAL: {
- baker.plot_light_directional(-pl.local_xform.basis.get_axis(2), pl.light->get_color(), pl.light->get_param(Light::PARAM_ENERGY), pl.light->get_param(Light::PARAM_INDIRECT_ENERGY), pl.light->get_bake_mode() == Light::BAKE_ALL);
- } break;
- case RS::LIGHT_OMNI: {
- baker.plot_light_omni(pl.local_xform.origin, pl.light->get_color(), pl.light->get_param(Light::PARAM_ENERGY), pl.light->get_param(Light::PARAM_INDIRECT_ENERGY), pl.light->get_param(Light::PARAM_RANGE), pl.light->get_param(Light::PARAM_ATTENUATION), pl.light->get_bake_mode() == Light::BAKE_ALL);
- } break;
- case RS::LIGHT_SPOT: {
- baker.plot_light_spot(pl.local_xform.origin, pl.local_xform.basis.get_axis(2), pl.light->get_color(), pl.light->get_param(Light::PARAM_ENERGY), pl.light->get_param(Light::PARAM_INDIRECT_ENERGY), pl.light->get_param(Light::PARAM_RANGE), pl.light->get_param(Light::PARAM_ATTENUATION), pl.light->get_param(Light::PARAM_SPOT_ANGLE), pl.light->get_param(Light::PARAM_SPOT_ATTENUATION), pl.light->get_bake_mode() == Light::BAKE_ALL);
+BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_data_path, Lightmapper::BakeStepFunc p_bake_step, void *p_bake_userdata) {
+ if (p_image_data_path == "" && (get_light_data().is_null() || !get_light_data()->get_path().is_resource_file())) {
+ return BAKE_ERROR_NO_SAVE_PATH;
+ }
- } break;
+ if (p_image_data_path == "") {
+ if (get_light_data().is_null()) {
+ return BAKE_ERROR_NO_SAVE_PATH;
+ }
+
+ p_image_data_path = get_light_data()->get_path();
+ if (!p_image_data_path.is_resource_file()) {
+ return BAKE_ERROR_NO_SAVE_PATH;
}
}
- /*if (bake_step_function) {
- bake_step_function(pmc++, RTR("Finishing Plot"));
- }*/
- baker.end_bake();
+ Ref<Lightmapper> lightmapper = Lightmapper::create();
+ ERR_FAIL_COND_V(lightmapper.is_null(), BAKE_ERROR_NO_LIGHTMAPPER);
- Set<String> used_mesh_names;
+ BakeStepUD bsud;
+ bsud.func = p_bake_step;
+ bsud.ud = p_bake_userdata;
+ bsud.from_percent = 0.2;
+ bsud.to_percent = 0.8;
- pmc = 0;
- for (List<PlotMesh>::Element *E = mesh_list.front(); E; E = E->next()) {
+ if (p_bake_step) {
+ p_bake_step(0.0, TTR("Finding meshes, lights and probes"), p_bake_userdata, true);
+ }
+ /* STEP 1, FIND MESHES, LIGHTS AND PROBES */
+ Vector<Lightmapper::MeshData> mesh_data;
+ Vector<LightsFound> lights_found;
+ Vector<Vector3> probes_found;
+ AABB bounds;
+ {
+ Vector<MeshesFound> meshes_found;
+ _find_meshes_and_lights(p_from_node ? p_from_node : get_parent(), meshes_found, lights_found, probes_found);
- String mesh_name = E->get().mesh->get_name();
- if (mesh_name == "" || mesh_name.find(":") != -1 || mesh_name.find("/") != -1) {
- mesh_name = "LightMap";
+ if (meshes_found.size() == 0) {
+ return BAKE_ERROR_NO_MESHES;
}
+ // create mesh data for insert
- if (used_mesh_names.has(mesh_name)) {
- int idx = 2;
- String base = mesh_name;
- while (true) {
- mesh_name = base + itos(idx);
- if (!used_mesh_names.has(mesh_name))
- break;
- idx++;
+ //get the base material textures, help compute altlas size and bounds
+ for (int m_i = 0; m_i < meshes_found.size(); m_i++) {
+ if (p_bake_step) {
+ float p = (float)(m_i) / meshes_found.size();
+ p_bake_step(p * 0.1, vformat(TTR("Preparing geometry %d/%d"), m_i, meshes_found.size()), p_bake_userdata, false);
}
- }
- used_mesh_names.insert(mesh_name);
- pmc++;
- Voxelizer::LightMapData lm;
+ MeshesFound &mf = meshes_found.write[m_i];
- Error err;
- if (bake_step_function) {
- BakeTimeData btd;
- btd.text = RTR("Lighting Meshes: ") + mesh_name + " (" + itos(pmc) + "/" + itos(mesh_list.size()) + ")";
- btd.pass = step;
- btd.last_step = 0;
- err = baker.make_lightmap(E->get().local_xform, E->get().mesh, bake_default_texels_per_unit, lm, _bake_time, &btd);
- if (err != OK) {
- bake_end_function();
- if (err == ERR_SKIP)
- return BAKE_ERROR_USER_ABORTED;
- return BAKE_ERROR_CANT_CREATE_IMAGE;
+ Size2i lightmap_size = mf.mesh->get_lightmap_size_hint() * mf.lightmap_scale;
+ Vector<RID> overrides;
+ overrides.resize(mf.overrides.size());
+ for (int i = 0; i < mf.overrides.size(); i++) {
+ if (mf.overrides[i].is_valid()) {
+ overrides.write[i] = mf.overrides[i]->get_rid();
+ }
}
- step += 100;
- } else {
+ TypedArray<Image> images = RS::get_singleton()->bake_render_uv2(mf.mesh->get_rid(), overrides, lightmap_size);
- err = baker.make_lightmap(E->get().local_xform, E->get().mesh, bake_default_texels_per_unit, lm);
- }
+ ERR_FAIL_COND_V(images.empty(), BAKE_ERROR_CANT_CREATE_IMAGE);
- if (err == OK) {
+ Ref<Image> albedo = images[RS::BAKE_CHANNEL_ALBEDO_ALPHA];
+ Ref<Image> orm = images[RS::BAKE_CHANNEL_ORM];
- Ref<Image> image;
- image.instance();
+ //multiply albedo by metal
- if (hdr) {
+ Lightmapper::MeshData md;
- //just save a regular image
- Vector<uint8_t> data;
- int s = lm.light.size();
- data.resize(lm.light.size() * 2);
- {
+ {
+ Dictionary d;
+ d["path"] = mf.node_path;
+ if (mf.subindex >= 0) {
+ d["subindex"] = mf.subindex;
+ }
+ md.userdata = d;
+ }
- uint8_t* w = data.ptrw();
- const float* r = lm.light.ptr();
- uint16_t *hfw = (uint16_t *)w.ptr();
- for (int i = 0; i < s; i++) {
- hfw[i] = Math::make_half_float(r[i]);
- }
+ {
+ if (albedo->get_format() != Image::FORMAT_RGBA8) {
+ albedo->convert(Image::FORMAT_RGBA8);
+ }
+ if (orm->get_format() != Image::FORMAT_RGBA8) {
+ orm->convert(Image::FORMAT_RGBA8);
+ }
+ Vector<uint8_t> albedo_alpha = albedo->get_data();
+ Vector<uint8_t> orm_data = orm->get_data();
+
+ Vector<uint8_t> albedom;
+ uint32_t len = albedo_alpha.size();
+ albedom.resize(len);
+ const uint8_t *r_aa = albedo_alpha.ptr();
+ const uint8_t *r_orm = orm_data.ptr();
+ uint8_t *w_albedo = albedom.ptrw();
+
+ for (uint32_t i = 0; i < len; i += 4) {
+ w_albedo[i + 0] = uint8_t(CLAMP(float(r_aa[i + 0]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
+ w_albedo[i + 1] = uint8_t(CLAMP(float(r_aa[i + 1]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
+ w_albedo[i + 2] = uint8_t(CLAMP(float(r_aa[i + 2]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
+ w_albedo[i + 3] = 255;
}
- image->create(lm.width, lm.height, false, Image::FORMAT_RGBH, data);
+ md.albedo_on_uv2.instance();
+ md.albedo_on_uv2->create(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom);
+ }
- } else {
+ md.emission_on_uv2 = images[RS::BAKE_CHANNEL_EMISSION];
+ if (md.emission_on_uv2->get_format() != Image::FORMAT_RGBAH) {
+ md.emission_on_uv2->convert(Image::FORMAT_RGBAH);
+ }
- //just save a regular image
- Vector<uint8_t> data;
- int s = lm.light.size();
- data.resize(lm.light.size());
- {
-
- uint8_t* w = data.ptrw();
- const float* r = lm.light.ptr();
- for (int i = 0; i < s; i += 3) {
- Color c(r[i + 0], r[i + 1], r[i + 2]);
- c = c.to_srgb();
- w[i + 0] = CLAMP(c.r * 255, 0, 255);
- w[i + 1] = CLAMP(c.g * 255, 0, 255);
- w[i + 2] = CLAMP(c.b * 255, 0, 255);
- }
+ //get geometry
+
+ Basis normal_xform = mf.xform.basis.inverse().transposed();
+
+ for (int i = 0; i < mf.mesh->get_surface_count(); i++) {
+ if (mf.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
+ continue;
}
+ Array a = mf.mesh->surface_get_arrays(i);
- image->create(lm.width, lm.height, false, Image::FORMAT_RGB8, data);
+ Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
+ const Vector3 *vr = vertices.ptr();
+ Vector<Vector2> uv = a[Mesh::ARRAY_TEX_UV2];
+ const Vector2 *uvr = nullptr;
+ Vector<Vector3> normals = a[Mesh::ARRAY_NORMAL];
+ const Vector3 *nr = nullptr;
+ Vector<int> index = a[Mesh::ARRAY_INDEX];
- //This texture is saved to SRGB for two reasons:
- // 1) first is so it looks better when doing the LINEAR->SRGB conversion (more accurate)
- // 2) So it can be used in the GLES2 backend, which does not support linkear workflow
- }
+ ERR_CONTINUE(uv.size() == 0);
+ ERR_CONTINUE(normals.size() == 0);
- String image_path = save_path.plus_file(mesh_name);
- Ref<Texture2D> texture;
+ uvr = uv.ptr();
+ nr = normals.ptr();
- if (ResourceLoader::import) {
+ int facecount;
+ const int *ir = nullptr;
- bool srgb = false;
- if (false && hdr) {
- //save hdr
+ if (index.size()) {
+ facecount = index.size() / 3;
+ ir = index.ptr();
} else {
- image_path += ".png";
- print_line("image path saving png: " + image_path);
- image->save_png(image_path);
- srgb = true;
+ facecount = vertices.size() / 3;
}
- if (!FileAccess::exists(image_path + ".import")) {
- Ref<ConfigFile> config;
- config.instance();
- config->set_value("remap", "importer", "texture");
- config->set_value("remap", "type", "StreamTexture");
- config->set_value("params", "compress/mode", 2);
- config->set_value("params", "detect_3d", false);
- config->set_value("params", "flags/repeat", false);
- config->set_value("params", "flags/filter", true);
- config->set_value("params", "flags/mipmaps", false);
- config->set_value("params", "flags/srgb", srgb);
-
- config->save(image_path + ".import");
+ for (int j = 0; j < facecount; j++) {
+ uint32_t vidx[3];
+
+ if (ir) {
+ for (int k = 0; k < 3; k++) {
+ vidx[k] = ir[j * 3 + k];
+ }
+ } else {
+ for (int k = 0; k < 3; k++) {
+ vidx[k] = j * 3 + k;
+ }
+ }
+
+ for (int k = 0; k < 3; k++) {
+ Vector3 v = mf.xform.xform(vr[vidx[k]]);
+ if (bounds == AABB()) {
+ bounds.position = v;
+ } else {
+ bounds.expand_to(v);
+ }
+ md.points.push_back(v);
+
+ md.uv2.push_back(uvr[vidx[k]]);
+ md.normal.push_back(normal_xform.xform(nr[vidx[k]]).normalized());
+ }
}
+ }
- ResourceLoader::import(image_path);
- texture = ResourceLoader::load(image_path); //if already loaded, it will be updated on refocus?
- } else {
+ mesh_data.push_back(md);
+ }
+ }
- image_path += ".text";
- Ref<ImageTexture> tex;
- bool set_path = true;
- if (ResourceCache::has(image_path)) {
- tex = Ref<Resource>((Resource *)ResourceCache::get(image_path));
- set_path = false;
- }
+ /* STEP 2, CREATE PROBES */
- if (!tex.is_valid()) {
- tex.instance();
- }
+ if (p_bake_step) {
+ p_bake_step(0.3, TTR("Creating probes"), p_bake_userdata, true);
+ }
- tex->create_from_image(image);
+ //bounds need to include the user probes
+ for (int i = 0; i < probes_found.size(); i++) {
+ bounds.expand_to(probes_found[i]);
+ }
- err = ResourceSaver::save(image_path, tex, ResourceSaver::FLAG_CHANGE_PATH);
- if (set_path) {
- tex->set_path(image_path);
- }
- texture = tex;
+ bounds.grow_by(bounds.size.length() * 0.001);
+
+ if (gen_probes == GENERATE_PROBES_DISABLED) {
+ // generate 8 probes on bound endpoints
+ for (int i = 0; i < 8; i++) {
+ probes_found.push_back(bounds.get_endpoint(i));
+ }
+ } else {
+ // detect probes from geometry
+ static const int subdiv_values[6] = { 0, 4, 8, 16, 32 };
+ int subdiv = subdiv_values[gen_probes];
+
+ float subdiv_cell_size;
+ Vector3i bound_limit;
+ {
+ int longest_axis = bounds.get_longest_axis_index();
+ subdiv_cell_size = bounds.size[longest_axis] / subdiv;
+ int axis_n1 = (longest_axis + 1) % 3;
+ int axis_n2 = (longest_axis + 2) % 3;
+
+ bound_limit[longest_axis] = subdiv;
+ bound_limit[axis_n1] = int(Math::ceil(bounds.size[axis_n1] / subdiv_cell_size));
+ bound_limit[axis_n2] = int(Math::ceil(bounds.size[axis_n2] / subdiv_cell_size));
+ //compensate bounds
+ bounds.size[axis_n1] = bound_limit[axis_n1] * subdiv_cell_size;
+ bounds.size[axis_n2] = bound_limit[axis_n2] * subdiv_cell_size;
+ }
+
+ GenProbesOctree octree;
+ octree.size = subdiv;
+
+ for (int i = 0; i < mesh_data.size(); i++) {
+ if (p_bake_step) {
+ float p = (float)(i) / mesh_data.size();
+ p_bake_step(0.3 + p * 0.1, vformat(TTR("Creating probes from mesh %d/%d"), i, mesh_data.size()), p_bake_userdata, false);
}
- if (err != OK) {
- if (bake_end_function) {
- bake_end_function();
- }
- ERR_FAIL_COND_V(err != OK, BAKE_ERROR_CANT_CREATE_IMAGE);
+
+ for (int j = 0; j < mesh_data[i].points.size(); j += 3) {
+ Vector3 points[3] = { mesh_data[i].points[j + 0] - bounds.position, mesh_data[i].points[j + 1] - bounds.position, mesh_data[i].points[j + 2] - bounds.position };
+ _plot_triangle_into_octree(&octree, subdiv_cell_size, points);
}
+ }
- new_light_data->add_user(E->get().path, texture, E->get().instance_idx);
+ LocalVector<Vector3> new_probe_positions;
+ HashMap<Vector3i, bool, Vector3iHash> positions_used;
+ for (uint32_t i = 0; i < 8; i++) { //insert bounding endpoints
+ Vector3i pos;
+ if (i & 1) {
+ pos.x += bound_limit.x;
+ }
+ if (i & 2) {
+ pos.y += bound_limit.y;
+ }
+ if (i & 4) {
+ pos.z += bound_limit.z;
+ }
+
+ positions_used[pos] = true;
+ Vector3 real_pos = bounds.position + Vector3(pos) * subdiv_cell_size; //use same formula for numerical stability
+ new_probe_positions.push_back(real_pos);
+ }
+ //skip first level, since probes are always added at bounds endpoints anyway (code above this)
+ for (int i = 0; i < 8; i++) {
+ if (octree.children[i]) {
+ _gen_new_positions_from_octree(octree.children[i], subdiv_cell_size, probes_found, new_probe_positions, positions_used, bounds);
+ }
+ }
+
+ for (uint32_t i = 0; i < new_probe_positions.size(); i++) {
+ probes_found.push_back(new_probe_positions[i]);
}
}
- AABB bounds = AABB(-extents, extents * 2);
- new_light_data->set_cell_subdiv(capture_subdiv);
- new_light_data->set_bounds(bounds);
- new_light_data->set_octree(baker.create_capture_octree(capture_subdiv));
+ // Add everything to lightmapper
+ if (p_bake_step) {
+ p_bake_step(0.4, TTR("Preparing Lightmapper"), p_bake_userdata, true);
+ }
+
{
+ for (int i = 0; i < mesh_data.size(); i++) {
+ lightmapper->add_mesh(mesh_data[i]);
+ }
+ for (int i = 0; i < lights_found.size(); i++) {
+ Light3D *light = lights_found[i].light;
+ Transform xf = lights_found[i].xform;
+
+ if (Object::cast_to<DirectionalLight3D>(light)) {
+ DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light);
+ lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE));
+ } else if (Object::cast_to<OmniLight3D>(light)) {
+ OmniLight3D *l = Object::cast_to<OmniLight3D>(light);
+ lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE));
+ } else if (Object::cast_to<SpotLight3D>(light)) {
+ SpotLight3D *l = Object::cast_to<SpotLight3D>(light);
+ lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE));
+ }
+ }
+ for (int i = 0; i < probes_found.size(); i++) {
+ lightmapper->add_probe(probes_found[i]);
+ }
+ }
+
+ Ref<Image> environment_image;
+ Basis environment_transform;
+
+ // Add everything to lightmapper
+ if (environment_mode != ENVIRONMENT_MODE_DISABLED) {
+ if (p_bake_step) {
+ p_bake_step(4.1, TTR("Preparing Environment"), p_bake_userdata, true);
+ }
+
+ environment_transform = get_global_transform().basis;
- float bake_bound_size = bake_bounds.get_longest_axis_size();
- Transform to_bounds;
- to_bounds.basis.scale(Vector3(bake_bound_size, bake_bound_size, bake_bound_size));
- to_bounds.origin = bounds.position;
+ switch (environment_mode) {
+ case ENVIRONMENT_MODE_DISABLED: {
+ //nothing
+ } break;
+ case ENVIRONMENT_MODE_SCENE: {
+ Ref<World3D> world = get_world_3d();
+ if (world.is_valid()) {
+ Ref<Environment> env = world->get_environment();
+ if (env.is_null()) {
+ env = world->get_fallback_environment();
+ }
- Transform to_grid;
- to_grid.basis.scale(Vector3(1 << (capture_subdiv - 1), 1 << (capture_subdiv - 1), 1 << (capture_subdiv - 1)));
+ if (env.is_valid()) {
+ environment_image = RS::get_singleton()->environment_bake_panorama(env->get_rid(), true, Size2i(128, 64));
+ }
+ }
+ } break;
+ case ENVIRONMENT_MODE_CUSTOM_SKY: {
+ if (environment_custom_sky.is_valid()) {
+ environment_image = RS::get_singleton()->sky_bake_panorama(environment_custom_sky->get_rid(), environment_custom_energy, true, Size2i(128, 64));
+ }
- Transform to_cell_space = to_grid * to_bounds.affine_inverse();
- new_light_data->set_cell_space_transform(to_cell_space);
+ } break;
+ case ENVIRONMENT_MODE_CUSTOM_COLOR: {
+ environment_image.instance();
+ environment_image->create(128, 64, false, Image::FORMAT_RGBAF);
+ Color c = environment_custom_color;
+ c.r *= environment_custom_energy;
+ c.g *= environment_custom_energy;
+ c.b *= environment_custom_energy;
+ for (int i = 0; i < 128; i++) {
+ for (int j = 0; j < 64; j++) {
+ environment_image->set_pixel(i, j, c);
+ }
+ }
+
+ } break;
+ }
}
- if (bake_end_function) {
- bake_end_function();
+ Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud);
+
+ if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES) {
+ return BAKE_ERROR_MESHES_INVALID;
}
- //create the data for visual server
+ /* POSTBAKE: Save Textures */
- if (p_create_visual_debug) {
- MultiMeshInstance *mmi = memnew(MultiMeshInstance);
- mmi->set_multimesh(baker.create_debug_multimesh(Voxelizer::DEBUG_LIGHT));
- add_child(mmi);
-#ifdef TOOLS_ENABLED
- if (get_tree()->get_edited_scene_root() == this) {
- mmi->set_owner(this);
- } else {
- mmi->set_owner(get_owner());
+ Ref<TextureLayered> texture;
+ {
+ Vector<Ref<Image>> images;
+ for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) {
+ images.push_back(lightmapper->get_bake_texture(i));
+ }
+ //we assume they are all the same, so lets create a large one for saving
+ Ref<Image> large_image;
+ large_image.instance();
+
+ large_image->create(images[0]->get_width(), images[0]->get_height() * images.size(), false, images[0]->get_format());
+
+ for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) {
+ large_image->blit_rect(images[i], Rect2(0, 0, images[i]->get_width(), images[i]->get_height()), Point2(0, images[i]->get_height() * i));
+ }
+
+ String base_path = p_image_data_path.get_basename() + ".exr";
+
+ Ref<ConfigFile> config;
+
+ config.instance();
+ if (FileAccess::exists(base_path + ".import")) {
+ config->load(base_path + ".import");
+ }
+
+ config->set_value("remap", "importer", "2d_array_texture");
+ config->set_value("remap", "type", "StreamTexture2DArray");
+ if (!config->has_section_key("params", "compress/mode")) {
+ config->set_value("params", "compress/mode", 2); //user may want another compression, so leave it be
+ }
+ config->set_value("params", "compress/channel_pack", 1);
+ config->set_value("params", "mipmaps/generate", false);
+ config->set_value("params", "slices/horizontal", 1);
+ config->set_value("params", "slices/vertical", images.size());
+
+ config->save(base_path + ".import");
+
+ Error err = large_image->save_exr(base_path, false);
+ ERR_FAIL_COND_V(err, BAKE_ERROR_CANT_CREATE_IMAGE);
+ ResourceLoader::import(base_path);
+ Ref<Texture> t = ResourceLoader::load(base_path); //if already loaded, it will be updated on refocus?
+ ERR_FAIL_COND_V(t.is_null(), BAKE_ERROR_CANT_CREATE_IMAGE);
+ texture = t;
+ }
+
+ /* POSTBAKE: Save Light Data */
+
+ Ref<BakedLightmapData> data;
+ if (get_light_data().is_valid()) {
+ data = get_light_data();
+ set_light_data(Ref<BakedLightmapData>()); //clear
+ data->clear();
+ } else {
+ data.instance();
+ }
+
+ data->set_light_texture(texture);
+ data->set_uses_spherical_harmonics(directional);
+
+ for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) {
+ Dictionary d = lightmapper->get_bake_mesh_userdata(i);
+ NodePath np = d["path"];
+ int32_t subindex = -1;
+ if (d.has("subindex")) {
+ subindex = d["subindex"];
+ }
+
+ Rect2 uv_scale = lightmapper->get_bake_mesh_uv_scale(i);
+ int slice_index = lightmapper->get_bake_mesh_texture_slice(i);
+ data->add_user(np, uv_scale, slice_index, subindex);
+ }
+
+ {
+ // create tetrahedrons
+ Vector<Vector3> points;
+ Vector<Color> sh;
+ points.resize(lightmapper->get_bake_probe_count());
+ sh.resize(lightmapper->get_bake_probe_count() * 9);
+ for (int i = 0; i < lightmapper->get_bake_probe_count(); i++) {
+ points.write[i] = lightmapper->get_bake_probe_point(i);
+ Vector<Color> colors = lightmapper->get_bake_probe_sh(i);
+ ERR_CONTINUE(colors.size() != 9);
+ for (int j = 0; j < 9; j++) {
+ sh.write[i * 9 + j] = colors[j];
+ }
+ }
+
+ //Obtain solved simplices
+
+ if (p_bake_step) {
+ p_bake_step(0.8, TTR("Generating Probe Volumes"), p_bake_userdata, true);
}
-#else
- mmi->set_owner(get_owner());
+ Vector<Delaunay3D::OutputSimplex> solved_simplices = Delaunay3D::tetrahedralize(points);
+
+ LocalVector<BSPSimplex> bsp_simplices;
+ LocalVector<Plane> bsp_planes;
+ LocalVector<int32_t> bsp_simplex_indices;
+ PackedInt32Array tetrahedrons;
+
+ for (int i = 0; i < solved_simplices.size(); i++) {
+ //Prepare a special representation of the simplex, which uses a BSP Tree
+ BSPSimplex bsp_simplex;
+ for (int j = 0; j < 4; j++) {
+ bsp_simplex.vertices[j] = solved_simplices[i].points[j];
+ }
+ for (int j = 0; j < 4; j++) {
+ static const int face_order[4][3] = {
+ { 0, 1, 2 },
+ { 0, 2, 3 },
+ { 0, 1, 3 },
+ { 1, 2, 3 }
+ };
+ Vector3 a = points[solved_simplices[i].points[face_order[j][0]]];
+ Vector3 b = points[solved_simplices[i].points[face_order[j][1]]];
+ Vector3 c = points[solved_simplices[i].points[face_order[j][2]]];
+
+ //store planes in an array, but ensure they are reused, to speed up processing
+
+ Plane p(a, b, c);
+ int plane_index = -1;
+ for (uint32_t k = 0; k < bsp_planes.size(); k++) {
+ if (bsp_planes[k].is_equal_approx_any_side(p)) {
+ plane_index = k;
+ break;
+ }
+ }
+
+ if (plane_index == -1) {
+ plane_index = bsp_planes.size();
+ bsp_planes.push_back(p);
+ }
+
+ bsp_simplex.planes[j] = plane_index;
+
+ //also fill simplex array
+ tetrahedrons.push_back(solved_simplices[i].points[j]);
+ }
+
+ bsp_simplex_indices.push_back(bsp_simplices.size());
+ bsp_simplices.push_back(bsp_simplex);
+ }
+
+//#define DEBUG_SIMPLICES_AS_OBJ_FILE
+#ifdef DEBUG_SIMPLICES_AS_OBJ_FILE
+ {
+ FileAccessRef f = FileAccess::open("res://bsp.obj", FileAccess::WRITE);
+ for (uint32_t i = 0; i < bsp_simplices.size(); i++) {
+ f->store_line("o Simplex" + itos(i));
+ for (int j = 0; j < 4; j++) {
+ f->store_line(vformat("v %f %f %f", points[bsp_simplices[i].vertices[j]].x, points[bsp_simplices[i].vertices[j]].y, points[bsp_simplices[i].vertices[j]].z));
+ }
+ static const int face_order[4][3] = {
+ { 1, 2, 3 },
+ { 1, 3, 4 },
+ { 1, 2, 4 },
+ { 2, 3, 4 }
+ };
+
+ for (int j = 0; j < 4; j++) {
+ f->store_line(vformat("f %d %d %d", 4 * i + face_order[j][0], 4 * i + face_order[j][1], 4 * i + face_order[j][2]));
+ }
+ }
+ f->close();
+ }
+#endif
+
+ LocalVector<BSPNode> bsp_nodes;
+ LocalVector<int32_t> planes_tested;
+ planes_tested.resize(bsp_planes.size());
+ for (uint32_t i = 0; i < planes_tested.size(); i++) {
+ planes_tested[i] = 0x7FFFFFFF;
+ }
+
+ if (p_bake_step) {
+ p_bake_step(0.9, TTR("Generating Probe Acceleration Structures"), p_bake_userdata, true);
+ }
+
+ _compute_bsp_tree(points, bsp_planes, planes_tested, bsp_simplices, bsp_simplex_indices, bsp_nodes);
+
+ PackedInt32Array bsp_array;
+ bsp_array.resize(bsp_nodes.size() * 6); // six 32 bits values used for each BSP node
+ {
+ float *fptr = (float *)bsp_array.ptrw();
+ int32_t *iptr = (int32_t *)bsp_array.ptrw();
+ for (uint32_t i = 0; i < bsp_nodes.size(); i++) {
+ fptr[i * 6 + 0] = bsp_nodes[i].plane.normal.x;
+ fptr[i * 6 + 1] = bsp_nodes[i].plane.normal.y;
+ fptr[i * 6 + 2] = bsp_nodes[i].plane.normal.z;
+ fptr[i * 6 + 3] = bsp_nodes[i].plane.d;
+ iptr[i * 6 + 4] = bsp_nodes[i].over;
+ iptr[i * 6 + 5] = bsp_nodes[i].under;
+ }
+//#define DEBUG_BSP_TREE
+#ifdef DEBUG_BSP_TREE
+ FileAccessRef f = FileAccess::open("res://bsp.txt", FileAccess::WRITE);
+ for (uint32_t i = 0; i < bsp_nodes.size(); i++) {
+ f->store_line(itos(i) + " - plane: " + bsp_nodes[i].plane + " over: " + itos(bsp_nodes[i].over) + " under: " + itos(bsp_nodes[i].under));
+ }
#endif
+ }
+
+ /* Obtain the colors from the images, they will be re-created as cubemaps on the server, depending on the driver */
+
+ data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array);
+ /* Compute a BSP tree of the simplices, so it's easy to find the exact one */
+ }
+
+ Error err = ResourceSaver::save(p_image_data_path, data);
+ data->set_path(p_image_data_path);
+
+ if (err != OK) {
+ return BAKE_ERROR_CANT_CREATE_IMAGE;
}
- set_light_data(new_light_data);
+ set_light_data(data);
return BAKE_ERROR_OK;
}
void BakedLightmap::_notification(int p_what) {
- if (p_what == NOTIFICATION_READY) {
-
+ if (p_what == NOTIFICATION_POST_ENTER_TREE) {
if (light_data.is_valid()) {
_assign_lightmaps();
}
- request_ready(); //will need ready again if re-enters tree
}
if (p_what == NOTIFICATION_EXIT_TREE) {
-
if (light_data.is_valid()) {
_clear_lightmaps();
}
@@ -663,24 +1201,20 @@ void BakedLightmap::_notification(int p_what) {
}
void BakedLightmap::_assign_lightmaps() {
-
ERR_FAIL_COND(!light_data.is_valid());
for (int i = 0; i < light_data->get_user_count(); i++) {
- Ref<Texture2D> lightmap = light_data->get_user_lightmap(i);
- ERR_CONTINUE(!lightmap.is_valid());
-
Node *node = get_node(light_data->get_user_path(i));
- int instance_idx = light_data->get_user_instance(i);
+ int instance_idx = light_data->get_user_sub_instance(i);
if (instance_idx >= 0) {
RID instance = node->call("get_bake_mesh_instance", instance_idx);
if (instance.is_valid()) {
- RS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), lightmap->get_rid());
+ RS::get_singleton()->instance_geometry_set_lightmap(instance, get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i));
}
} else {
- VisualInstance *vi = Object::cast_to<VisualInstance>(node);
+ VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(node);
ERR_CONTINUE(!vi);
- RS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), lightmap->get_rid());
+ RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i));
}
}
}
@@ -689,22 +1223,21 @@ void BakedLightmap::_clear_lightmaps() {
ERR_FAIL_COND(!light_data.is_valid());
for (int i = 0; i < light_data->get_user_count(); i++) {
Node *node = get_node(light_data->get_user_path(i));
- int instance_idx = light_data->get_user_instance(i);
+ int instance_idx = light_data->get_user_sub_instance(i);
if (instance_idx >= 0) {
RID instance = node->call("get_bake_mesh_instance", instance_idx);
if (instance.is_valid()) {
- RS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), RID());
+ RS::get_singleton()->instance_geometry_set_lightmap(instance, RID(), Rect2(), 0);
}
} else {
- VisualInstance *vi = Object::cast_to<VisualInstance>(node);
+ VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(node);
ERR_CONTINUE(!vi);
- RS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), RID());
+ RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), RID(), Rect2(), 0);
}
}
}
void BakedLightmap::set_light_data(const Ref<BakedLightmapData> &p_data) {
-
if (light_data.is_valid()) {
if (is_inside_tree()) {
_clear_lightmaps();
@@ -719,146 +1252,231 @@ void BakedLightmap::set_light_data(const Ref<BakedLightmapData> &p_data) {
_assign_lightmaps();
}
}
+
+ update_gizmo();
}
Ref<BakedLightmapData> BakedLightmap::get_light_data() const {
-
return light_data;
}
-void BakedLightmap::_debug_bake() {
- bake(get_parent(), true);
+void BakedLightmap::set_bake_quality(BakeQuality p_quality) {
+ bake_quality = p_quality;
+}
+
+BakedLightmap::BakeQuality BakedLightmap::get_bake_quality() const {
+ return bake_quality;
+}
+
+AABB BakedLightmap::get_aabb() const {
+ return AABB();
+}
+
+Vector<Face3> BakedLightmap::get_faces(uint32_t p_usage_flags) const {
+ return Vector<Face3>();
}
-void BakedLightmap::set_propagation(float p_propagation) {
- propagation = p_propagation;
+void BakedLightmap::set_use_denoiser(bool p_enable) {
+ use_denoiser = p_enable;
}
-float BakedLightmap::get_propagation() const {
+bool BakedLightmap::is_using_denoiser() const {
+ return use_denoiser;
+}
- return propagation;
+void BakedLightmap::set_directional(bool p_enable) {
+ directional = p_enable;
}
-void BakedLightmap::set_energy(float p_energy) {
- energy = p_energy;
+bool BakedLightmap::is_directional() const {
+ return directional;
}
-float BakedLightmap::get_energy() const {
+void BakedLightmap::set_interior(bool p_enable) {
+ interior = p_enable;
+}
- return energy;
+bool BakedLightmap::is_interior() const {
+ return interior;
}
-void BakedLightmap::set_bake_quality(BakeQuality p_quality) {
- bake_quality = p_quality;
+void BakedLightmap::set_environment_mode(EnvironmentMode p_mode) {
+ environment_mode = p_mode;
+ _change_notify();
}
-BakedLightmap::BakeQuality BakedLightmap::get_bake_quality() const {
- return bake_quality;
+BakedLightmap::EnvironmentMode BakedLightmap::get_environment_mode() const {
+ return environment_mode;
}
-void BakedLightmap::set_bake_mode(BakeMode p_mode) {
- bake_mode = p_mode;
+void BakedLightmap::set_environment_custom_sky(const Ref<Sky> &p_sky) {
+ environment_custom_sky = p_sky;
}
-BakedLightmap::BakeMode BakedLightmap::get_bake_mode() const {
- return bake_mode;
+Ref<Sky> BakedLightmap::get_environment_custom_sky() const {
+ return environment_custom_sky;
}
-void BakedLightmap::set_image_path(const String &p_path) {
- image_path = p_path;
+void BakedLightmap::set_environment_custom_color(const Color &p_color) {
+ environment_custom_color = p_color;
}
-String BakedLightmap::get_image_path() const {
- return image_path;
+Color BakedLightmap::get_environment_custom_color() const {
+ return environment_custom_color;
}
-AABB BakedLightmap::get_aabb() const {
- return AABB(-extents, extents * 2);
+void BakedLightmap::set_environment_custom_energy(float p_energy) {
+ environment_custom_energy = p_energy;
}
-Vector<Face3> BakedLightmap::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
+
+float BakedLightmap::get_environment_custom_energy() const {
+ return environment_custom_energy;
}
-void BakedLightmap::_bind_methods() {
+void BakedLightmap::set_bounces(int p_bounces) {
+ ERR_FAIL_COND(p_bounces < 0 || p_bounces > 16);
+ bounces = p_bounces;
+}
- ClassDB::bind_method(D_METHOD("set_light_data", "data"), &BakedLightmap::set_light_data);
- ClassDB::bind_method(D_METHOD("get_light_data"), &BakedLightmap::get_light_data);
+int BakedLightmap::get_bounces() const {
+ return bounces;
+}
+
+void BakedLightmap::set_bias(float p_bias) {
+ ERR_FAIL_COND(p_bias < 0.00001);
+ bias = p_bias;
+}
+
+float BakedLightmap::get_bias() const {
+ return bias;
+}
- ClassDB::bind_method(D_METHOD("set_bake_cell_size", "bake_cell_size"), &BakedLightmap::set_bake_cell_size);
- ClassDB::bind_method(D_METHOD("get_bake_cell_size"), &BakedLightmap::get_bake_cell_size);
+void BakedLightmap::set_max_texture_size(int p_size) {
+ ERR_FAIL_COND(p_size < 2048);
+ max_texture_size = p_size;
+}
+
+int BakedLightmap::get_max_texture_size() const {
+ return max_texture_size;
+}
+
+void BakedLightmap::set_generate_probes(GenerateProbes p_generate_probes) {
+ gen_probes = p_generate_probes;
+}
+
+BakedLightmap::GenerateProbes BakedLightmap::get_generate_probes() const {
+ return gen_probes;
+}
- ClassDB::bind_method(D_METHOD("set_capture_cell_size", "capture_cell_size"), &BakedLightmap::set_capture_cell_size);
- ClassDB::bind_method(D_METHOD("get_capture_cell_size"), &BakedLightmap::get_capture_cell_size);
+void BakedLightmap::_validate_property(PropertyInfo &property) const {
+ if (property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
+ property.usage = 0;
+ }
+ if (property.name == "environment_custom_color" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR) {
+ property.usage = 0;
+ }
+ if (property.name == "environment_custom_energy" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
+ property.usage = 0;
+ }
+}
+
+void BakedLightmap::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_light_data", "data"), &BakedLightmap::set_light_data);
+ ClassDB::bind_method(D_METHOD("get_light_data"), &BakedLightmap::get_light_data);
ClassDB::bind_method(D_METHOD("set_bake_quality", "bake_quality"), &BakedLightmap::set_bake_quality);
ClassDB::bind_method(D_METHOD("get_bake_quality"), &BakedLightmap::get_bake_quality);
- ClassDB::bind_method(D_METHOD("set_bake_mode", "bake_mode"), &BakedLightmap::set_bake_mode);
- ClassDB::bind_method(D_METHOD("get_bake_mode"), &BakedLightmap::get_bake_mode);
+ ClassDB::bind_method(D_METHOD("set_bounces", "bounces"), &BakedLightmap::set_bounces);
+ ClassDB::bind_method(D_METHOD("get_bounces"), &BakedLightmap::get_bounces);
+
+ ClassDB::bind_method(D_METHOD("set_generate_probes", "subdivision"), &BakedLightmap::set_generate_probes);
+ ClassDB::bind_method(D_METHOD("get_generate_probes"), &BakedLightmap::get_generate_probes);
+
+ ClassDB::bind_method(D_METHOD("set_bias", "bias"), &BakedLightmap::set_bias);
+ ClassDB::bind_method(D_METHOD("get_bias"), &BakedLightmap::get_bias);
+
+ ClassDB::bind_method(D_METHOD("set_environment_mode", "mode"), &BakedLightmap::set_environment_mode);
+ ClassDB::bind_method(D_METHOD("get_environment_mode"), &BakedLightmap::get_environment_mode);
- ClassDB::bind_method(D_METHOD("set_extents", "extents"), &BakedLightmap::set_extents);
- ClassDB::bind_method(D_METHOD("get_extents"), &BakedLightmap::get_extents);
+ ClassDB::bind_method(D_METHOD("set_environment_custom_sky", "sky"), &BakedLightmap::set_environment_custom_sky);
+ ClassDB::bind_method(D_METHOD("get_environment_custom_sky"), &BakedLightmap::get_environment_custom_sky);
- ClassDB::bind_method(D_METHOD("set_bake_default_texels_per_unit", "texels"), &BakedLightmap::set_bake_default_texels_per_unit);
- ClassDB::bind_method(D_METHOD("get_bake_default_texels_per_unit"), &BakedLightmap::get_bake_default_texels_per_unit);
+ ClassDB::bind_method(D_METHOD("set_environment_custom_color", "color"), &BakedLightmap::set_environment_custom_color);
+ ClassDB::bind_method(D_METHOD("get_environment_custom_color"), &BakedLightmap::get_environment_custom_color);
- ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &BakedLightmap::set_propagation);
- ClassDB::bind_method(D_METHOD("get_propagation"), &BakedLightmap::get_propagation);
+ ClassDB::bind_method(D_METHOD("set_environment_custom_energy", "energy"), &BakedLightmap::set_environment_custom_energy);
+ ClassDB::bind_method(D_METHOD("get_environment_custom_energy"), &BakedLightmap::get_environment_custom_energy);
- ClassDB::bind_method(D_METHOD("set_energy", "energy"), &BakedLightmap::set_energy);
- ClassDB::bind_method(D_METHOD("get_energy"), &BakedLightmap::get_energy);
+ ClassDB::bind_method(D_METHOD("set_max_texture_size", "max_texture_size"), &BakedLightmap::set_max_texture_size);
+ ClassDB::bind_method(D_METHOD("get_max_texture_size"), &BakedLightmap::get_max_texture_size);
- ClassDB::bind_method(D_METHOD("set_hdr", "hdr"), &BakedLightmap::set_hdr);
- ClassDB::bind_method(D_METHOD("is_hdr"), &BakedLightmap::is_hdr);
+ ClassDB::bind_method(D_METHOD("set_use_denoiser", "use_denoiser"), &BakedLightmap::set_use_denoiser);
+ ClassDB::bind_method(D_METHOD("is_using_denoiser"), &BakedLightmap::is_using_denoiser);
- ClassDB::bind_method(D_METHOD("set_image_path", "image_path"), &BakedLightmap::set_image_path);
- ClassDB::bind_method(D_METHOD("get_image_path"), &BakedLightmap::get_image_path);
+ ClassDB::bind_method(D_METHOD("set_interior", "enable"), &BakedLightmap::set_interior);
+ ClassDB::bind_method(D_METHOD("is_interior"), &BakedLightmap::is_interior);
- ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &BakedLightmap::bake, DEFVAL(Variant()), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("debug_bake"), &BakedLightmap::_debug_bake);
- ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("set_directional", "directional"), &BakedLightmap::set_directional);
+ ClassDB::bind_method(D_METHOD("is_directional"), &BakedLightmap::is_directional);
- ADD_GROUP("Bake", "bake_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_bake_cell_size", "get_bake_cell_size");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_bake_quality", "get_bake_quality");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mode", PROPERTY_HINT_ENUM, "ConeTrace,RayTrace"), "set_bake_mode", "get_bake_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_energy", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_energy", "get_energy");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_hdr"), "set_hdr", "is_hdr");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "bake_extents"), "set_extents", "get_extents");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_default_texels_per_unit"), "set_bake_default_texels_per_unit", "get_bake_default_texels_per_unit");
- ADD_GROUP("Capture", "capture_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "capture_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_capture_cell_size", "get_capture_cell_size");
+ // ClassDB::bind_method(D_METHOD("bake", "from_node"), &BakedLightmap::bake, DEFVAL(Variant()));
+
+ ADD_GROUP("Tweaks", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "quality", PROPERTY_HINT_ENUM, "Low,Medium,High,Ultra"), "set_bake_quality", "get_bake_quality");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "bounces", PROPERTY_HINT_RANGE, "0,16,1"), "set_bounces", "get_bounces");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional"), "set_directional", "is_directional");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size"), "set_max_texture_size", "get_max_texture_size");
+ ADD_GROUP("Environment", "environment_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy");
+ ADD_GROUP("Gen Probes", "generate_probes_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "generate_probes_subdiv", PROPERTY_HINT_ENUM, "Disabled,4,8,16,32"), "set_generate_probes", "get_generate_probes");
ADD_GROUP("Data", "");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "image_path", PROPERTY_HINT_DIR), "set_image_path", "get_image_path");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "BakedLightmapData"), "set_light_data", "get_light_data");
BIND_ENUM_CONSTANT(BAKE_QUALITY_LOW);
BIND_ENUM_CONSTANT(BAKE_QUALITY_MEDIUM);
BIND_ENUM_CONSTANT(BAKE_QUALITY_HIGH);
- BIND_ENUM_CONSTANT(BAKE_MODE_CONE_TRACE);
- BIND_ENUM_CONSTANT(BAKE_MODE_RAY_TRACE);
+ BIND_ENUM_CONSTANT(BAKE_QUALITY_ULTRA);
+
+ BIND_ENUM_CONSTANT(GENERATE_PROBES_DISABLED);
+ BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_4);
+ BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_8);
+ BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_16);
+ BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_32);
BIND_ENUM_CONSTANT(BAKE_ERROR_OK);
+ BIND_ENUM_CONSTANT(BAKE_ERROR_NO_LIGHTMAPPER);
BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SAVE_PATH);
BIND_ENUM_CONSTANT(BAKE_ERROR_NO_MESHES);
+ BIND_ENUM_CONSTANT(BAKE_ERROR_MESHES_INVALID);
BIND_ENUM_CONSTANT(BAKE_ERROR_CANT_CREATE_IMAGE);
BIND_ENUM_CONSTANT(BAKE_ERROR_USER_ABORTED);
+
+ BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_DISABLED);
+ BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_SCENE);
+ BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_SKY);
+ BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_COLOR);
}
BakedLightmap::BakedLightmap() {
-
- extents = Vector3(10, 10, 10);
- bake_default_texels_per_unit = 20;
- bake_cell_size = 0.25;
- capture_cell_size = 0.5;
+ environment_mode = ENVIRONMENT_MODE_DISABLED;
+ environment_custom_color = Color(0.2, 0.7, 1.0);
+ environment_custom_energy = 1.0;
bake_quality = BAKE_QUALITY_MEDIUM;
- bake_mode = BAKE_MODE_CONE_TRACE;
- energy = 1;
- propagation = 1;
- hdr = false;
- image_path = ".";
- set_disable_scale(true);
+ interior = false;
+ directional = false;
+
+ gen_probes = GENERATE_PROBES_DISABLED;
+ use_denoiser = true;
+ bounces = 1;
+ bias = 0.0005;
+ max_texture_size = 16384;
}
-#endif
diff --git a/scene/3d/baked_lightmap.h b/scene/3d/baked_lightmap.h
index bc9e3f55ea..8808569215 100644
--- a/scene/3d/baked_lightmap.h
+++ b/scene/3d/baked_lightmap.h
@@ -28,189 +28,256 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#if 0
-#ifndef BAKED_INDIRECT_LIGHT_H
-#define BAKED_INDIRECT_LIGHT_H
+#ifndef BAKED_LIGHTMAP_H
+#define BAKED_LIGHTMAP_H
-#include "multimesh_instance.h"
-#include "scene/3d/light.h"
-#include "scene/3d/visual_instance.h"
+#include "core/templates/local_vector.h"
+#include "scene/3d/light_3d.h"
+#include "scene/3d/lightmapper.h"
+#include "scene/3d/mesh_instance_3d.h"
+#include "scene/3d/multimesh_instance_3d.h"
+#include "scene/3d/visual_instance_3d.h"
+#include "scene/resources/sky.h"
class BakedLightmapData : public Resource {
GDCLASS(BakedLightmapData, Resource);
+ RES_BASE_EXTENSION("lmbake")
- RID baked_light;
+ Ref<TextureLayered> light_texture;
+
+ bool uses_spherical_harmonics = false;
+ bool interior = false;
+
+ RID lightmap;
AABB bounds;
- float energy;
- int cell_subdiv;
- Transform cell_space_xform;
struct User {
-
NodePath path;
- Ref<Texture2D> lightmap;
- int instance_index;
+ int32_t sub_instance;
+ Rect2 uv_scale;
+ int slice_index;
};
Vector<User> users;
void _set_user_data(const Array &p_data);
Array _get_user_data() const;
+ void _set_probe_data(const Dictionary &p_data);
+ Dictionary _get_probe_data() const;
protected:
static void _bind_methods();
public:
- void set_bounds(const AABB &p_bounds);
- AABB get_bounds() const;
+ void add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance = -1);
+ int get_user_count() const;
+ NodePath get_user_path(int p_user) const;
+ int32_t get_user_sub_instance(int p_user) const;
+ Rect2 get_user_lightmap_uv_scale(int p_user) const;
+ int get_user_lightmap_slice_index(int p_user) const;
+ void clear_users();
- void set_octree(const Vector<uint8_t> &p_octree);
- Vector<uint8_t> get_octree() const;
+ void set_light_texture(const Ref<TextureLayered> &p_light_texture);
+ Ref<TextureLayered> get_light_texture() const;
- void set_cell_space_transform(const Transform &p_xform);
- Transform get_cell_space_transform() const;
+ void set_uses_spherical_harmonics(bool p_enable);
+ bool is_using_spherical_harmonics() const;
- void set_cell_subdiv(int p_cell_subdiv);
- int get_cell_subdiv() const;
+ bool is_interior() const;
- void set_energy(float p_energy);
- float get_energy() const;
+ void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree);
+ PackedVector3Array get_capture_points() const;
+ PackedColorArray get_capture_sh() const;
+ PackedInt32Array get_capture_tetrahedra() const;
+ PackedInt32Array get_capture_bsp_tree() const;
+ AABB get_capture_bounds() const;
- void add_user(const NodePath &p_path, const Ref<Texture2D> &p_lightmap, int p_instance = -1);
- int get_user_count() const;
- NodePath get_user_path(int p_user) const;
- Ref<Texture2D> get_user_lightmap(int p_user) const;
- int get_user_instance(int p_user) const;
- void clear_users();
+ void clear();
- virtual RID get_rid() const;
+ virtual RID get_rid() const override;
BakedLightmapData();
~BakedLightmapData();
};
-class BakedLightmap : public VisualInstance {
- GDCLASS(BakedLightmap, VisualInstance);
+class BakedLightmap : public VisualInstance3D {
+ GDCLASS(BakedLightmap, VisualInstance3D);
public:
enum BakeQuality {
BAKE_QUALITY_LOW,
BAKE_QUALITY_MEDIUM,
- BAKE_QUALITY_HIGH
+ BAKE_QUALITY_HIGH,
+ BAKE_QUALITY_ULTRA,
};
- enum BakeMode {
- BAKE_MODE_CONE_TRACE,
- BAKE_MODE_RAY_TRACE,
+ enum GenerateProbes {
+ GENERATE_PROBES_DISABLED,
+ GENERATE_PROBES_SUBDIV_4,
+ GENERATE_PROBES_SUBDIV_8,
+ GENERATE_PROBES_SUBDIV_16,
+ GENERATE_PROBES_SUBDIV_32,
};
enum BakeError {
BAKE_ERROR_OK,
+ BAKE_ERROR_NO_LIGHTMAPPER,
BAKE_ERROR_NO_SAVE_PATH,
BAKE_ERROR_NO_MESHES,
+ BAKE_ERROR_MESHES_INVALID,
BAKE_ERROR_CANT_CREATE_IMAGE,
- BAKE_ERROR_USER_ABORTED
-
+ BAKE_ERROR_USER_ABORTED,
};
- typedef void (*BakeBeginFunc)(int);
- typedef bool (*BakeStepFunc)(int, const String &);
- typedef void (*BakeEndFunc)();
+ enum EnvironmentMode {
+ ENVIRONMENT_MODE_DISABLED,
+ ENVIRONMENT_MODE_SCENE,
+ ENVIRONMENT_MODE_CUSTOM_SKY,
+ ENVIRONMENT_MODE_CUSTOM_COLOR,
+ };
private:
- float bake_cell_size;
- float capture_cell_size;
- Vector3 extents;
- float bake_default_texels_per_unit;
- float propagation;
- float energy;
BakeQuality bake_quality;
- BakeMode bake_mode;
- bool hdr;
- String image_path;
+ bool use_denoiser;
+ int bounces;
+ float bias;
+ int max_texture_size;
+ bool interior;
+ EnvironmentMode environment_mode;
+ Ref<Sky> environment_custom_sky;
+ Color environment_custom_color;
+ float environment_custom_energy;
+ bool directional;
+ GenerateProbes gen_probes;
Ref<BakedLightmapData> light_data;
- struct PlotMesh {
- Ref<Material> override_material;
- Vector<Ref<Material> > instance_materials;
- Ref<Mesh> mesh;
- Transform local_xform;
- NodePath path;
- int instance_idx;
+ struct LightsFound {
+ Transform xform;
+ Light3D *light;
};
- struct PlotLight {
- Light *light;
- Transform local_xform;
+ struct MeshesFound {
+ Transform xform;
+ NodePath node_path;
+ int32_t subindex;
+ Ref<Mesh> mesh;
+ int32_t lightmap_scale;
+ Vector<Ref<Material>> overrides;
};
- void _find_meshes_and_lights(Node *p_at_node, List<PlotMesh> &plot_meshes, List<PlotLight> &plot_lights);
-
- void _debug_bake();
+ void _find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights, Vector<Vector3> &probes);
void _assign_lightmaps();
void _clear_lightmaps();
- static bool _bake_time(void *ud, float p_secs, float p_progress);
-
struct BakeTimeData {
String text;
int pass;
uint64_t last_step;
};
+ struct BSPSimplex {
+ int vertices[4];
+ int planes[4];
+ };
+
+ struct BSPNode {
+ static const int32_t EMPTY_LEAF = INT32_MIN;
+ Plane plane;
+ int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
+ };
+
+ int _bsp_get_simplex_side(const Vector<Vector3> &p_points, const LocalVector<BSPSimplex> &p_simplices, const Plane &p_plane, uint32_t p_simplex) const;
+ int32_t _compute_bsp_tree(const Vector<Vector3> &p_points, const LocalVector<Plane> &p_planes, LocalVector<int32_t> &planes_tested, const LocalVector<BSPSimplex> &p_simplices, const LocalVector<int32_t> &p_simplex_indices, LocalVector<BSPNode> &bsp_nodes);
+
+ struct BakeStepUD {
+ Lightmapper::BakeStepFunc func;
+ void *ud;
+ float from_percent;
+ float to_percent;
+ };
+
+ static bool _lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh);
+
+ struct GenProbesOctree {
+ Vector3i offset;
+ uint32_t size;
+ GenProbesOctree *children[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+ ~GenProbesOctree() {
+ for (int i = 0; i < 8; i++) {
+ if (children[i] != nullptr) {
+ memdelete(children[i]);
+ }
+ }
+ }
+ };
+
+ struct Vector3iHash {
+ _FORCE_INLINE_ static uint32_t hash(const Vector3i &p_vtx) {
+ uint32_t h = hash_djb2_one_32(p_vtx.x);
+ h = hash_djb2_one_32(p_vtx.y, h);
+ return hash_djb2_one_32(p_vtx.z, h);
+ }
+ };
+
+ void _plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle);
+ void _gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector<Vector3> &probe_positions, LocalVector<Vector3> &new_probe_positions, HashMap<Vector3i, bool, Vector3iHash> &positions_used, const AABB &p_bounds);
+
protected:
+ void _validate_property(PropertyInfo &property) const override;
static void _bind_methods();
void _notification(int p_what);
public:
- static BakeBeginFunc bake_begin_function;
- static BakeStepFunc bake_step_function;
- static BakeEndFunc bake_end_function;
-
void set_light_data(const Ref<BakedLightmapData> &p_data);
Ref<BakedLightmapData> get_light_data() const;
- void set_bake_cell_size(float p_cell_size);
- float get_bake_cell_size() const;
+ void set_bake_quality(BakeQuality p_quality);
+ BakeQuality get_bake_quality() const;
+
+ void set_use_denoiser(bool p_enable);
+ bool is_using_denoiser() const;
- void set_capture_cell_size(float p_cell_size);
- float get_capture_cell_size() const;
+ void set_directional(bool p_enable);
+ bool is_directional() const;
- void set_extents(const Vector3 &p_extents);
- Vector3 get_extents() const;
+ void set_interior(bool p_interior);
+ bool is_interior() const;
- void set_bake_default_texels_per_unit(const float &p_bake_texels_per_unit);
- float get_bake_default_texels_per_unit() const;
+ void set_environment_mode(EnvironmentMode p_mode);
+ EnvironmentMode get_environment_mode() const;
- void set_propagation(float p_propagation);
- float get_propagation() const;
+ void set_environment_custom_sky(const Ref<Sky> &p_sky);
+ Ref<Sky> get_environment_custom_sky() const;
- void set_energy(float p_energy);
- float get_energy() const;
+ void set_environment_custom_color(const Color &p_color);
+ Color get_environment_custom_color() const;
- void set_bake_quality(BakeQuality p_quality);
- BakeQuality get_bake_quality() const;
+ void set_environment_custom_energy(float p_energy);
+ float get_environment_custom_energy() const;
+
+ void set_bounces(int p_bounces);
+ int get_bounces() const;
- void set_bake_mode(BakeMode p_mode);
- BakeMode get_bake_mode() const;
+ void set_bias(float p_bias);
+ float get_bias() const;
- void set_hdr(bool p_enable);
- bool is_hdr() const;
+ void set_max_texture_size(int p_size);
+ int get_max_texture_size() const;
- void set_image_path(const String &p_path);
- String get_image_path() const;
+ void set_generate_probes(GenerateProbes p_generate_probes);
+ GenerateProbes get_generate_probes() const;
- AABB get_aabb() const;
- Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ AABB get_aabb() const override;
+ Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
- BakeError bake(Node *p_from_node, bool p_create_visual_debug = false);
+ BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr);
BakedLightmap();
};
VARIANT_ENUM_CAST(BakedLightmap::BakeQuality);
-VARIANT_ENUM_CAST(BakedLightmap::BakeMode);
+VARIANT_ENUM_CAST(BakedLightmap::GenerateProbes);
VARIANT_ENUM_CAST(BakedLightmap::BakeError);
+VARIANT_ENUM_CAST(BakedLightmap::EnvironmentMode);
-#endif
-#endif // BAKED_INDIRECT_LIGHT_H
+#endif // BAKED_LIGHTMAP_H
diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp
index 825cb39e2d..68303bbfe5 100644
--- a/scene/3d/bone_attachment_3d.cpp
+++ b/scene/3d/bone_attachment_3d.cpp
@@ -31,23 +31,21 @@
#include "bone_attachment_3d.h"
void BoneAttachment3D::_validate_property(PropertyInfo &property) const {
-
if (property.name == "bone_name") {
Skeleton3D *parent = Object::cast_to<Skeleton3D>(get_parent());
if (parent) {
-
String names;
for (int i = 0; i < parent->get_bone_count(); i++) {
- if (i > 0)
+ if (i > 0) {
names += ",";
+ }
names += parent->get_bone_name(i);
}
property.hint = PROPERTY_HINT_ENUM;
property.hint_string = names;
} else {
-
property.hint = PROPERTY_HINT_NONE;
property.hint_string = "";
}
@@ -55,10 +53,8 @@ void BoneAttachment3D::_validate_property(PropertyInfo &property) const {
}
void BoneAttachment3D::_check_bind() {
-
Skeleton3D *sk = Object::cast_to<Skeleton3D>(get_parent());
if (sk) {
-
int idx = sk->find_bone(bone_name);
if (idx != -1) {
sk->bind_child_node_to_bone(idx, this);
@@ -69,12 +65,9 @@ void BoneAttachment3D::_check_bind() {
}
void BoneAttachment3D::_check_unbind() {
-
if (bound) {
-
Skeleton3D *sk = Object::cast_to<Skeleton3D>(get_parent());
if (sk) {
-
int idx = sk->find_bone(bone_name);
if (idx != -1) {
sk->unbind_child_node_from_bone(idx, this);
@@ -85,31 +78,27 @@ void BoneAttachment3D::_check_unbind() {
}
void BoneAttachment3D::set_bone_name(const String &p_name) {
-
- if (is_inside_tree())
+ if (is_inside_tree()) {
_check_unbind();
+ }
bone_name = p_name;
- if (is_inside_tree())
+ if (is_inside_tree()) {
_check_bind();
+ }
}
String BoneAttachment3D::get_bone_name() const {
-
return bone_name;
}
void BoneAttachment3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_ENTER_TREE: {
-
_check_bind();
} break;
case NOTIFICATION_EXIT_TREE: {
-
_check_unbind();
} break;
}
diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h
index d2a3ffec90..70b871430f 100644
--- a/scene/3d/bone_attachment_3d.h
+++ b/scene/3d/bone_attachment_3d.h
@@ -34,7 +34,6 @@
#include "scene/3d/skeleton_3d.h"
class BoneAttachment3D : public Node3D {
-
GDCLASS(BoneAttachment3D, Node3D);
bool bound;
@@ -44,7 +43,7 @@ class BoneAttachment3D : public Node3D {
void _check_unbind();
protected:
- virtual void _validate_property(PropertyInfo &property) const;
+ virtual void _validate_property(PropertyInfo &property) const override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 706c49b43b..191159448a 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -31,24 +31,22 @@
#include "camera_3d.h"
#include "collision_object_3d.h"
-#include "core/engine.h"
+#include "core/config/engine.h"
#include "core/math/camera_matrix.h"
#include "scene/resources/material.h"
#include "scene/resources/surface_tool.h"
+
void Camera3D::_update_audio_listener_state() {
}
void Camera3D::_request_camera_update() {
-
_update_camera();
}
void Camera3D::_update_camera_mode() {
-
force_change = true;
switch (mode) {
case PROJECTION_PERSPECTIVE: {
-
set_perspective(fov, near, far);
} break;
@@ -78,9 +76,9 @@ void Camera3D::_validate_property(PropertyInfo &p_property) const {
}
void Camera3D::_update_camera() {
-
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
RenderingServer::get_singleton()->camera_set_transform(camera, get_camera_transform());
@@ -90,22 +88,20 @@ void Camera3D::_update_camera() {
get_viewport()->_camera_transform_changed_notify();
*/
- if (get_tree()->is_node_being_edited(this) || !is_current())
+ if (get_tree()->is_node_being_edited(this) || !is_current()) {
return;
+ }
get_viewport()->_camera_transform_changed_notify();
- if (get_world().is_valid()) {
- get_world()->_update_camera(this);
+ if (get_world_3d().is_valid()) {
+ get_world_3d()->_update_camera(this);
}
}
void Camera3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_ENTER_WORLD: {
-
// Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD
// and Spatial will handle it first, including clearing its reference to the Viewport,
// therefore making it impossible to subclasses to access it
@@ -113,19 +109,18 @@ void Camera3D::_notification(int p_what) {
ERR_FAIL_COND(!viewport);
bool first_camera = viewport->_camera_add(this);
- if (current || first_camera)
+ if (current || first_camera) {
viewport->_camera_set(this);
+ }
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
-
_request_camera_update();
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
velocity_tracker->update_position(get_global_transform().origin);
}
} break;
case NOTIFICATION_EXIT_WORLD: {
-
if (!get_tree()->is_node_being_edited(this)) {
if (is_current()) {
clear_current();
@@ -144,19 +139,18 @@ void Camera3D::_notification(int p_what) {
} break;
case NOTIFICATION_BECAME_CURRENT: {
if (viewport) {
- viewport->find_world()->_register_camera(this);
+ viewport->find_world_3d()->_register_camera(this);
}
} break;
case NOTIFICATION_LOST_CURRENT: {
if (viewport) {
- viewport->find_world()->_remove_camera(this);
+ viewport->find_world_3d()->_remove_camera(this);
}
} break;
}
}
Transform Camera3D::get_camera_transform() const {
-
Transform tr = get_global_transform().orthonormalized();
tr.origin += tr.basis.get_axis(1) * v_offset;
tr.origin += tr.basis.get_axis(0) * h_offset;
@@ -164,9 +158,9 @@ Transform Camera3D::get_camera_transform() const {
}
void Camera3D::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
-
- if (!force_change && fov == p_fovy_degrees && p_z_near == near && p_z_far == far && mode == PROJECTION_PERSPECTIVE)
+ if (!force_change && fov == p_fovy_degrees && p_z_near == near && p_z_far == far && mode == PROJECTION_PERSPECTIVE) {
return;
+ }
fov = p_fovy_degrees;
near = p_z_near;
@@ -177,10 +171,11 @@ void Camera3D::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_f
update_gizmo();
force_change = false;
}
-void Camera3D::set_orthogonal(float p_size, float p_z_near, float p_z_far) {
- if (!force_change && size == p_size && p_z_near == near && p_z_far == far && mode == PROJECTION_ORTHOGONAL)
+void Camera3D::set_orthogonal(float p_size, float p_z_near, float p_z_far) {
+ if (!force_change && size == p_size && p_z_near == near && p_z_far == far && mode == PROJECTION_ORTHOGONAL) {
return;
+ }
size = p_size;
@@ -194,8 +189,9 @@ void Camera3D::set_orthogonal(float p_size, float p_z_near, float p_z_far) {
}
void Camera3D::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
- if (!force_change && size == p_size && frustum_offset == p_offset && p_z_near == near && p_z_far == far && mode == PROJECTION_FRUSTUM)
+ if (!force_change && size == p_size && frustum_offset == p_offset && p_z_near == near && p_z_far == far && mode == PROJECTION_FRUSTUM) {
return;
+ }
size = p_size;
frustum_offset = p_offset;
@@ -218,16 +214,15 @@ void Camera3D::set_projection(Camera3D::Projection p_mode) {
}
RID Camera3D::get_camera() const {
-
return camera;
};
void Camera3D::make_current() {
-
current = true;
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
get_viewport()->_camera_set(this);
@@ -235,10 +230,10 @@ void Camera3D::make_current() {
}
void Camera3D::clear_current(bool p_enable_next) {
-
current = false;
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
if (get_viewport()->get_camera() == this) {
get_viewport()->_camera_set(nullptr);
@@ -258,27 +253,23 @@ void Camera3D::set_current(bool p_current) {
}
bool Camera3D::is_current() const {
-
if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) {
-
return get_viewport()->get_camera() == this;
- } else
+ } else {
return current;
+ }
}
bool Camera3D::_can_gizmo_scale() const {
-
return false;
}
Vector3 Camera3D::project_ray_normal(const Point2 &p_pos) const {
-
Vector3 ray = project_local_ray_normal(p_pos);
return get_camera_transform().basis.xform(ray).normalized();
};
Vector3 Camera3D::project_local_ray_normal(const Point2 &p_pos) const {
-
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene.");
Size2 viewport_size = get_viewport()->get_camera_rect_size();
@@ -286,7 +277,6 @@ Vector3 Camera3D::project_local_ray_normal(const Point2 &p_pos) const {
Vector3 ray;
if (mode == PROJECTION_ORTHOGONAL) {
-
ray = Vector3(0, 0, -1);
} else {
CameraMatrix cm;
@@ -299,7 +289,6 @@ Vector3 Camera3D::project_local_ray_normal(const Point2 &p_pos) const {
};
Vector3 Camera3D::project_ray_origin(const Point2 &p_pos) const {
-
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene.");
Size2 viewport_size = get_viewport()->get_camera_rect_size();
@@ -307,10 +296,8 @@ Vector3 Camera3D::project_ray_origin(const Point2 &p_pos) const {
ERR_FAIL_COND_V(viewport_size.y == 0, Vector3());
if (mode == PROJECTION_PERSPECTIVE) {
-
return get_camera_transform().origin;
} else {
-
Vector2 pos = cpos / viewport_size;
float vsize, hsize;
if (keep_aspect == KEEP_WIDTH) {
@@ -331,10 +318,9 @@ Vector3 Camera3D::project_ray_origin(const Point2 &p_pos) const {
};
bool Camera3D::is_position_behind(const Vector3 &p_pos) const {
-
Transform t = get_global_transform();
- Vector3 eyedir = -get_global_transform().basis.get_axis(2).normalized();
- return eyedir.dot(p_pos) < (eyedir.dot(t.origin) + near);
+ Vector3 eyedir = -t.basis.get_axis(2).normalized();
+ return eyedir.dot(p_pos - t.origin) < near;
}
Vector<Vector3> Camera3D::get_near_plane_points() const {
@@ -344,10 +330,11 @@ Vector<Vector3> Camera3D::get_near_plane_points() const {
CameraMatrix cm;
- if (mode == PROJECTION_ORTHOGONAL)
+ if (mode == PROJECTION_ORTHOGONAL) {
cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
- else
+ } else {
cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
+ }
Vector3 endpoints[8];
cm.get_endpoints(Transform(), endpoints);
@@ -361,17 +348,17 @@ Vector<Vector3> Camera3D::get_near_plane_points() const {
}
Point2 Camera3D::unproject_position(const Vector3 &p_pos) const {
-
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector2(), "Camera is not inside scene.");
Size2 viewport_size = get_viewport()->get_visible_rect().size;
CameraMatrix cm;
- if (mode == PROJECTION_ORTHOGONAL)
+ if (mode == PROJECTION_ORTHOGONAL) {
cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
- else
+ } else {
cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
+ }
Plane p(get_camera_transform().xform_inv(p_pos), 1.0);
@@ -386,7 +373,6 @@ Point2 Camera3D::unproject_position(const Vector3 &p_pos) const {
}
Vector3 Camera3D::project_position(const Point2 &p_point, float p_z_depth) const {
-
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene.");
if (p_z_depth == 0 && mode != PROJECTION_ORTHOGONAL) {
@@ -396,10 +382,11 @@ Vector3 Camera3D::project_position(const Point2 &p_point, float p_z_depth) const
CameraMatrix cm;
- if (mode == PROJECTION_ORTHOGONAL)
+ if (mode == PROJECTION_ORTHOGONAL) {
cm.set_orthogonal(size, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH);
- else
+ } else {
cm.set_perspective(fov, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH);
+ }
Vector2 vp_he = cm.get_viewport_half_extents();
@@ -414,32 +401,30 @@ Vector3 Camera3D::project_position(const Point2 &p_point, float p_z_depth) const
}
void Camera3D::set_environment(const Ref<Environment> &p_environment) {
-
environment = p_environment;
- if (environment.is_valid())
+ if (environment.is_valid()) {
RS::get_singleton()->camera_set_environment(camera, environment->get_rid());
- else
+ } else {
RS::get_singleton()->camera_set_environment(camera, RID());
+ }
_update_camera_mode();
}
Ref<Environment> Camera3D::get_environment() const {
-
return environment;
}
void Camera3D::set_effects(const Ref<CameraEffects> &p_effects) {
-
effects = p_effects;
- if (effects.is_valid())
+ if (effects.is_valid()) {
RS::get_singleton()->camera_set_camera_effects(camera, effects->get_rid());
- else
+ } else {
RS::get_singleton()->camera_set_camera_effects(camera, RID());
+ }
_update_camera_mode();
}
Ref<CameraEffects> Camera3D::get_effects() const {
-
return effects;
}
@@ -451,14 +436,13 @@ void Camera3D::set_keep_aspect_mode(KeepAspect p_aspect) {
}
Camera3D::KeepAspect Camera3D::get_keep_aspect_mode() const {
-
return keep_aspect;
}
void Camera3D::set_doppler_tracking(DopplerTracking p_tracking) {
-
- if (doppler_tracking == p_tracking)
+ if (doppler_tracking == p_tracking) {
return;
+ }
doppler_tracking = p_tracking;
if (p_tracking != DOPPLER_TRACKING_DISABLED) {
@@ -475,7 +459,6 @@ Camera3D::DopplerTracking Camera3D::get_doppler_tracking() const {
}
void Camera3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("project_ray_normal", "screen_point"), &Camera3D::project_ray_normal);
ClassDB::bind_method(D_METHOD("project_local_ray_normal", "screen_point"), &Camera3D::project_local_ray_normal);
ClassDB::bind_method(D_METHOD("project_ray_origin", "screen_point"), &Camera3D::project_ray_origin);
@@ -536,8 +519,8 @@ void Camera3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1"), "set_fov", "get_fov");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_znear", "get_znear");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_zfar", "get_zfar");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_EXP_RANGE, "0.001,8192,0.001,or_greater"), "set_znear", "get_znear");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_zfar", "get_zfar");
BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE);
BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL);
@@ -552,17 +535,14 @@ void Camera3D::_bind_methods() {
}
float Camera3D::get_fov() const {
-
return fov;
}
float Camera3D::get_size() const {
-
return size;
}
float Camera3D::get_znear() const {
-
return near;
}
@@ -571,12 +551,10 @@ Vector2 Camera3D::get_frustum_offset() const {
}
float Camera3D::get_zfar() const {
-
return far;
}
Camera3D::Projection Camera3D::get_projection() const {
-
return mode;
}
@@ -616,7 +594,6 @@ void Camera3D::set_cull_mask(uint32_t p_layers) {
}
uint32_t Camera3D::get_cull_mask() const {
-
return layers;
}
@@ -635,27 +612,25 @@ bool Camera3D::get_cull_mask_bit(int p_layer) const {
}
Vector<Plane> Camera3D::get_frustum() const {
-
ERR_FAIL_COND_V(!is_inside_world(), Vector<Plane>());
Size2 viewport_size = get_viewport()->get_visible_rect().size;
CameraMatrix cm;
- if (mode == PROJECTION_PERSPECTIVE)
+ if (mode == PROJECTION_PERSPECTIVE) {
cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
- else
+ } else {
cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
+ }
return cm.get_projection_planes(get_camera_transform());
}
void Camera3D::set_v_offset(float p_offset) {
-
v_offset = p_offset;
_update_camera();
}
float Camera3D::get_v_offset() const {
-
return v_offset;
}
@@ -665,20 +640,18 @@ void Camera3D::set_h_offset(float p_offset) {
}
float Camera3D::get_h_offset() const {
-
return h_offset;
}
Vector3 Camera3D::get_doppler_tracked_velocity() const {
-
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
return velocity_tracker->get_tracked_linear_velocity();
} else {
return Vector3();
}
}
-Camera3D::Camera3D() {
+Camera3D::Camera3D() {
camera = RenderingServer::get_singleton()->camera_create();
size = 1;
fov = 0;
@@ -689,7 +662,7 @@ Camera3D::Camera3D() {
viewport = nullptr;
force_change = false;
mode = PROJECTION_PERSPECTIVE;
- set_perspective(70.0, 0.05, 100.0);
+ set_perspective(75.0, 0.05, 100.0);
keep_aspect = KEEP_HEIGHT;
layers = 0xfffff;
v_offset = 0;
@@ -703,7 +676,6 @@ Camera3D::Camera3D() {
}
Camera3D::~Camera3D() {
-
RenderingServer::get_singleton()->free(camera);
}
@@ -712,11 +684,12 @@ Camera3D::~Camera3D() {
void ClippedCamera3D::set_margin(float p_margin) {
margin = p_margin;
}
+
float ClippedCamera3D::get_margin() const {
return margin;
}
-void ClippedCamera3D::set_process_mode(ProcessMode p_mode) {
+void ClippedCamera3D::set_process_mode(ProcessMode p_mode) {
if (process_mode == p_mode) {
return;
}
@@ -724,12 +697,12 @@ void ClippedCamera3D::set_process_mode(ProcessMode p_mode) {
set_process_internal(process_mode == CLIP_PROCESS_IDLE);
set_physics_process_internal(process_mode == CLIP_PROCESS_PHYSICS);
}
+
ClippedCamera3D::ProcessMode ClippedCamera3D::get_process_mode() const {
return process_mode;
}
Transform ClippedCamera3D::get_camera_transform() const {
-
Transform t = Camera3D::get_camera_transform();
t.origin += -t.basis.get_axis(Vector3::AXIS_Z).normalized() * clip_offset;
return t;
@@ -737,13 +710,12 @@ Transform ClippedCamera3D::get_camera_transform() const {
void ClippedCamera3D::_notification(int p_what) {
if (p_what == NOTIFICATION_INTERNAL_PROCESS || p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
-
Node3D *parent = Object::cast_to<Node3D>(get_parent());
if (!parent) {
return;
}
- PhysicsDirectSpaceState3D *dspace = get_world()->get_direct_space_state();
+ PhysicsDirectSpaceState3D *dspace = get_world_3d()->get_direct_space_state();
ERR_FAIL_COND(!dspace); // most likely physics set to threads
Vector3 cam_fw = -get_global_transform().basis.get_axis(Vector3::AXIS_Z).normalized();
@@ -783,9 +755,9 @@ void ClippedCamera3D::_notification(int p_what) {
xf.origin = ray_from;
xf.orthonormalize();
- float csafe, cunsafe;
- if (dspace->cast_motion(pyramid_shape, xf, cam_pos - ray_from, margin, csafe, cunsafe, exclude, collision_mask, clip_to_bodies, clip_to_areas)) {
- clip_offset = cam_pos.distance_to(ray_from + (cam_pos - ray_from) * csafe);
+ float closest_safe = 1.0f, closest_unsafe = 1.0f;
+ if (dspace->cast_motion(pyramid_shape, xf, cam_pos - ray_from, margin, closest_safe, closest_unsafe, exclude, collision_mask, clip_to_bodies, clip_to_areas)) {
+ clip_offset = cam_pos.distance_to(ray_from + (cam_pos - ray_from) * closest_safe);
}
_update_camera();
@@ -797,90 +769,78 @@ void ClippedCamera3D::_notification(int p_what) {
}
void ClippedCamera3D::set_collision_mask(uint32_t p_mask) {
-
collision_mask = p_mask;
}
uint32_t ClippedCamera3D::get_collision_mask() const {
-
return collision_mask;
}
void ClippedCamera3D::set_collision_mask_bit(int p_bit, bool p_value) {
-
uint32_t mask = get_collision_mask();
- if (p_value)
+ if (p_value) {
mask |= 1 << p_bit;
- else
+ } else {
mask &= ~(1 << p_bit);
+ }
set_collision_mask(mask);
}
bool ClippedCamera3D::get_collision_mask_bit(int p_bit) const {
-
return get_collision_mask() & (1 << p_bit);
}
void ClippedCamera3D::add_exception_rid(const RID &p_rid) {
-
exclude.insert(p_rid);
}
void ClippedCamera3D::add_exception(const Object *p_object) {
-
ERR_FAIL_NULL(p_object);
const CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_object);
- if (!co)
+ if (!co) {
return;
+ }
add_exception_rid(co->get_rid());
}
void ClippedCamera3D::remove_exception_rid(const RID &p_rid) {
-
exclude.erase(p_rid);
}
void ClippedCamera3D::remove_exception(const Object *p_object) {
-
ERR_FAIL_NULL(p_object);
const CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_object);
- if (!co)
+ if (!co) {
return;
+ }
remove_exception_rid(co->get_rid());
}
void ClippedCamera3D::clear_exceptions() {
-
exclude.clear();
}
float ClippedCamera3D::get_clip_offset() const {
-
return clip_offset;
}
void ClippedCamera3D::set_clip_to_areas(bool p_clip) {
-
clip_to_areas = p_clip;
}
bool ClippedCamera3D::is_clip_to_areas_enabled() const {
-
return clip_to_areas;
}
void ClippedCamera3D::set_clip_to_bodies(bool p_clip) {
-
clip_to_bodies = p_clip;
}
bool ClippedCamera3D::is_clip_to_bodies_enabled() const {
-
return clip_to_bodies;
}
void ClippedCamera3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_margin", "margin"), &ClippedCamera3D::set_margin);
ClassDB::bind_method(D_METHOD("get_margin"), &ClippedCamera3D::get_margin);
@@ -920,6 +880,7 @@ void ClippedCamera3D::_bind_methods() {
BIND_ENUM_CONSTANT(CLIP_PROCESS_PHYSICS);
BIND_ENUM_CONSTANT(CLIP_PROCESS_IDLE);
}
+
ClippedCamera3D::ClippedCamera3D() {
margin = 0;
clip_offset = 0;
@@ -932,6 +893,7 @@ ClippedCamera3D::ClippedCamera3D() {
clip_to_areas = false;
clip_to_bodies = true;
}
+
ClippedCamera3D::~ClippedCamera3D() {
PhysicsServer3D::get_singleton()->free(pyramid_shape);
}
diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h
index 9a005226cb..04cec92b14 100644
--- a/scene/3d/camera_3d.h
+++ b/scene/3d/camera_3d.h
@@ -34,15 +34,14 @@
#include "scene/3d/node_3d.h"
#include "scene/3d/velocity_tracker_3d.h"
#include "scene/main/window.h"
+#include "scene/resources/camera_effects.h"
#include "scene/resources/environment.h"
class Camera3D : public Node3D {
-
GDCLASS(Camera3D, Node3D);
public:
enum Projection {
-
PROJECTION_PERSPECTIVE,
PROJECTION_ORTHOGONAL,
PROJECTION_FRUSTUM
@@ -97,13 +96,12 @@ protected:
void _update_camera_mode();
void _notification(int p_what);
- virtual void _validate_property(PropertyInfo &p_property) const;
+ virtual void _validate_property(PropertyInfo &p_property) const override;
static void _bind_methods();
public:
enum {
-
NOTIFICATION_BECAME_CURRENT = 50,
NOTIFICATION_LOST_CURRENT = 51
};
@@ -184,7 +182,6 @@ VARIANT_ENUM_CAST(Camera3D::KeepAspect);
VARIANT_ENUM_CAST(Camera3D::DopplerTracking);
class ClippedCamera3D : public Camera3D {
-
GDCLASS(ClippedCamera3D, Camera3D);
public:
@@ -209,7 +206,7 @@ private:
protected:
void _notification(int p_what);
static void _bind_methods();
- virtual Transform get_camera_transform() const;
+ virtual Transform get_camera_transform() const override;
public:
void set_clip_to_areas(bool p_clip);
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index e6cd7bfe7e..356992e922 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -34,52 +34,49 @@
#include "servers/physics_server_3d.h"
void CollisionObject3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_ENTER_WORLD: {
-
- if (area)
+ if (area) {
PhysicsServer3D::get_singleton()->area_set_transform(rid, get_global_transform());
- else
+ } else {
PhysicsServer3D::get_singleton()->body_set_state(rid, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
+ }
- RID space = get_world()->get_space();
+ RID space = get_world_3d()->get_space();
if (area) {
PhysicsServer3D::get_singleton()->area_set_space(rid, space);
- } else
+ } else {
PhysicsServer3D::get_singleton()->body_set_space(rid, space);
+ }
_update_pickable();
//get space
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
-
- if (area)
+ if (area) {
PhysicsServer3D::get_singleton()->area_set_transform(rid, get_global_transform());
- else
+ } else {
PhysicsServer3D::get_singleton()->body_set_state(rid, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
+ }
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
-
_update_pickable();
} break;
case NOTIFICATION_EXIT_WORLD: {
-
if (area) {
PhysicsServer3D::get_singleton()->area_set_space(rid, RID());
- } else
+ } else {
PhysicsServer3D::get_singleton()->body_set_space(rid, RID());
+ }
} break;
}
}
void CollisionObject3D::_input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
-
if (get_script_instance()) {
get_script_instance()->call(SceneStringNames::get_singleton()->_input_event, p_camera, p_input_event, p_pos, p_normal, p_shape);
}
@@ -87,7 +84,6 @@ void CollisionObject3D::_input_event(Node *p_camera, const Ref<InputEvent> &p_in
}
void CollisionObject3D::_mouse_enter() {
-
if (get_script_instance()) {
get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_enter);
}
@@ -95,7 +91,6 @@ void CollisionObject3D::_mouse_enter() {
}
void CollisionObject3D::_mouse_exit() {
-
if (get_script_instance()) {
get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_exit);
}
@@ -103,29 +98,28 @@ void CollisionObject3D::_mouse_exit() {
}
void CollisionObject3D::_update_pickable() {
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
bool pickable = ray_pickable && is_visible_in_tree();
- if (area)
+ if (area) {
PhysicsServer3D::get_singleton()->area_set_ray_pickable(rid, pickable);
- else
+ } else {
PhysicsServer3D::get_singleton()->body_set_ray_pickable(rid, pickable);
+ }
}
void CollisionObject3D::set_ray_pickable(bool p_ray_pickable) {
-
ray_pickable = p_ray_pickable;
_update_pickable();
}
bool CollisionObject3D::is_ray_pickable() const {
-
return ray_pickable;
}
void CollisionObject3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &CollisionObject3D::set_ray_pickable);
ClassDB::bind_method(D_METHOD("is_ray_pickable"), &CollisionObject3D::is_ray_pickable);
ClassDB::bind_method(D_METHOD("set_capture_input_on_drag", "enable"), &CollisionObject3D::set_capture_input_on_drag);
@@ -158,7 +152,6 @@ void CollisionObject3D::_bind_methods() {
}
uint32_t CollisionObject3D::create_shape_owner(Object *p_owner) {
-
ShapeData sd;
uint32_t id;
@@ -176,7 +169,6 @@ uint32_t CollisionObject3D::create_shape_owner(Object *p_owner) {
}
void CollisionObject3D::remove_shape_owner(uint32_t owner) {
-
ERR_FAIL_COND(!shapes.has(owner));
shape_owner_clear_shapes(owner);
@@ -199,21 +191,18 @@ void CollisionObject3D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabl
}
bool CollisionObject3D::is_shape_owner_disabled(uint32_t p_owner) const {
-
ERR_FAIL_COND_V(!shapes.has(p_owner), false);
return shapes[p_owner].disabled;
}
void CollisionObject3D::get_shape_owners(List<uint32_t> *r_owners) {
-
for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
r_owners->push_back(E->key());
}
}
Array CollisionObject3D::_get_shape_owners() {
-
Array ret;
for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
ret.push_back(E->key());
@@ -223,7 +212,6 @@ Array CollisionObject3D::_get_shape_owners() {
}
void CollisionObject3D::shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform) {
-
ERR_FAIL_COND(!shapes.has(p_owner));
ShapeData &sd = shapes[p_owner];
@@ -236,22 +224,20 @@ void CollisionObject3D::shape_owner_set_transform(uint32_t p_owner, const Transf
}
}
}
-Transform CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const {
+Transform CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const {
ERR_FAIL_COND_V(!shapes.has(p_owner), Transform());
return shapes[p_owner].xform;
}
Object *CollisionObject3D::shape_owner_get_owner(uint32_t p_owner) const {
-
ERR_FAIL_COND_V(!shapes.has(p_owner), nullptr);
return shapes[p_owner].owner;
}
void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3D> &p_shape) {
-
ERR_FAIL_COND(!shapes.has(p_owner));
ERR_FAIL_COND(p_shape.is_null());
@@ -268,21 +254,21 @@ void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3
total_subshapes++;
}
-int CollisionObject3D::shape_owner_get_shape_count(uint32_t p_owner) const {
+int CollisionObject3D::shape_owner_get_shape_count(uint32_t p_owner) const {
ERR_FAIL_COND_V(!shapes.has(p_owner), 0);
return shapes[p_owner].shapes.size();
}
-Ref<Shape3D> CollisionObject3D::shape_owner_get_shape(uint32_t p_owner, int p_shape) const {
+Ref<Shape3D> CollisionObject3D::shape_owner_get_shape(uint32_t p_owner, int p_shape) const {
ERR_FAIL_COND_V(!shapes.has(p_owner), Ref<Shape3D>());
ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), Ref<Shape3D>());
return shapes[p_owner].shapes[p_shape].shape;
}
-int CollisionObject3D::shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const {
+int CollisionObject3D::shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const {
ERR_FAIL_COND_V(!shapes.has(p_owner), -1);
ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), -1);
@@ -290,7 +276,6 @@ int CollisionObject3D::shape_owner_get_shape_index(uint32_t p_owner, int p_shape
}
void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) {
-
ERR_FAIL_COND(!shapes.has(p_owner));
ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size());
@@ -315,7 +300,6 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape)
}
void CollisionObject3D::shape_owner_clear_shapes(uint32_t p_owner) {
-
ERR_FAIL_COND(!shapes.has(p_owner));
while (shape_owner_get_shape_count(p_owner) > 0) {
@@ -324,7 +308,6 @@ void CollisionObject3D::shape_owner_clear_shapes(uint32_t p_owner) {
}
uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const {
-
ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0);
for (const Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
@@ -340,7 +323,6 @@ uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const {
}
CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) {
-
rid = p_rid;
area = p_area;
capture_input_on_drag = false;
@@ -357,17 +339,14 @@ CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) {
}
void CollisionObject3D::set_capture_input_on_drag(bool p_capture) {
-
capture_input_on_drag = p_capture;
}
bool CollisionObject3D::get_capture_input_on_drag() const {
-
return capture_input_on_drag;
}
String CollisionObject3D::get_configuration_warning() const {
-
String warning = Node3D::get_configuration_warning();
if (shapes.empty()) {
@@ -381,7 +360,6 @@ String CollisionObject3D::get_configuration_warning() const {
}
CollisionObject3D::CollisionObject3D() {
-
capture_input_on_drag = false;
ray_pickable = true;
set_notify_transform(true);
@@ -391,6 +369,5 @@ CollisionObject3D::CollisionObject3D() {
}
CollisionObject3D::~CollisionObject3D() {
-
PhysicsServer3D::get_singleton()->free(rid);
}
diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h
index 67d3aed3c8..39e7df40a8 100644
--- a/scene/3d/collision_object_3d.h
+++ b/scene/3d/collision_object_3d.h
@@ -35,7 +35,6 @@
#include "scene/resources/shape_3d.h"
class CollisionObject3D : public Node3D {
-
GDCLASS(CollisionObject3D, Node3D);
bool area;
@@ -43,7 +42,6 @@ class CollisionObject3D : public Node3D {
RID rid;
struct ShapeData {
-
Object *owner;
Transform xform;
struct ShapeBase {
@@ -110,7 +108,7 @@ public:
_FORCE_INLINE_ RID get_rid() const { return rid; }
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
CollisionObject3D();
~CollisionObject3D();
diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp
index 66bd903eeb..b8a4ab74ee 100644
--- a/scene/3d/collision_polygon_3d.cpp
+++ b/scene/3d/collision_polygon_3d.cpp
@@ -31,22 +31,25 @@
#include "collision_polygon_3d.h"
#include "collision_object_3d.h"
+#include "core/math/geometry_2d.h"
#include "scene/resources/concave_polygon_shape_3d.h"
#include "scene/resources/convex_polygon_shape_3d.h"
void CollisionPolygon3D::_build_polygon() {
-
- if (!parent)
+ if (!parent) {
return;
+ }
parent->shape_owner_clear_shapes(owner_id);
- if (polygon.size() == 0)
+ if (polygon.size() == 0) {
return;
+ }
- Vector<Vector<Vector2>> decomp = Geometry::decompose_polygon_in_convex(polygon);
- if (decomp.size() == 0)
+ Vector<Vector<Vector2>> decomp = Geometry2D::decompose_polygon_in_convex(polygon);
+ if (decomp.size() == 0) {
return;
+ }
//here comes the sun, lalalala
//decompose concave into multiple convex polygons and add them
@@ -60,7 +63,6 @@ void CollisionPolygon3D::_build_polygon() {
Vector3 *w = cp.ptrw();
int idx = 0;
for (int j = 0; j < cs; j++) {
-
Vector2 d = decomp[i][j];
w[idx++] = Vector3(d.x, d.y, depth * 0.5);
w[idx++] = Vector3(d.x, d.y, -depth * 0.5);
@@ -74,17 +76,15 @@ void CollisionPolygon3D::_build_polygon() {
}
void CollisionPolygon3D::_update_in_shape_owner(bool p_xform_only) {
-
parent->shape_owner_set_transform(owner_id, get_transform());
- if (p_xform_only)
+ if (p_xform_only) {
return;
+ }
parent->shape_owner_set_disabled(owner_id, disabled);
}
void CollisionPolygon3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_PARENTED: {
parent = Object::cast_to<CollisionObject3D>(get_parent());
if (parent) {
@@ -94,14 +94,12 @@ void CollisionPolygon3D::_notification(int p_what) {
}
} break;
case NOTIFICATION_ENTER_TREE: {
-
if (parent) {
_update_in_shape_owner();
}
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
-
if (parent) {
_update_in_shape_owner(true);
}
@@ -118,7 +116,6 @@ void CollisionPolygon3D::_notification(int p_what) {
}
void CollisionPolygon3D::set_polygon(const Vector<Point2> &p_polygon) {
-
polygon = p_polygon;
if (parent) {
_build_polygon();
@@ -128,24 +125,20 @@ void CollisionPolygon3D::set_polygon(const Vector<Point2> &p_polygon) {
}
Vector<Point2> CollisionPolygon3D::get_polygon() const {
-
return polygon;
}
AABB CollisionPolygon3D::get_item_rect() const {
-
return aabb;
}
void CollisionPolygon3D::set_depth(float p_depth) {
-
depth = p_depth;
_build_polygon();
update_gizmo();
}
float CollisionPolygon3D::get_depth() const {
-
return depth;
}
@@ -163,23 +156,30 @@ bool CollisionPolygon3D::is_disabled() const {
}
String CollisionPolygon3D::get_configuration_warning() const {
+ String warning = Node3D::get_configuration_warning();
if (!Object::cast_to<CollisionObject3D>(get_parent())) {
- return TTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape.");
}
if (polygon.empty()) {
- return TTR("An empty CollisionPolygon3D has no effect on collision.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("An empty CollisionPolygon3D has no effect on collision.");
}
- return String();
+ return warning;
}
bool CollisionPolygon3D::_is_editable_3d_polygon() const {
return true;
}
-void CollisionPolygon3D::_bind_methods() {
+void CollisionPolygon3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CollisionPolygon3D::set_depth);
ClassDB::bind_method(D_METHOD("get_depth"), &CollisionPolygon3D::get_depth);
@@ -197,7 +197,6 @@ void CollisionPolygon3D::_bind_methods() {
}
CollisionPolygon3D::CollisionPolygon3D() {
-
aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
depth = 1.0;
set_notify_local_transform(true);
diff --git a/scene/3d/collision_polygon_3d.h b/scene/3d/collision_polygon_3d.h
index 256aee3d7e..bab85b6011 100644
--- a/scene/3d/collision_polygon_3d.h
+++ b/scene/3d/collision_polygon_3d.h
@@ -36,7 +36,6 @@
class CollisionObject3D;
class CollisionPolygon3D : public Node3D {
-
GDCLASS(CollisionPolygon3D, Node3D);
protected:
@@ -71,7 +70,7 @@ public:
virtual AABB get_item_rect() const;
- String get_configuration_warning() const;
+ String get_configuration_warning() const override;
CollisionPolygon3D();
};
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp
index a66e84ac3c..e1c691b89a 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -44,39 +44,48 @@
//TODO: Implement CylinderShape and HeightMapShape?
-void CollisionShape3D::make_convex_from_brothers() {
-
+void CollisionShape3D::make_convex_from_siblings() {
Node *p = get_parent();
- if (!p)
+ if (!p) {
return;
+ }
- for (int i = 0; i < p->get_child_count(); i++) {
+ Vector<Vector3> vertices;
+ for (int i = 0; i < p->get_child_count(); i++) {
Node *n = p->get_child(i);
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(n);
if (mi) {
-
Ref<Mesh> m = mi->get_mesh();
if (m.is_valid()) {
-
- Ref<Shape3D> s = m->create_convex_shape();
- set_shape(s);
+ for (int j = 0; j < m->get_surface_count(); j++) {
+ Array a = m->surface_get_arrays(j);
+ if (!a.empty()) {
+ Vector<Vector3> v = a[RenderingServer::ARRAY_VERTEX];
+ for (int k = 0; k < v.size(); k++) {
+ vertices.append(mi->get_transform().xform(v[k]));
+ }
+ }
+ }
}
}
}
+
+ Ref<ConvexPolygonShape3D> shape = memnew(ConvexPolygonShape3D);
+ shape->set_points(vertices);
+ set_shape(shape);
}
void CollisionShape3D::_update_in_shape_owner(bool p_xform_only) {
parent->shape_owner_set_transform(owner_id, get_transform());
- if (p_xform_only)
+ if (p_xform_only) {
return;
+ }
parent->shape_owner_set_disabled(owner_id, disabled);
}
void CollisionShape3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_PARENTED: {
parent = Object::cast_to<CollisionObject3D>(get_parent());
if (parent) {
@@ -111,41 +120,48 @@ void CollisionShape3D::_notification(int p_what) {
}
void CollisionShape3D::resource_changed(RES res) {
-
update_gizmo();
}
String CollisionShape3D::get_configuration_warning() const {
+ String warning = Node3D::get_configuration_warning();
if (!Object::cast_to<CollisionObject3D>(get_parent())) {
- return TTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape.");
}
if (!shape.is_valid()) {
- return TTR("A shape must be provided for CollisionShape3D to function. Please create a shape resource for it.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("A shape must be provided for CollisionShape3D to function. Please create a shape resource for it.");
}
- if (Object::cast_to<RigidBody3D>(get_parent())) {
- if (Object::cast_to<ConcavePolygonShape3D>(*shape)) {
- if (Object::cast_to<RigidBody3D>(get_parent())->get_mode() != RigidBody3D::MODE_STATIC) {
- return TTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static.");
- }
+ if (shape.is_valid() &&
+ Object::cast_to<RigidBody3D>(get_parent()) &&
+ Object::cast_to<ConcavePolygonShape3D>(*shape) &&
+ Object::cast_to<RigidBody3D>(get_parent())->get_mode() != RigidBody3D::MODE_STATIC) {
+ if (!warning.empty()) {
+ warning += "\n\n";
}
+ warning += TTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static.");
}
- return String();
+ return warning;
}
void CollisionShape3D::_bind_methods() {
-
//not sure if this should do anything
ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &CollisionShape3D::resource_changed);
ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape3D::set_shape);
ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape3D::get_shape);
ClassDB::bind_method(D_METHOD("set_disabled", "enable"), &CollisionShape3D::set_disabled);
ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape3D::is_disabled);
- ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape3D::make_convex_from_brothers);
- ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("make_convex_from_siblings"), &CollisionShape3D::make_convex_from_siblings);
+ ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_siblings", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ClassDB::bind_method(D_METHOD("_update_debug_shape"), &CollisionShape3D::_update_debug_shape);
@@ -154,7 +170,6 @@ void CollisionShape3D::_bind_methods() {
}
void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) {
-
if (!shape.is_null()) {
shape->unregister_owner(this);
shape->disconnect("changed", callable_mp(this, &CollisionShape3D::_shape_changed));
@@ -172,18 +187,17 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) {
}
}
- if (is_inside_tree())
+ if (is_inside_tree()) {
_shape_changed();
+ }
update_configuration_warning();
}
Ref<Shape3D> CollisionShape3D::get_shape() const {
-
return shape;
}
void CollisionShape3D::set_disabled(bool p_disabled) {
-
disabled = p_disabled;
update_gizmo();
if (parent) {
@@ -192,12 +206,10 @@ void CollisionShape3D::set_disabled(bool p_disabled) {
}
bool CollisionShape3D::is_disabled() const {
-
return disabled;
}
CollisionShape3D::CollisionShape3D() {
-
//indicator = RenderingServer::get_singleton()->mesh_create();
disabled = false;
debug_shape = nullptr;
@@ -207,8 +219,9 @@ CollisionShape3D::CollisionShape3D() {
}
CollisionShape3D::~CollisionShape3D() {
- if (!shape.is_null())
+ if (!shape.is_null()) {
shape->unregister_owner(this);
+ }
//RenderingServer::get_singleton()->free(indicator);
}
@@ -221,8 +234,9 @@ void CollisionShape3D::_update_debug_shape() {
}
Ref<Shape3D> s = get_shape();
- if (s.is_null())
+ if (s.is_null()) {
return;
+ }
Ref<Mesh> mesh = s->get_debug_mesh();
MeshInstance3D *mi = memnew(MeshInstance3D);
diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h
index 8515d292af..35f40d27b1 100644
--- a/scene/3d/collision_shape_3d.h
+++ b/scene/3d/collision_shape_3d.h
@@ -35,7 +35,6 @@
#include "scene/resources/shape_3d.h"
class CollisionObject3D;
class CollisionShape3D : public Node3D {
-
GDCLASS(CollisionShape3D, Node3D);
OBJ_CATEGORY("3D Physics Nodes");
@@ -61,7 +60,7 @@ protected:
static void _bind_methods();
public:
- void make_convex_from_brothers();
+ void make_convex_from_siblings();
void set_shape(const Ref<Shape3D> &p_shape);
Ref<Shape3D> get_shape() const;
@@ -69,7 +68,7 @@ public:
void set_disabled(bool p_disabled);
bool is_disabled() const;
- String get_configuration_warning() const;
+ String get_configuration_warning() const override;
CollisionShape3D();
~CollisionShape3D();
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 12c105b0f4..c977e0d4aa 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -36,31 +36,30 @@
#include "servers/rendering_server.h"
AABB CPUParticles3D::get_aabb() const {
-
return AABB();
}
-Vector<Face3> CPUParticles3D::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> CPUParticles3D::get_faces(uint32_t p_usage_flags) const {
return Vector<Face3>();
}
void CPUParticles3D::set_emitting(bool p_emitting) {
-
- if (emitting == p_emitting)
+ if (emitting == p_emitting) {
return;
+ }
emitting = p_emitting;
if (emitting) {
set_process_internal(true);
// first update before rendering to avoid one frame delay after emitting starts
- if (time == 0)
+ if (time == 0) {
_update_internal();
+ }
}
}
void CPUParticles3D::set_amount(int p_amount) {
-
ERR_FAIL_COND_MSG(p_amount < 1, "Amount of particles must be greater than 0.");
particles.resize(p_amount);
@@ -69,6 +68,7 @@ void CPUParticles3D::set_amount(int p_amount) {
for (int i = 0; i < p_amount; i++) {
w[i].active = false;
+ w[i].custom[3] = 0.0; // Make sure w component isn't garbage data
}
}
@@ -77,98 +77,89 @@ void CPUParticles3D::set_amount(int p_amount) {
particle_order.resize(p_amount);
}
-void CPUParticles3D::set_lifetime(float p_lifetime) {
+void CPUParticles3D::set_lifetime(float p_lifetime) {
ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0.");
lifetime = p_lifetime;
}
void CPUParticles3D::set_one_shot(bool p_one_shot) {
-
one_shot = p_one_shot;
}
void CPUParticles3D::set_pre_process_time(float p_time) {
-
pre_process_time = p_time;
}
-void CPUParticles3D::set_explosiveness_ratio(float p_ratio) {
+void CPUParticles3D::set_explosiveness_ratio(float p_ratio) {
explosiveness_ratio = p_ratio;
}
-void CPUParticles3D::set_randomness_ratio(float p_ratio) {
+void CPUParticles3D::set_randomness_ratio(float p_ratio) {
randomness_ratio = p_ratio;
}
-void CPUParticles3D::set_lifetime_randomness(float p_random) {
+void CPUParticles3D::set_lifetime_randomness(float p_random) {
lifetime_randomness = p_random;
}
-void CPUParticles3D::set_use_local_coordinates(bool p_enable) {
+void CPUParticles3D::set_use_local_coordinates(bool p_enable) {
local_coords = p_enable;
}
-void CPUParticles3D::set_speed_scale(float p_scale) {
+void CPUParticles3D::set_speed_scale(float p_scale) {
speed_scale = p_scale;
}
bool CPUParticles3D::is_emitting() const {
-
return emitting;
}
-int CPUParticles3D::get_amount() const {
+int CPUParticles3D::get_amount() const {
return particles.size();
}
-float CPUParticles3D::get_lifetime() const {
+float CPUParticles3D::get_lifetime() const {
return lifetime;
}
-bool CPUParticles3D::get_one_shot() const {
+bool CPUParticles3D::get_one_shot() const {
return one_shot;
}
float CPUParticles3D::get_pre_process_time() const {
-
return pre_process_time;
}
-float CPUParticles3D::get_explosiveness_ratio() const {
+float CPUParticles3D::get_explosiveness_ratio() const {
return explosiveness_ratio;
}
-float CPUParticles3D::get_randomness_ratio() const {
+float CPUParticles3D::get_randomness_ratio() const {
return randomness_ratio;
}
-float CPUParticles3D::get_lifetime_randomness() const {
+float CPUParticles3D::get_lifetime_randomness() const {
return lifetime_randomness;
}
bool CPUParticles3D::get_use_local_coordinates() const {
-
return local_coords;
}
float CPUParticles3D::get_speed_scale() const {
-
return speed_scale;
}
void CPUParticles3D::set_draw_order(DrawOrder p_order) {
-
draw_order = p_order;
}
CPUParticles3D::DrawOrder CPUParticles3D::get_draw_order() const {
-
return draw_order;
}
void CPUParticles3D::set_mesh(const Ref<Mesh> &p_mesh) {
-
mesh = p_mesh;
if (mesh.is_valid()) {
RS::get_singleton()->multimesh_set_mesh(multimesh, mesh->get_rid());
@@ -178,7 +169,6 @@ void CPUParticles3D::set_mesh(const Ref<Mesh> &p_mesh) {
}
Ref<Mesh> CPUParticles3D::get_mesh() const {
-
return mesh;
}
@@ -199,8 +189,7 @@ bool CPUParticles3D::get_fractional_delta() const {
}
String CPUParticles3D::get_configuration_warning() const {
-
- String warnings;
+ String warnings = GeometryInstance3D::get_configuration_warning();
bool mesh_found = false;
bool anim_material_found = false;
@@ -219,15 +208,17 @@ String CPUParticles3D::get_configuration_warning() const {
anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES);
if (!mesh_found) {
- if (warnings != String())
+ if (warnings != String()) {
warnings += "\n";
+ }
warnings += "- " + TTR("Nothing is visible because no mesh has been assigned.");
}
if (!anim_material_found && (get_param(PARAM_ANIM_SPEED) != 0.0 || get_param(PARAM_ANIM_OFFSET) != 0.0 ||
get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid())) {
- if (warnings != String())
+ if (warnings != String()) {
warnings += "\n";
+ }
warnings += "- " + TTR("CPUParticles3D animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\".");
}
@@ -235,7 +226,6 @@ String CPUParticles3D::get_configuration_warning() const {
}
void CPUParticles3D::restart() {
-
time = 0;
inactive_time = 0;
frame_remainder = 0;
@@ -255,71 +245,63 @@ void CPUParticles3D::restart() {
}
void CPUParticles3D::set_direction(Vector3 p_direction) {
-
direction = p_direction;
}
Vector3 CPUParticles3D::get_direction() const {
-
return direction;
}
void CPUParticles3D::set_spread(float p_spread) {
-
spread = p_spread;
}
float CPUParticles3D::get_spread() const {
-
return spread;
}
void CPUParticles3D::set_flatness(float p_flatness) {
-
flatness = p_flatness;
}
-float CPUParticles3D::get_flatness() const {
+float CPUParticles3D::get_flatness() const {
return flatness;
}
void CPUParticles3D::set_param(Parameter p_param, float p_value) {
-
ERR_FAIL_INDEX(p_param, PARAM_MAX);
parameters[p_param] = p_value;
}
-float CPUParticles3D::get_param(Parameter p_param) const {
+float CPUParticles3D::get_param(Parameter p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return parameters[p_param];
}
void CPUParticles3D::set_param_randomness(Parameter p_param, float p_value) {
-
ERR_FAIL_INDEX(p_param, PARAM_MAX);
randomness[p_param] = p_value;
}
-float CPUParticles3D::get_param_randomness(Parameter p_param) const {
+float CPUParticles3D::get_param_randomness(Parameter p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return randomness[p_param];
}
static void _adjust_curve_range(const Ref<Curve> &p_curve, float p_min, float p_max) {
-
Ref<Curve> curve = p_curve;
- if (!curve.is_valid())
+ if (!curve.is_valid()) {
return;
+ }
curve->ensure_default_setup(p_min, p_max);
}
void CPUParticles3D::set_param_curve(Parameter p_param, const Ref<Curve> &p_curve) {
-
ERR_FAIL_INDEX(p_param, PARAM_MAX);
curve_parameters[p_param] = p_curve;
@@ -350,7 +332,6 @@ void CPUParticles3D::set_param_curve(Parameter p_param, const Ref<Curve> &p_curv
_adjust_curve_range(p_curve, -360, 360);
} break;
case PARAM_SCALE: {
-
} break;
case PARAM_HUE_VARIATION: {
_adjust_curve_range(p_curve, -1, 1);
@@ -364,30 +345,26 @@ void CPUParticles3D::set_param_curve(Parameter p_param, const Ref<Curve> &p_curv
}
}
}
-Ref<Curve> CPUParticles3D::get_param_curve(Parameter p_param) const {
+Ref<Curve> CPUParticles3D::get_param_curve(Parameter p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Curve>());
return curve_parameters[p_param];
}
void CPUParticles3D::set_color(const Color &p_color) {
-
color = p_color;
}
Color CPUParticles3D::get_color() const {
-
return color;
}
void CPUParticles3D::set_color_ramp(const Ref<Gradient> &p_ramp) {
-
color_ramp = p_ramp;
}
Ref<Gradient> CPUParticles3D::get_color_ramp() const {
-
return color_ramp;
}
@@ -410,67 +387,58 @@ void CPUParticles3D::set_emission_shape(EmissionShape p_shape) {
}
void CPUParticles3D::set_emission_sphere_radius(float p_radius) {
-
emission_sphere_radius = p_radius;
}
void CPUParticles3D::set_emission_box_extents(Vector3 p_extents) {
-
emission_box_extents = p_extents;
}
void CPUParticles3D::set_emission_points(const Vector<Vector3> &p_points) {
-
emission_points = p_points;
}
void CPUParticles3D::set_emission_normals(const Vector<Vector3> &p_normals) {
-
emission_normals = p_normals;
}
void CPUParticles3D::set_emission_colors(const Vector<Color> &p_colors) {
-
emission_colors = p_colors;
}
float CPUParticles3D::get_emission_sphere_radius() const {
-
return emission_sphere_radius;
}
-Vector3 CPUParticles3D::get_emission_box_extents() const {
+Vector3 CPUParticles3D::get_emission_box_extents() const {
return emission_box_extents;
}
-Vector<Vector3> CPUParticles3D::get_emission_points() const {
+Vector<Vector3> CPUParticles3D::get_emission_points() const {
return emission_points;
}
-Vector<Vector3> CPUParticles3D::get_emission_normals() const {
+Vector<Vector3> CPUParticles3D::get_emission_normals() const {
return emission_normals;
}
Vector<Color> CPUParticles3D::get_emission_colors() const {
-
return emission_colors;
}
CPUParticles3D::EmissionShape CPUParticles3D::get_emission_shape() const {
return emission_shape;
}
-void CPUParticles3D::set_gravity(const Vector3 &p_gravity) {
+void CPUParticles3D::set_gravity(const Vector3 &p_gravity) {
gravity = p_gravity;
}
Vector3 CPUParticles3D::get_gravity() const {
-
return gravity;
}
void CPUParticles3D::_validate_property(PropertyInfo &property) const {
-
if (property.name == "color" && color_ramp.is_valid()) {
property.usage = 0;
}
@@ -497,7 +465,6 @@ void CPUParticles3D::_validate_property(PropertyInfo &property) const {
}
static uint32_t idhash(uint32_t x) {
-
x = ((x >> uint32_t(16)) ^ x) * uint32_t(0x45d9f3b);
x = ((x >> uint32_t(16)) ^ x) * uint32_t(0x45d9f3b);
x = (x >> uint32_t(16)) ^ x;
@@ -507,18 +474,19 @@ static uint32_t idhash(uint32_t x) {
static float rand_from_seed(uint32_t &seed) {
int k;
int s = int(seed);
- if (s == 0)
+ if (s == 0) {
s = 305420679;
+ }
k = s / 127773;
s = 16807 * (s - k * 127773) - 2836 * k;
- if (s < 0)
+ if (s < 0) {
s += 2147483647;
+ }
seed = uint32_t(s);
return float(seed % uint32_t(65536)) / 65535.0;
}
void CPUParticles3D::_update_internal() {
-
if (particles.size() == 0 || !is_visible_in_tree()) {
_set_redraw(false);
return;
@@ -546,12 +514,12 @@ void CPUParticles3D::_update_internal() {
bool processed = false;
if (time == 0 && pre_process_time > 0.0) {
-
float frame_time;
- if (fixed_fps > 0)
+ if (fixed_fps > 0) {
frame_time = 1.0 / fixed_fps;
- else
+ } else {
frame_time = 1.0 / 30.0;
+ }
float todo = pre_process_time;
@@ -593,7 +561,6 @@ void CPUParticles3D::_update_internal() {
}
void CPUParticles3D::_particles_process(float p_delta) {
-
p_delta *= speed_scale;
int pcount = particles.size();
@@ -622,11 +589,11 @@ void CPUParticles3D::_particles_process(float p_delta) {
float system_phase = time / lifetime;
for (int i = 0; i < pcount; i++) {
-
Particle &p = parray[i];
- if (!emitting && !p.active)
+ if (!emitting && !p.active) {
continue;
+ }
float local_delta = p_delta;
@@ -680,7 +647,6 @@ void CPUParticles3D::_particles_process(float p_delta) {
}
if (restart) {
-
if (!emitting) {
p.active = false;
continue;
@@ -749,10 +715,10 @@ void CPUParticles3D::_particles_process(float p_delta) {
} break;
case EMISSION_SHAPE_POINTS:
case EMISSION_SHAPE_DIRECTED_POINTS: {
-
int pc = emission_points.size();
- if (pc == 0)
+ if (pc == 0) {
break;
+ }
int random_idx = Math::rand() % pc;
@@ -760,13 +726,15 @@ void CPUParticles3D::_particles_process(float p_delta) {
if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS && emission_normals.size() == pc) {
if (flags[FLAG_DISABLE_Z]) {
- /*
- mat2 rotm;
- ";
- rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy;
- rotm[1] = rotm[0].yx * vec2(1.0, -1.0);
- VELOCITY.xy = rotm * VELOCITY.xy;
- */
+ Vector3 normal = emission_normals.get(random_idx);
+ Vector2 normal_2d(normal.x, normal.y);
+ Transform2D m2;
+ m2.set_axis(0, normal_2d);
+ m2.set_axis(1, normal_2d.tangent());
+ Vector2 velocity_2d(p.velocity.x, p.velocity.y);
+ velocity_2d = m2.basis_xform(velocity_2d);
+ p.velocity.x = velocity_2d.x;
+ p.velocity.y = velocity_2d.y;
} else {
Vector3 normal = emission_normals.get(random_idx);
Vector3 v0 = Math::abs(normal.z) < 0.999 ? Vector3(0.0, 0.0, 1.0) : Vector3(0, 1.0, 0.0);
@@ -804,7 +772,6 @@ void CPUParticles3D::_particles_process(float p_delta) {
} else if (p.time > p.lifetime) {
p.active = false;
} else {
-
uint32_t alt_seed = p.seed;
p.time += local_delta;
@@ -874,7 +841,6 @@ void CPUParticles3D::_particles_process(float p_delta) {
force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector3();
//apply tangential acceleration;
if (flags[FLAG_DISABLE_Z]) {
-
Vector2 yx = Vector2(diff.y, diff.x);
Vector2 yx2 = (yx * Vector2(-1.0, 1.0)).normalized();
force += yx.length() > 0.0 ? Vector3(yx2.x, yx2.y, 0.0) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3();
@@ -902,7 +868,6 @@ void CPUParticles3D::_particles_process(float p_delta) {
p.velocity = p.velocity.normalized() * tex_linear_velocity;
}
if (parameters[PARAM_DAMPING] + tex_damping > 0.0) {
-
float v = p.velocity.length();
float damp = (parameters[PARAM_DAMPING] + tex_damping) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_DAMPING]);
v -= damp * local_delta;
@@ -959,7 +924,6 @@ void CPUParticles3D::_particles_process(float p_delta) {
p.color *= p.base_color;
if (flags[FLAG_DISABLE_Z]) {
-
if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) {
if (p.velocity.length() > 0.0) {
p.transform.basis.set_axis(1, p.velocity.normalized());
@@ -1003,7 +967,9 @@ void CPUParticles3D::_particles_process(float p_delta) {
//scale by scale
float base_scale = tex_scale * Math::lerp(parameters[PARAM_SCALE], 1.0f, p.scale_rand * randomness[PARAM_SCALE]);
- if (base_scale < 0.000001) base_scale = 0.000001;
+ if (base_scale < 0.000001) {
+ base_scale = 0.000001;
+ }
p.transform.basis.scale(Vector3(1, 1, 1) * base_scale);
@@ -1045,7 +1011,6 @@ void CPUParticles3D::_update_particle_data_buffer() {
Vector3 dir = c->get_global_transform().basis.get_axis(2); //far away to close
if (local_coords) {
-
// will look different from Particles in editor as this is based on the camera in the scenetree
// and not the editor camera
dir = inv_emission_transform.xform(dir).normalized();
@@ -1062,7 +1027,6 @@ void CPUParticles3D::_update_particle_data_buffer() {
}
for (int i = 0; i < pc; i++) {
-
int idx = order ? order[i] : i;
Transform t = r[idx].transform;
@@ -1107,8 +1071,9 @@ void CPUParticles3D::_update_particle_data_buffer() {
}
void CPUParticles3D::_set_redraw(bool p_redraw) {
- if (redraw == p_redraw)
+ if (redraw == p_redraw) {
return;
+ }
redraw = p_redraw;
{
@@ -1129,7 +1094,6 @@ void CPUParticles3D::_set_redraw(bool p_redraw) {
}
void CPUParticles3D::_update_render_thread() {
-
MutexLock lock(update_mutex);
if (can_update) {
@@ -1139,13 +1103,13 @@ void CPUParticles3D::_update_render_thread() {
}
void CPUParticles3D::_notification(int p_what) {
-
if (p_what == NOTIFICATION_ENTER_TREE) {
set_process_internal(emitting);
// first update before rendering to avoid one frame delay after emitting starts
- if (emitting && (time == 0))
+ if (emitting && (time == 0)) {
_update_internal();
+ }
}
if (p_what == NOTIFICATION_EXIT_TREE) {
@@ -1154,8 +1118,9 @@ void CPUParticles3D::_notification(int p_what) {
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
// first update before rendering to avoid one frame delay after emitting starts
- if (emitting && (time == 0))
+ if (emitting && (time == 0)) {
_update_internal();
+ }
}
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
@@ -1163,11 +1128,9 @@ void CPUParticles3D::_notification(int p_what) {
}
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
-
inv_emission_transform = get_global_transform().affine_inverse();
if (!local_coords) {
-
int pc = particles.size();
float *w = particle_data.ptrw();
@@ -1175,7 +1138,6 @@ void CPUParticles3D::_notification(int p_what) {
float *ptr = w;
for (int i = 0; i < pc; i++) {
-
Transform t = inv_emission_transform * r[i].transform;
if (r[i].active) {
@@ -1204,7 +1166,6 @@ void CPUParticles3D::_notification(int p_what) {
}
void CPUParticles3D::convert_from_particles(Node *p_particles) {
-
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_particles);
ERR_FAIL_COND_MSG(!particles, "Only GPUParticles3D nodes can be converted to CPUParticles3D.");
@@ -1223,8 +1184,9 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) {
set_mesh(particles->get_draw_pass_mesh(0));
Ref<ParticlesMaterial> material = particles->get_process_material();
- if (material.is_null())
+ if (material.is_null()) {
return;
+ }
set_direction(material->get_direction());
set_spread(material->get_spread());
@@ -1252,7 +1214,8 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) {
set_param(m_param, material->get_param(ParticlesMaterial::m_param)); \
{ \
Ref<CurveTexture> ctex = material->get_param_texture(ParticlesMaterial::m_param); \
- if (ctex.is_valid()) set_param_curve(m_param, ctex->get_curve()); \
+ if (ctex.is_valid()) \
+ set_param_curve(m_param, ctex->get_curve()); \
} \
set_param_randomness(m_param, material->get_param_randomness(ParticlesMaterial::m_param));
@@ -1273,7 +1236,6 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) {
}
void CPUParticles3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &CPUParticles3D::set_emitting);
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &CPUParticles3D::set_amount);
ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &CPUParticles3D::set_lifetime);
@@ -1383,7 +1345,7 @@ void CPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles3D::convert_from_particles);
ADD_GROUP("Emission Shape", "emission_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_points"), "set_emission_points", "get_emission_points");
@@ -1478,7 +1440,6 @@ void CPUParticles3D::_bind_methods() {
}
CPUParticles3D::CPUParticles3D() {
-
time = 0;
inactive_time = 0;
frame_remainder = 0;
diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h
index ffe0ecc9a9..da4811b60e 100644
--- a/scene/3d/cpu_particles_3d.h
+++ b/scene/3d/cpu_particles_3d.h
@@ -31,7 +31,7 @@
#ifndef CPU_PARTICLES_H
#define CPU_PARTICLES_H
-#include "core/rid.h"
+#include "core/templates/rid.h"
#include "scene/3d/visual_instance_3d.h"
class CPUParticles3D : public GeometryInstance3D {
@@ -46,7 +46,6 @@ public:
};
enum Parameter {
-
PARAM_INITIAL_LINEAR_VELOCITY,
PARAM_ANGULAR_VELOCITY,
PARAM_ORBIT_VELOCITY,
@@ -122,7 +121,6 @@ private:
const Particle *particles;
Vector3 axis;
bool operator()(int p_a, int p_b) const {
-
return axis.dot(particles[p_a].transform.origin) < axis.dot(particles[p_b].transform.origin);
}
};
@@ -187,11 +185,11 @@ private:
protected:
static void _bind_methods();
void _notification(int p_what);
- virtual void _validate_property(PropertyInfo &property) const;
+ virtual void _validate_property(PropertyInfo &property) const override;
public:
- AABB get_aabb() const;
- Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ AABB get_aabb() const override;
+ Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
@@ -280,7 +278,7 @@ public:
void set_gravity(const Vector3 &p_gravity);
Vector3 get_gravity() const;
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
void restart();
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index 4c824aedc4..fb72e10171 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -47,6 +47,7 @@ void Decal::set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture) {
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
RS::get_singleton()->decal_set_texture(decal, RS::DecalTexture(p_type), texture_rid);
}
+
Ref<Texture2D> Decal::get_texture(DecalTexture p_type) const {
ERR_FAIL_INDEX_V(p_type, TEXTURE_MAX, Ref<Texture2D>());
return textures[p_type];
@@ -56,6 +57,7 @@ void Decal::set_emission_energy(float p_energy) {
emission_energy = p_energy;
RS::get_singleton()->decal_set_emission_energy(decal, emission_energy);
}
+
float Decal::get_emission_energy() const {
return emission_energy;
}
@@ -64,6 +66,7 @@ void Decal::set_albedo_mix(float p_mix) {
albedo_mix = p_mix;
RS::get_singleton()->decal_set_albedo_mix(decal, albedo_mix);
}
+
float Decal::get_albedo_mix() const {
return albedo_mix;
}
@@ -72,6 +75,7 @@ void Decal::set_upper_fade(float p_fade) {
upper_fade = p_fade;
RS::get_singleton()->decal_set_fade(decal, upper_fade, lower_fade);
}
+
float Decal::get_upper_fade() const {
return upper_fade;
}
@@ -80,6 +84,7 @@ void Decal::set_lower_fade(float p_fade) {
lower_fade = p_fade;
RS::get_singleton()->decal_set_fade(decal, upper_fade, lower_fade);
}
+
float Decal::get_lower_fade() const {
return lower_fade;
}
@@ -88,6 +93,7 @@ void Decal::set_normal_fade(float p_fade) {
normal_fade = p_fade;
RS::get_singleton()->decal_set_normal_fade(decal, normal_fade);
}
+
float Decal::get_normal_fade() const {
return normal_fade;
}
@@ -105,6 +111,7 @@ void Decal::set_enable_distance_fade(bool p_enable) {
distance_fade_enabled = p_enable;
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
}
+
bool Decal::is_distance_fade_enabled() const {
return distance_fade_enabled;
}
@@ -113,6 +120,7 @@ void Decal::set_distance_fade_begin(float p_distance) {
distance_fade_begin = p_distance;
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
}
+
float Decal::get_distance_fade_begin() const {
return distance_fade_begin;
}
@@ -121,6 +129,7 @@ void Decal::set_distance_fade_length(float p_length) {
distance_fade_length = p_length;
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
}
+
float Decal::get_distance_fade_length() const {
return distance_fade_length;
}
@@ -129,24 +138,23 @@ void Decal::set_cull_mask(uint32_t p_layers) {
cull_mask = p_layers;
RS::get_singleton()->decal_set_cull_mask(decal, cull_mask);
}
+
uint32_t Decal::get_cull_mask() const {
return cull_mask;
}
AABB Decal::get_aabb() const {
-
AABB aabb;
aabb.position = -extents;
aabb.size = extents * 2.0;
return aabb;
}
-Vector<Face3> Decal::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> Decal::get_faces(uint32_t p_usage_flags) const {
return Vector<Face3>();
}
void Decal::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &Decal::set_extents);
ClassDB::bind_method(D_METHOD("get_extents"), &Decal::get_extents);
@@ -212,7 +220,6 @@ void Decal::_bind_methods() {
}
Decal::Decal() {
-
extents = Vector3(1, 1, 1);
emission_energy = 1.0;
modulate = Color(1, 1, 1, 1);
@@ -230,6 +237,5 @@ Decal::Decal() {
}
Decal::~Decal() {
-
RS::get_singleton()->free(decal);
}
diff --git a/scene/3d/decal.h b/scene/3d/decal.h
index 665444829d..e821461772 100644
--- a/scene/3d/decal.h
+++ b/scene/3d/decal.h
@@ -102,8 +102,8 @@ public:
void set_cull_mask(uint32_t p_layers);
uint32_t get_cull_mask() const;
- virtual AABB get_aabb() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual AABB get_aabb() const override;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
Decal();
~Decal();
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 6d571ee4f2..fd592012f8 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -32,7 +32,6 @@
#include "core/os/os.h"
-#include "core/method_bind_ext.gen.inc"
#include "mesh_instance_3d.h"
#include "voxelizer.h"
@@ -101,15 +100,19 @@ void GIProbeData::allocate(const Transform &p_to_cell_xform, const AABB &p_aabb,
AABB GIProbeData::get_bounds() const {
return bounds;
}
+
Vector3 GIProbeData::get_octree_size() const {
return octree_size;
}
+
Vector<uint8_t> GIProbeData::get_octree_cells() const {
return RS::get_singleton()->gi_probe_get_octree_cells(probe);
}
+
Vector<uint8_t> GIProbeData::get_data_cells() const {
return RS::get_singleton()->gi_probe_get_data_cells(probe);
}
+
Vector<uint8_t> GIProbeData::get_distance_field() const {
return RS::get_singleton()->gi_probe_get_distance_field(probe);
}
@@ -117,6 +120,7 @@ Vector<uint8_t> GIProbeData::get_distance_field() const {
Vector<int> GIProbeData::get_level_counts() const {
return RS::get_singleton()->gi_probe_get_level_counts(probe);
}
+
Transform GIProbeData::get_to_cell_xform() const {
return to_cell_xform;
}
@@ -212,7 +216,6 @@ bool GIProbeData::is_using_two_bounces() const {
}
RID GIProbeData::get_rid() const {
-
return probe;
}
@@ -283,7 +286,6 @@ void GIProbeData::_bind_methods() {
}
GIProbeData::GIProbeData() {
-
ao = 0.0;
ao_size = 0.5;
dynamic_range = 4;
@@ -299,7 +301,6 @@ GIProbeData::GIProbeData() {
}
GIProbeData::~GIProbeData() {
-
RS::get_singleton()->free(probe);
}
@@ -307,7 +308,6 @@ GIProbeData::~GIProbeData() {
//////////////////////
void GIProbe::set_probe_data(const Ref<GIProbeData> &p_data) {
-
if (p_data.is_valid()) {
RS::get_singleton()->instance_set_base(get_instance(), p_data->get_rid());
} else {
@@ -318,41 +318,34 @@ void GIProbe::set_probe_data(const Ref<GIProbeData> &p_data) {
}
Ref<GIProbeData> GIProbe::get_probe_data() const {
-
return probe_data;
}
void GIProbe::set_subdiv(Subdiv p_subdiv) {
-
ERR_FAIL_INDEX(p_subdiv, SUBDIV_MAX);
subdiv = p_subdiv;
update_gizmo();
}
GIProbe::Subdiv GIProbe::get_subdiv() const {
-
return subdiv;
}
void GIProbe::set_extents(const Vector3 &p_extents) {
-
extents = p_extents;
update_gizmo();
_change_notify("extents");
}
Vector3 GIProbe::get_extents() const {
-
return extents;
}
void GIProbe::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) {
-
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
- if (mi && mi->get_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) {
+ if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) {
Ref<Mesh> mesh = mi->get_mesh();
if (mesh.is_valid()) {
-
AABB aabb = mesh->get_aabb();
Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform();
@@ -372,16 +365,14 @@ void GIProbe::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) {
Node3D *s = Object::cast_to<Node3D>(p_at_node);
if (s) {
-
if (s->is_visible_in_tree()) {
-
Array meshes = p_at_node->call("get_meshes");
for (int i = 0; i < meshes.size(); i += 2) {
-
Transform mxf = meshes[i];
Ref<Mesh> mesh = meshes[i + 1];
- if (!mesh.is_valid())
+ if (!mesh.is_valid()) {
continue;
+ }
AABB aabb = mesh->get_aabb();
@@ -416,9 +407,9 @@ Vector3i GIProbe::get_estimated_cell_size() const {
axis_cell_size[longest_axis] = 1 << cell_subdiv;
for (int i = 0; i < 3; i++) {
-
- if (i == longest_axis)
+ if (i == longest_axis) {
continue;
+ }
axis_cell_size[i] = axis_cell_size[longest_axis];
float axis_size = bounds.size[longest_axis];
@@ -432,8 +423,8 @@ Vector3i GIProbe::get_estimated_cell_size() const {
return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]);
}
-void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
+void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 };
Voxelizer baker;
@@ -451,7 +442,6 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
int pmc = 0;
for (List<PlotMesh>::Element *E = mesh_list.front(); E; E = E->next()) {
-
if (bake_step_function) {
bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(mesh_list.size()));
}
@@ -483,11 +473,11 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
#endif
} else {
-
Ref<GIProbeData> probe_data = get_probe_data();
- if (probe_data.is_null())
+ if (probe_data.is_null()) {
probe_data.instance();
+ }
if (bake_step_function) {
bake_step_function(pmc++, RTR("Generating Distance Field"));
@@ -511,30 +501,30 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
}
void GIProbe::_debug_bake() {
-
bake(nullptr, true);
}
AABB GIProbe::get_aabb() const {
-
return AABB(-extents, extents * 2);
}
Vector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
-
return Vector<Face3>();
}
String GIProbe::get_configuration_warning() const {
+ String warning = VisualInstance3D::get_configuration_warning();
if (RenderingServer::get_singleton()->is_low_end()) {
- return TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead.");
}
- return String();
+ return warning;
}
void GIProbe::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_probe_data", "data"), &GIProbe::set_probe_data);
ClassDB::bind_method(D_METHOD("get_probe_data"), &GIProbe::get_probe_data);
@@ -560,7 +550,6 @@ void GIProbe::_bind_methods() {
}
GIProbe::GIProbe() {
-
subdiv = SUBDIV_128;
extents = Vector3(10, 10, 10);
diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h
index 28b533e82d..2dadf48a06 100644
--- a/scene/3d/gi_probe.h
+++ b/scene/3d/gi_probe.h
@@ -35,7 +35,6 @@
#include "scene/3d/visual_instance_3d.h"
class GIProbeData : public Resource {
-
GDCLASS(GIProbeData, Resource);
RID probe;
@@ -60,7 +59,7 @@ class GIProbeData : public Resource {
protected:
static void _bind_methods();
- void _validate_property(PropertyInfo &property) const;
+ void _validate_property(PropertyInfo &property) const override;
public:
void allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
@@ -102,7 +101,7 @@ public:
void set_use_two_bounces(bool p_enable);
bool is_using_two_bounces() const;
- virtual RID get_rid() const;
+ virtual RID get_rid() const override;
GIProbeData();
~GIProbeData();
@@ -163,10 +162,10 @@ public:
void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false);
- virtual AABB get_aabb() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual AABB get_aabb() const override;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
GIProbe();
~GIProbe();
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 7744c477cb..ec33d7bcab 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -36,16 +36,14 @@
#include "servers/rendering_server.h"
AABB GPUParticles3D::get_aabb() const {
-
return AABB();
}
-Vector<Face3> GPUParticles3D::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> GPUParticles3D::get_faces(uint32_t p_usage_flags) const {
return Vector<Face3>();
}
void GPUParticles3D::set_emitting(bool p_emitting) {
-
RS::get_singleton()->particles_set_emitting(particles, p_emitting);
if (p_emitting && one_shot) {
@@ -56,157 +54,158 @@ void GPUParticles3D::set_emitting(bool p_emitting) {
}
void GPUParticles3D::set_amount(int p_amount) {
-
ERR_FAIL_COND_MSG(p_amount < 1, "Amount of particles cannot be smaller than 1.");
amount = p_amount;
RS::get_singleton()->particles_set_amount(particles, amount);
}
-void GPUParticles3D::set_lifetime(float p_lifetime) {
+void GPUParticles3D::set_lifetime(float p_lifetime) {
ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0.");
lifetime = p_lifetime;
RS::get_singleton()->particles_set_lifetime(particles, lifetime);
}
void GPUParticles3D::set_one_shot(bool p_one_shot) {
-
one_shot = p_one_shot;
RS::get_singleton()->particles_set_one_shot(particles, one_shot);
if (is_emitting()) {
-
set_process_internal(true);
- if (!one_shot)
+ if (!one_shot) {
RenderingServer::get_singleton()->particles_restart(particles);
+ }
}
- if (!one_shot)
+ if (!one_shot) {
set_process_internal(false);
+ }
}
void GPUParticles3D::set_pre_process_time(float p_time) {
-
pre_process_time = p_time;
RS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time);
}
-void GPUParticles3D::set_explosiveness_ratio(float p_ratio) {
+void GPUParticles3D::set_explosiveness_ratio(float p_ratio) {
explosiveness_ratio = p_ratio;
RS::get_singleton()->particles_set_explosiveness_ratio(particles, explosiveness_ratio);
}
-void GPUParticles3D::set_randomness_ratio(float p_ratio) {
+void GPUParticles3D::set_randomness_ratio(float p_ratio) {
randomness_ratio = p_ratio;
RS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio);
}
-void GPUParticles3D::set_visibility_aabb(const AABB &p_aabb) {
+void GPUParticles3D::set_visibility_aabb(const AABB &p_aabb) {
visibility_aabb = p_aabb;
RS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb);
update_gizmo();
_change_notify("visibility_aabb");
}
-void GPUParticles3D::set_use_local_coordinates(bool p_enable) {
+void GPUParticles3D::set_use_local_coordinates(bool p_enable) {
local_coords = p_enable;
RS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords);
}
-void GPUParticles3D::set_process_material(const Ref<Material> &p_material) {
+void GPUParticles3D::set_process_material(const Ref<Material> &p_material) {
process_material = p_material;
RID material_rid;
- if (process_material.is_valid())
+ if (process_material.is_valid()) {
material_rid = process_material->get_rid();
+ }
RS::get_singleton()->particles_set_process_material(particles, material_rid);
update_configuration_warning();
}
void GPUParticles3D::set_speed_scale(float p_scale) {
-
speed_scale = p_scale;
RS::get_singleton()->particles_set_speed_scale(particles, p_scale);
}
-bool GPUParticles3D::is_emitting() const {
+void GPUParticles3D::set_collision_base_size(float p_size) {
+ collision_base_size = p_size;
+ RS::get_singleton()->particles_set_collision_base_size(particles, p_size);
+}
+bool GPUParticles3D::is_emitting() const {
return RS::get_singleton()->particles_get_emitting(particles);
}
-int GPUParticles3D::get_amount() const {
+int GPUParticles3D::get_amount() const {
return amount;
}
-float GPUParticles3D::get_lifetime() const {
+float GPUParticles3D::get_lifetime() const {
return lifetime;
}
-bool GPUParticles3D::get_one_shot() const {
+bool GPUParticles3D::get_one_shot() const {
return one_shot;
}
float GPUParticles3D::get_pre_process_time() const {
-
return pre_process_time;
}
-float GPUParticles3D::get_explosiveness_ratio() const {
+float GPUParticles3D::get_explosiveness_ratio() const {
return explosiveness_ratio;
}
-float GPUParticles3D::get_randomness_ratio() const {
+float GPUParticles3D::get_randomness_ratio() const {
return randomness_ratio;
}
-AABB GPUParticles3D::get_visibility_aabb() const {
+AABB GPUParticles3D::get_visibility_aabb() const {
return visibility_aabb;
}
-bool GPUParticles3D::get_use_local_coordinates() const {
+bool GPUParticles3D::get_use_local_coordinates() const {
return local_coords;
}
-Ref<Material> GPUParticles3D::get_process_material() const {
+Ref<Material> GPUParticles3D::get_process_material() const {
return process_material;
}
float GPUParticles3D::get_speed_scale() const {
-
return speed_scale;
}
-void GPUParticles3D::set_draw_order(DrawOrder p_order) {
+float GPUParticles3D::get_collision_base_size() const {
+ return collision_base_size;
+}
+void GPUParticles3D::set_draw_order(DrawOrder p_order) {
draw_order = p_order;
RS::get_singleton()->particles_set_draw_order(particles, RS::ParticlesDrawOrder(p_order));
}
GPUParticles3D::DrawOrder GPUParticles3D::get_draw_order() const {
-
return draw_order;
}
void GPUParticles3D::set_draw_passes(int p_count) {
-
ERR_FAIL_COND(p_count < 1);
draw_passes.resize(p_count);
RS::get_singleton()->particles_set_draw_passes(particles, p_count);
_change_notify();
}
-int GPUParticles3D::get_draw_passes() const {
+int GPUParticles3D::get_draw_passes() const {
return draw_passes.size();
}
void GPUParticles3D::set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh) {
-
ERR_FAIL_INDEX(p_pass, draw_passes.size());
draw_passes.write[p_pass] = p_mesh;
RID mesh_rid;
- if (p_mesh.is_valid())
+ if (p_mesh.is_valid()) {
mesh_rid = p_mesh->get_rid();
+ }
RS::get_singleton()->particles_set_draw_pass_mesh(particles, p_pass, mesh_rid);
@@ -214,7 +213,6 @@ void GPUParticles3D::set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh) {
}
Ref<Mesh> GPUParticles3D::get_draw_pass_mesh(int p_pass) const {
-
ERR_FAIL_INDEX_V(p_pass, draw_passes.size(), Ref<Mesh>());
return draw_passes[p_pass];
@@ -239,12 +237,11 @@ bool GPUParticles3D::get_fractional_delta() const {
}
String GPUParticles3D::get_configuration_warning() const {
-
if (RenderingServer::get_singleton()->is_low_end()) {
return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles3D node instead. You can use the \"Convert to CPUParticles3D\" option for this purpose.");
}
- String warnings;
+ String warnings = GeometryInstance3D::get_configuration_warning();
bool meshes_found = false;
bool anim_material_found = false;
@@ -257,7 +254,9 @@ String GPUParticles3D::get_configuration_warning() const {
StandardMaterial3D *spat = Object::cast_to<StandardMaterial3D>(draw_passes[i]->surface_get_material(j).ptr());
anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES);
}
- if (anim_material_found) break;
+ if (anim_material_found) {
+ break;
+ }
}
}
@@ -266,22 +265,25 @@ String GPUParticles3D::get_configuration_warning() const {
anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES);
if (!meshes_found) {
- if (warnings != String())
+ if (warnings != String()) {
warnings += "\n";
+ }
warnings += "- " + TTR("Nothing is visible because meshes have not been assigned to draw passes.");
}
if (process_material.is_null()) {
- if (warnings != String())
+ if (warnings != String()) {
warnings += "\n";
+ }
warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted.");
} else {
const ParticlesMaterial *process = Object::cast_to<ParticlesMaterial>(process_material.ptr());
if (!anim_material_found && process &&
(process->get_param(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 ||
process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) {
- if (warnings != String())
+ if (warnings != String()) {
warnings += "\n";
+ }
warnings += "- " + TTR("Particles animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\".");
}
}
@@ -290,18 +292,15 @@ String GPUParticles3D::get_configuration_warning() const {
}
void GPUParticles3D::restart() {
-
RenderingServer::get_singleton()->particles_restart(particles);
RenderingServer::get_singleton()->particles_set_emitting(particles, true);
}
AABB GPUParticles3D::capture_aabb() const {
-
return RS::get_singleton()->particles_get_current_aabb(particles);
}
void GPUParticles3D::_validate_property(PropertyInfo &property) const {
-
if (property.name.begins_with("draw_pass_")) {
int index = property.name.get_slicec('_', 2).to_int() - 1;
if (index >= draw_passes.size()) {
@@ -311,13 +310,41 @@ void GPUParticles3D::_validate_property(PropertyInfo &property) const {
}
}
-void GPUParticles3D::_notification(int p_what) {
+void GPUParticles3D::emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+ RS::get_singleton()->particles_emit(particles, p_transform, p_velocity, p_color, p_custom, p_emit_flags);
+}
+
+void GPUParticles3D::_attach_sub_emitter() {
+ Node *n = get_node_or_null(sub_emitter);
+ if (n) {
+ GPUParticles3D *sen = Object::cast_to<GPUParticles3D>(n);
+ if (sen && sen != this) {
+ RS::get_singleton()->particles_set_subemitter(particles, sen->particles);
+ }
+ }
+}
+void GPUParticles3D::set_sub_emitter(const NodePath &p_path) {
+ if (is_inside_tree()) {
+ RS::get_singleton()->particles_set_subemitter(particles, RID());
+ }
+
+ sub_emitter = p_path;
+
+ if (is_inside_tree() && sub_emitter != NodePath()) {
+ _attach_sub_emitter();
+ }
+}
+
+NodePath GPUParticles3D::get_sub_emitter() const {
+ return sub_emitter;
+}
+
+void GPUParticles3D::_notification(int p_what) {
if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) {
if (can_process()) {
RS::get_singleton()->particles_set_speed_scale(particles, speed_scale);
} else {
-
RS::get_singleton()->particles_set_speed_scale(particles, 0);
}
}
@@ -325,13 +352,22 @@ void GPUParticles3D::_notification(int p_what) {
// Use internal process when emitting and one_shot are on so that when
// the shot ends the editor can properly update
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
-
if (one_shot && !is_emitting()) {
_change_notify();
set_process_internal(false);
}
}
+ if (p_what == NOTIFICATION_ENTER_TREE) {
+ if (sub_emitter != NodePath()) {
+ _attach_sub_emitter();
+ }
+ }
+
+ if (p_what == NOTIFICATION_EXIT_TREE) {
+ RS::get_singleton()->particles_set_subemitter(particles, RID());
+ }
+
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
// make sure particles are updated before rendering occurs if they were active before
if (is_visible_in_tree() && !RS::get_singleton()->particles_is_inactive(particles)) {
@@ -341,7 +377,6 @@ void GPUParticles3D::_notification(int p_what) {
}
void GPUParticles3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &GPUParticles3D::set_emitting);
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &GPUParticles3D::set_amount);
ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &GPUParticles3D::set_lifetime);
@@ -355,6 +390,7 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &GPUParticles3D::set_fractional_delta);
ClassDB::bind_method(D_METHOD("set_process_material", "material"), &GPUParticles3D::set_process_material);
ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &GPUParticles3D::set_speed_scale);
+ ClassDB::bind_method(D_METHOD("set_collision_base_size", "size"), &GPUParticles3D::set_collision_base_size);
ClassDB::bind_method(D_METHOD("is_emitting"), &GPUParticles3D::is_emitting);
ClassDB::bind_method(D_METHOD("get_amount"), &GPUParticles3D::get_amount);
@@ -369,6 +405,7 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_fractional_delta"), &GPUParticles3D::get_fractional_delta);
ClassDB::bind_method(D_METHOD("get_process_material"), &GPUParticles3D::get_process_material);
ClassDB::bind_method(D_METHOD("get_speed_scale"), &GPUParticles3D::get_speed_scale);
+ ClassDB::bind_method(D_METHOD("get_collision_base_size"), &GPUParticles3D::get_collision_base_size);
ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &GPUParticles3D::set_draw_order);
@@ -383,8 +420,14 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("restart"), &GPUParticles3D::restart);
ClassDB::bind_method(D_METHOD("capture_aabb"), &GPUParticles3D::capture_aabb);
+ ClassDB::bind_method(D_METHOD("set_sub_emitter", "path"), &GPUParticles3D::set_sub_emitter);
+ ClassDB::bind_method(D_METHOD("get_sub_emitter"), &GPUParticles3D::get_sub_emitter);
+
+ ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles3D::emit_particle);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter");
ADD_GROUP("Time", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
@@ -394,6 +437,8 @@ void GPUParticles3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
+ ADD_GROUP("Collision", "collision_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_base_size", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_collision_base_size", "get_collision_base_size");
ADD_GROUP("Drawing", "");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
@@ -403,7 +448,6 @@ void GPUParticles3D::_bind_methods() {
ADD_GROUP("Draw Passes", "draw_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_passes", PROPERTY_HINT_RANGE, "0," + itos(MAX_DRAW_PASSES) + ",1"), "set_draw_passes", "get_draw_passes");
for (int i = 0; i < MAX_DRAW_PASSES; i++) {
-
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "draw_pass_" + itos(i + 1), PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_draw_pass_mesh", "get_draw_pass_mesh", i);
}
@@ -411,11 +455,16 @@ void GPUParticles3D::_bind_methods() {
BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME);
BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH);
+ BIND_ENUM_CONSTANT(EMIT_FLAG_POSITION);
+ BIND_ENUM_CONSTANT(EMIT_FLAG_ROTATION_SCALE);
+ BIND_ENUM_CONSTANT(EMIT_FLAG_VELOCITY);
+ BIND_ENUM_CONSTANT(EMIT_FLAG_COLOR);
+ BIND_ENUM_CONSTANT(EMIT_FLAG_CUSTOM);
+
BIND_CONSTANT(MAX_DRAW_PASSES);
}
GPUParticles3D::GPUParticles3D() {
-
particles = RS::get_singleton()->particles_create();
set_base(particles);
one_shot = false; // Needed so that set_emitting doesn't access uninitialized values
@@ -433,9 +482,9 @@ GPUParticles3D::GPUParticles3D() {
set_draw_passes(1);
set_draw_order(DRAW_ORDER_INDEX);
set_speed_scale(1);
+ set_collision_base_size(0.01);
}
GPUParticles3D::~GPUParticles3D() {
-
RS::get_singleton()->free(particles);
}
diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h
index 0c6653294b..f0e5f05e5b 100644
--- a/scene/3d/gpu_particles_3d.h
+++ b/scene/3d/gpu_particles_3d.h
@@ -31,7 +31,7 @@
#ifndef PARTICLES_H
#define PARTICLES_H
-#include "core/rid.h"
+#include "core/templates/rid.h"
#include "scene/3d/visual_instance_3d.h"
#include "scene/resources/material.h"
@@ -64,6 +64,8 @@ private:
bool local_coords;
int fixed_fps;
bool fractional_delta;
+ NodePath sub_emitter;
+ float collision_base_size;
Ref<Material> process_material;
@@ -71,14 +73,16 @@ private:
Vector<Ref<Mesh>> draw_passes;
+ void _attach_sub_emitter();
+
protected:
static void _bind_methods();
void _notification(int p_what);
- virtual void _validate_property(PropertyInfo &property) const;
+ virtual void _validate_property(PropertyInfo &property) const override;
public:
- AABB get_aabb() const;
- Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ AABB get_aabb() const override;
+ Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
@@ -91,6 +95,7 @@ public:
void set_use_local_coordinates(bool p_enable);
void set_process_material(const Ref<Material> &p_material);
void set_speed_scale(float p_scale);
+ void set_collision_base_size(float p_ratio);
bool is_emitting() const;
int get_amount() const;
@@ -103,6 +108,7 @@ public:
bool get_use_local_coordinates() const;
Ref<Material> get_process_material() const;
float get_speed_scale() const;
+ float get_collision_base_size() const;
void set_fixed_fps(int p_count);
int get_fixed_fps() const;
@@ -119,15 +125,29 @@ public:
void set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh);
Ref<Mesh> get_draw_pass_mesh(int p_pass) const;
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
+
+ void set_sub_emitter(const NodePath &p_path);
+ NodePath get_sub_emitter() const;
void restart();
+ enum EmitFlags {
+ EMIT_FLAG_POSITION = RS::PARTICLES_EMIT_FLAG_POSITION,
+ EMIT_FLAG_ROTATION_SCALE = RS::PARTICLES_EMIT_FLAG_ROTATION_SCALE,
+ EMIT_FLAG_VELOCITY = RS::PARTICLES_EMIT_FLAG_VELOCITY,
+ EMIT_FLAG_COLOR = RS::PARTICLES_EMIT_FLAG_COLOR,
+ EMIT_FLAG_CUSTOM = RS::PARTICLES_EMIT_FLAG_CUSTOM
+ };
+
+ void emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);
+
AABB capture_aabb() const;
GPUParticles3D();
~GPUParticles3D();
};
VARIANT_ENUM_CAST(GPUParticles3D::DrawOrder)
+VARIANT_ENUM_CAST(GPUParticles3D::EmitFlags)
#endif // PARTICLES_H
diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp
new file mode 100644
index 0000000000..1f0d5d587d
--- /dev/null
+++ b/scene/3d/gpu_particles_collision_3d.cpp
@@ -0,0 +1,901 @@
+/*************************************************************************/
+/* gpu_particles_collision_3d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "gpu_particles_collision_3d.h"
+
+#include "core/templates/thread_work_pool.h"
+#include "mesh_instance_3d.h"
+#include "scene/3d/camera_3d.h"
+#include "scene/main/viewport.h"
+
+void GPUParticlesCollision3D::set_cull_mask(uint32_t p_cull_mask) {
+ cull_mask = p_cull_mask;
+ RS::get_singleton()->particles_collision_set_cull_mask(collision, p_cull_mask);
+}
+
+uint32_t GPUParticlesCollision3D::get_cull_mask() const {
+ return cull_mask;
+}
+
+void GPUParticlesCollision3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &GPUParticlesCollision3D::set_cull_mask);
+ ClassDB::bind_method(D_METHOD("get_cull_mask"), &GPUParticlesCollision3D::get_cull_mask);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
+}
+
+GPUParticlesCollision3D::GPUParticlesCollision3D(RS::ParticlesCollisionType p_type) {
+ collision = RS::get_singleton()->particles_collision_create();
+ RS::get_singleton()->particles_collision_set_collision_type(collision, p_type);
+ set_base(collision);
+}
+
+GPUParticlesCollision3D::~GPUParticlesCollision3D() {
+ RS::get_singleton()->free(collision);
+}
+
+/////////////////////////////////
+
+void GPUParticlesCollisionSphere::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_radius", "radius"), &GPUParticlesCollisionSphere::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"), &GPUParticlesCollisionSphere::get_radius);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_radius", "get_radius");
+}
+
+void GPUParticlesCollisionSphere::set_radius(float p_radius) {
+ radius = p_radius;
+ RS::get_singleton()->particles_collision_set_sphere_radius(_get_collision(), radius);
+ update_gizmo();
+}
+
+float GPUParticlesCollisionSphere::get_radius() const {
+ return radius;
+}
+
+AABB GPUParticlesCollisionSphere::get_aabb() const {
+ return AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2, radius * 2, radius * 2));
+}
+
+GPUParticlesCollisionSphere::GPUParticlesCollisionSphere() :
+ GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE) {
+}
+
+GPUParticlesCollisionSphere::~GPUParticlesCollisionSphere() {
+}
+
+///////////////////////////
+
+void GPUParticlesCollisionBox::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionBox::set_extents);
+ ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionBox::get_extents);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents");
+}
+
+void GPUParticlesCollisionBox::set_extents(const Vector3 &p_extents) {
+ extents = p_extents;
+ RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
+ update_gizmo();
+}
+
+Vector3 GPUParticlesCollisionBox::get_extents() const {
+ return extents;
+}
+
+AABB GPUParticlesCollisionBox::get_aabb() const {
+ return AABB(-extents, extents * 2);
+}
+
+GPUParticlesCollisionBox::GPUParticlesCollisionBox() :
+ GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE) {
+}
+
+GPUParticlesCollisionBox::~GPUParticlesCollisionBox() {
+}
+
+///////////////////////////////
+///////////////////////////
+
+void GPUParticlesCollisionSDF::_find_meshes(const AABB &p_aabb, Node *p_at_node, List<PlotMesh> &plot_meshes) {
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
+ if (mi && mi->is_visible_in_tree()) {
+ Ref<Mesh> mesh = mi->get_mesh();
+ if (mesh.is_valid()) {
+ AABB aabb = mesh->get_aabb();
+
+ Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform();
+
+ if (p_aabb.intersects(xf.xform(aabb))) {
+ PlotMesh pm;
+ pm.local_xform = xf;
+ pm.mesh = mesh;
+ plot_meshes.push_back(pm);
+ }
+ }
+ }
+
+ Node3D *s = Object::cast_to<Node3D>(p_at_node);
+ if (s) {
+ if (s->is_visible_in_tree()) {
+ Array meshes = p_at_node->call("get_meshes");
+ for (int i = 0; i < meshes.size(); i += 2) {
+ Transform mxf = meshes[i];
+ Ref<Mesh> mesh = meshes[i + 1];
+ if (!mesh.is_valid()) {
+ continue;
+ }
+
+ AABB aabb = mesh->get_aabb();
+
+ Transform xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf);
+
+ if (p_aabb.intersects(xf.xform(aabb))) {
+ PlotMesh pm;
+ pm.local_xform = xf;
+ pm.mesh = mesh;
+ plot_meshes.push_back(pm);
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < p_at_node->get_child_count(); i++) {
+ Node *child = p_at_node->get_child(i);
+ _find_meshes(p_aabb, child, plot_meshes);
+ }
+}
+
+uint32_t GPUParticlesCollisionSDF::_create_bvh(LocalVector<BVH> &bvh_tree, FacePos *p_faces, uint32_t p_face_count, const Face3 *p_triangles, float p_thickness) {
+ if (p_face_count == 1) {
+ return BVH::LEAF_BIT | p_faces[0].index;
+ }
+
+ uint32_t index = bvh_tree.size();
+ {
+ BVH bvh;
+
+ for (uint32_t i = 0; i < p_face_count; i++) {
+ const Face3 &f = p_triangles[p_faces[i].index];
+ AABB aabb(f.vertex[0], Vector3());
+ aabb.expand_to(f.vertex[1]);
+ aabb.expand_to(f.vertex[2]);
+ if (p_thickness > 0.0) {
+ Vector3 normal = p_triangles[p_faces[i].index].get_plane().normal;
+ aabb.expand_to(f.vertex[0] - normal * p_thickness);
+ aabb.expand_to(f.vertex[1] - normal * p_thickness);
+ aabb.expand_to(f.vertex[2] - normal * p_thickness);
+ }
+ if (i == 0) {
+ bvh.bounds = aabb;
+ } else {
+ bvh.bounds.merge_with(aabb);
+ }
+ }
+ bvh_tree.push_back(bvh);
+ }
+
+ uint32_t middle = p_face_count / 2;
+
+ SortArray<FacePos, FaceSort> s;
+ s.compare.axis = bvh_tree[index].bounds.get_longest_axis_index();
+ s.sort(p_faces, p_face_count);
+
+ uint32_t left = _create_bvh(bvh_tree, p_faces, middle, p_triangles, p_thickness);
+ uint32_t right = _create_bvh(bvh_tree, p_faces + middle, p_face_count - middle, p_triangles, p_thickness);
+
+ bvh_tree[index].children[0] = left;
+ bvh_tree[index].children[1] = right;
+
+ return index;
+}
+
+static _FORCE_INLINE_ float Vector3_dot2(const Vector3 &p_vec3) {
+ return p_vec3.dot(p_vec3);
+}
+
+void GPUParticlesCollisionSDF::_find_closest_distance(const Vector3 &p_pos, const BVH *bvh, uint32_t p_bvh_cell, const Face3 *triangles, float thickness, float &closest_distance) {
+ if (p_bvh_cell & BVH::LEAF_BIT) {
+ p_bvh_cell &= BVH::LEAF_MASK; //remove bit
+
+ Vector3 point = p_pos;
+ Plane p = triangles[p_bvh_cell].get_plane();
+ float d = p.distance_to(point);
+ float inside_d = 1e20;
+ if (d < 0 && d > -thickness) {
+ //inside planes, do this in 2D
+
+ Vector3 x_axis = (triangles[p_bvh_cell].vertex[0] - triangles[p_bvh_cell].vertex[1]).normalized();
+ Vector3 y_axis = p.normal.cross(x_axis).normalized();
+
+ Vector2 points[3];
+ for (int i = 0; i < 3; i++) {
+ points[i] = Vector2(x_axis.dot(triangles[p_bvh_cell].vertex[i]), y_axis.dot(triangles[p_bvh_cell].vertex[i]));
+ }
+
+ Vector2 p2d = Vector2(x_axis.dot(point), y_axis.dot(point));
+
+ {
+ // https://www.shadertoy.com/view/XsXSz4
+
+ Vector2 e0 = points[1] - points[0];
+ Vector2 e1 = points[2] - points[1];
+ Vector2 e2 = points[0] - points[2];
+
+ Vector2 v0 = p2d - points[0];
+ Vector2 v1 = p2d - points[1];
+ Vector2 v2 = p2d - points[2];
+
+ Vector2 pq0 = v0 - e0 * CLAMP(v0.dot(e0) / e0.dot(e0), 0.0, 1.0);
+ Vector2 pq1 = v1 - e1 * CLAMP(v1.dot(e1) / e1.dot(e1), 0.0, 1.0);
+ Vector2 pq2 = v2 - e2 * CLAMP(v2.dot(e2) / e2.dot(e2), 0.0, 1.0);
+
+ float s = SGN(e0.x * e2.y - e0.y * e2.x);
+ Vector2 d2 = Vector2(pq0.dot(pq0), s * (v0.x * e0.y - v0.y * e0.x)).min(Vector2(pq1.dot(pq1), s * (v1.x * e1.y - v1.y * e1.x))).min(Vector2(pq2.dot(pq2), s * (v2.x * e2.y - v2.y * e2.x)));
+
+ inside_d = -Math::sqrt(d2.x) * SGN(d2.y);
+ }
+
+ //make sure distance to planes is not shorter if inside
+ if (inside_d < 0) {
+ inside_d = MAX(inside_d, d);
+ inside_d = MAX(inside_d, -(thickness + d));
+ }
+
+ closest_distance = MIN(closest_distance, inside_d);
+ } else {
+ if (d < 0) {
+ point -= p.normal * thickness; //flatten
+ }
+
+ // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
+ Vector3 a = triangles[p_bvh_cell].vertex[0];
+ Vector3 b = triangles[p_bvh_cell].vertex[1];
+ Vector3 c = triangles[p_bvh_cell].vertex[2];
+
+ Vector3 ba = b - a;
+ Vector3 pa = point - a;
+ Vector3 cb = c - b;
+ Vector3 pb = point - b;
+ Vector3 ac = a - c;
+ Vector3 pc = point - c;
+ Vector3 nor = ba.cross(ac);
+
+ inside_d = Math::sqrt(
+ (SGN(ba.cross(nor).dot(pa)) +
+ SGN(cb.cross(nor).dot(pb)) +
+ SGN(ac.cross(nor).dot(pc)) <
+ 2.0) ?
+ MIN(MIN(
+ Vector3_dot2(ba * CLAMP(ba.dot(pa) / Vector3_dot2(ba), 0.0, 1.0) - pa),
+ Vector3_dot2(cb * CLAMP(cb.dot(pb) / Vector3_dot2(cb), 0.0, 1.0) - pb)),
+ Vector3_dot2(ac * CLAMP(ac.dot(pc) / Vector3_dot2(ac), 0.0, 1.0) - pc)) :
+ nor.dot(pa) * nor.dot(pa) / Vector3_dot2(nor));
+
+ closest_distance = MIN(closest_distance, inside_d);
+ }
+
+ } else {
+ bool pass = true;
+ if (!bvh[p_bvh_cell].bounds.has_point(p_pos)) {
+ //outside, find closest point
+ Vector3 he = bvh[p_bvh_cell].bounds.size * 0.5;
+ Vector3 center = bvh[p_bvh_cell].bounds.position + he;
+
+ Vector3 rel = (p_pos - center).abs();
+ Vector3 closest(MIN(rel.x, he.x), MIN(rel.y, he.y), MIN(rel.z, he.z));
+ float d = rel.distance_to(closest);
+
+ if (d >= closest_distance) {
+ pass = false; //already closer than this aabb, discard
+ }
+ }
+
+ if (pass) {
+ _find_closest_distance(p_pos, bvh, bvh[p_bvh_cell].children[0], triangles, thickness, closest_distance);
+ _find_closest_distance(p_pos, bvh, bvh[p_bvh_cell].children[1], triangles, thickness, closest_distance);
+ }
+ }
+}
+
+void GPUParticlesCollisionSDF::_compute_sdf_z(uint32_t p_z, ComputeSDFParams *params) {
+ int32_t z_ofs = p_z * params->size.y * params->size.x;
+ for (int32_t y = 0; y < params->size.y; y++) {
+ int32_t y_ofs = z_ofs + y * params->size.x;
+ for (int32_t x = 0; x < params->size.x; x++) {
+ int32_t x_ofs = y_ofs + x;
+ float &cell = params->cells[x_ofs];
+
+ Vector3 pos = params->cell_offset + Vector3(x, y, p_z) * params->cell_size;
+
+ cell = 1e20;
+
+ _find_closest_distance(pos, params->bvh, 0, params->triangles, params->thickness, cell);
+ }
+ }
+}
+
+void GPUParticlesCollisionSDF::_compute_sdf(ComputeSDFParams *params) {
+ ThreadWorkPool work_pool;
+ work_pool.init();
+ work_pool.begin_work(params->size.z, this, &GPUParticlesCollisionSDF::_compute_sdf_z, params);
+ while (work_pool.get_work_index() < (uint32_t)params->size.z) {
+ OS::get_singleton()->delay_usec(10000);
+ bake_step_function(work_pool.get_work_index() * 100 / params->size.z, "Baking SDF");
+ }
+ work_pool.end_work();
+ work_pool.finish();
+}
+
+Vector3i GPUParticlesCollisionSDF::get_estimated_cell_size() const {
+ static const int subdivs[RESOLUTION_MAX] = { 16, 32, 64, 128, 256, 512 };
+ int subdiv = subdivs[get_resolution()];
+
+ AABB aabb(-extents, extents * 2);
+
+ float cell_size = aabb.get_longest_axis_size() / float(subdiv);
+
+ Vector3i sdf_size = Vector3i(aabb.size / cell_size);
+ sdf_size.x = MAX(1, sdf_size.x);
+ sdf_size.y = MAX(1, sdf_size.y);
+ sdf_size.z = MAX(1, sdf_size.z);
+ return sdf_size;
+}
+
+Ref<Image> GPUParticlesCollisionSDF::bake() {
+ static const int subdivs[RESOLUTION_MAX] = { 16, 32, 64, 128, 256, 512 };
+ int subdiv = subdivs[get_resolution()];
+
+ AABB aabb(-extents, extents * 2);
+
+ float cell_size = aabb.get_longest_axis_size() / float(subdiv);
+
+ Vector3i sdf_size = Vector3i(aabb.size / cell_size);
+ sdf_size.x = MAX(1, sdf_size.x);
+ sdf_size.y = MAX(1, sdf_size.y);
+ sdf_size.z = MAX(1, sdf_size.z);
+
+ if (bake_begin_function) {
+ bake_begin_function(100);
+ }
+
+ aabb.size = Vector3(sdf_size) * cell_size;
+
+ List<PlotMesh> plot_meshes;
+ _find_meshes(aabb, get_parent(), plot_meshes);
+
+ LocalVector<Face3> faces;
+
+ if (bake_step_function) {
+ bake_step_function(0, "Finding Meshes");
+ }
+
+ for (List<PlotMesh>::Element *E = plot_meshes.front(); E; E = E->next()) {
+ const PlotMesh &pm = E->get();
+
+ for (int i = 0; i < pm.mesh->get_surface_count(); i++) {
+ if (pm.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
+ continue; //only triangles
+ }
+
+ Array a = pm.mesh->surface_get_arrays(i);
+
+ Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
+ const Vector3 *vr = vertices.ptr();
+ Vector<int> index = a[Mesh::ARRAY_INDEX];
+
+ if (index.size()) {
+ int facecount = index.size() / 3;
+ const int *ir = index.ptr();
+
+ for (int j = 0; j < facecount; j++) {
+ Face3 face;
+
+ for (int k = 0; k < 3; k++) {
+ face.vertex[k] = pm.local_xform.xform(vr[ir[j * 3 + k]]);
+ }
+
+ //test against original bounds
+ if (!Geometry3D::triangle_box_overlap(aabb.position + aabb.size * 0.5, aabb.size * 0.5, face.vertex)) {
+ continue;
+ }
+
+ faces.push_back(face);
+ }
+
+ } else {
+ int facecount = vertices.size() / 3;
+
+ for (int j = 0; j < facecount; j++) {
+ Face3 face;
+
+ for (int k = 0; k < 3; k++) {
+ face.vertex[k] = pm.local_xform.xform(vr[j * 3 + k]);
+ }
+
+ //test against original bounds
+ if (!Geometry3D::triangle_box_overlap(aabb.position + aabb.size * 0.5, aabb.size * 0.5, face.vertex)) {
+ continue;
+ }
+
+ faces.push_back(face);
+ }
+ }
+ }
+ }
+
+ //compute bvh
+
+ ERR_FAIL_COND_V(faces.size() <= 1, Ref<Image>());
+
+ LocalVector<FacePos> face_pos;
+
+ face_pos.resize(faces.size());
+
+ float th = cell_size * thickness;
+
+ for (uint32_t i = 0; i < faces.size(); i++) {
+ face_pos[i].index = i;
+ face_pos[i].center = (faces[i].vertex[0] + faces[i].vertex[1] + faces[i].vertex[2]) / 2;
+ if (th > 0.0) {
+ face_pos[i].center -= faces[i].get_plane().normal * th * 0.5;
+ }
+ }
+
+ if (bake_step_function) {
+ bake_step_function(0, "Creating BVH");
+ }
+
+ LocalVector<BVH> bvh;
+
+ _create_bvh(bvh, face_pos.ptr(), face_pos.size(), faces.ptr(), th);
+
+ Vector<uint8_t> data;
+ data.resize(sdf_size.z * sdf_size.y * sdf_size.x * sizeof(float));
+
+ if (bake_step_function) {
+ bake_step_function(0, "Baking SDF");
+ }
+
+ ComputeSDFParams params;
+ params.cells = (float *)data.ptrw();
+ params.size = sdf_size;
+ params.cell_size = cell_size;
+ params.cell_offset = aabb.position + Vector3(cell_size * 0.5, cell_size * 0.5, cell_size * 0.5);
+ params.bvh = bvh.ptr();
+ params.triangles = faces.ptr();
+ params.thickness = th;
+ _compute_sdf(&params);
+
+ Ref<Image> ret;
+ ret.instance();
+ ret->create(sdf_size.x, sdf_size.y * sdf_size.z, false, Image::FORMAT_RF, data);
+ ret->convert(Image::FORMAT_RH); //convert to half, save space
+ ret->set_meta("depth", sdf_size.z); //hack, make sure to add to the docs of this function
+
+ if (bake_end_function) {
+ bake_end_function();
+ }
+
+ return ret;
+}
+
+void GPUParticlesCollisionSDF::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionSDF::set_extents);
+ ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionSDF::get_extents);
+
+ ClassDB::bind_method(D_METHOD("set_resolution", "resolution"), &GPUParticlesCollisionSDF::set_resolution);
+ ClassDB::bind_method(D_METHOD("get_resolution"), &GPUParticlesCollisionSDF::get_resolution);
+
+ ClassDB::bind_method(D_METHOD("set_texture", "texture"), &GPUParticlesCollisionSDF::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture"), &GPUParticlesCollisionSDF::get_texture);
+
+ ClassDB::bind_method(D_METHOD("set_thickness", "thickness"), &GPUParticlesCollisionSDF::set_thickness);
+ ClassDB::bind_method(D_METHOD("get_thickness"), &GPUParticlesCollisionSDF::get_thickness);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "16,32,64,128,256,512"), "set_resolution", "get_resolution");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "thickness", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_thickness", "get_thickness");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture");
+
+ BIND_ENUM_CONSTANT(RESOLUTION_16);
+ BIND_ENUM_CONSTANT(RESOLUTION_32);
+ BIND_ENUM_CONSTANT(RESOLUTION_64);
+ BIND_ENUM_CONSTANT(RESOLUTION_128);
+ BIND_ENUM_CONSTANT(RESOLUTION_256);
+ BIND_ENUM_CONSTANT(RESOLUTION_512);
+ BIND_ENUM_CONSTANT(RESOLUTION_MAX);
+}
+
+void GPUParticlesCollisionSDF::set_thickness(float p_thickness) {
+ thickness = p_thickness;
+}
+
+float GPUParticlesCollisionSDF::get_thickness() const {
+ return thickness;
+}
+
+void GPUParticlesCollisionSDF::set_extents(const Vector3 &p_extents) {
+ extents = p_extents;
+ RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
+ update_gizmo();
+}
+
+Vector3 GPUParticlesCollisionSDF::get_extents() const {
+ return extents;
+}
+
+void GPUParticlesCollisionSDF::set_resolution(Resolution p_resolution) {
+ resolution = p_resolution;
+ update_gizmo();
+}
+
+GPUParticlesCollisionSDF::Resolution GPUParticlesCollisionSDF::get_resolution() const {
+ return resolution;
+}
+
+void GPUParticlesCollisionSDF::set_texture(const Ref<Texture3D> &p_texture) {
+ texture = p_texture;
+ RID tex = texture.is_valid() ? texture->get_rid() : RID();
+ RS::get_singleton()->particles_collision_set_field_texture(_get_collision(), tex);
+}
+
+Ref<Texture3D> GPUParticlesCollisionSDF::get_texture() const {
+ return texture;
+}
+
+AABB GPUParticlesCollisionSDF::get_aabb() const {
+ return AABB(-extents, extents * 2);
+}
+
+GPUParticlesCollisionSDF::BakeBeginFunc GPUParticlesCollisionSDF::bake_begin_function = nullptr;
+GPUParticlesCollisionSDF::BakeStepFunc GPUParticlesCollisionSDF::bake_step_function = nullptr;
+GPUParticlesCollisionSDF::BakeEndFunc GPUParticlesCollisionSDF::bake_end_function = nullptr;
+
+GPUParticlesCollisionSDF::GPUParticlesCollisionSDF() :
+ GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE) {
+}
+
+GPUParticlesCollisionSDF::~GPUParticlesCollisionSDF() {
+}
+
+////////////////////////////
+////////////////////////////
+
+void GPUParticlesCollisionHeightField::_notification(int p_what) {
+ if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
+ if (update_mode == UPDATE_MODE_ALWAYS) {
+ RS::get_singleton()->particles_collision_height_field_update(_get_collision());
+ }
+
+ if (follow_camera_mode && get_viewport()) {
+ Camera3D *cam = get_viewport()->get_camera();
+ if (cam) {
+ Transform xform = get_global_transform();
+ Vector3 x_axis = xform.basis.get_axis(Vector3::AXIS_X).normalized();
+ Vector3 z_axis = xform.basis.get_axis(Vector3::AXIS_Z).normalized();
+ float x_len = xform.basis.get_scale().x;
+ float z_len = xform.basis.get_scale().z;
+
+ Vector3 cam_pos = cam->get_global_transform().origin;
+ Transform new_xform = xform;
+
+ while (x_axis.dot(cam_pos - new_xform.origin) > x_len) {
+ new_xform.origin += x_axis * x_len;
+ }
+ while (x_axis.dot(cam_pos - new_xform.origin) < -x_len) {
+ new_xform.origin -= x_axis * x_len;
+ }
+
+ while (z_axis.dot(cam_pos - new_xform.origin) > z_len) {
+ new_xform.origin += z_axis * z_len;
+ }
+ while (z_axis.dot(cam_pos - new_xform.origin) < -z_len) {
+ new_xform.origin -= z_axis * z_len;
+ }
+
+ if (new_xform != xform) {
+ set_global_transform(new_xform);
+ RS::get_singleton()->particles_collision_height_field_update(_get_collision());
+ }
+ }
+ }
+ }
+
+ if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
+ RS::get_singleton()->particles_collision_height_field_update(_get_collision());
+ }
+}
+
+void GPUParticlesCollisionHeightField::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionHeightField::set_extents);
+ ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionHeightField::get_extents);
+
+ ClassDB::bind_method(D_METHOD("set_resolution", "resolution"), &GPUParticlesCollisionHeightField::set_resolution);
+ ClassDB::bind_method(D_METHOD("get_resolution"), &GPUParticlesCollisionHeightField::get_resolution);
+
+ ClassDB::bind_method(D_METHOD("set_update_mode", "update_mode"), &GPUParticlesCollisionHeightField::set_update_mode);
+ ClassDB::bind_method(D_METHOD("get_update_mode"), &GPUParticlesCollisionHeightField::get_update_mode);
+
+ ClassDB::bind_method(D_METHOD("set_follow_camera_mode", "enabled"), &GPUParticlesCollisionHeightField::set_follow_camera_mode);
+ ClassDB::bind_method(D_METHOD("is_follow_camera_mode_enabled"), &GPUParticlesCollisionHeightField::is_follow_camera_mode_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_follow_camera_push_ratio", "ratio"), &GPUParticlesCollisionHeightField::set_follow_camera_push_ratio);
+ ClassDB::bind_method(D_METHOD("get_follow_camera_push_ratio"), &GPUParticlesCollisionHeightField::get_follow_camera_push_ratio);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096,8192"), "set_resolution", "get_resolution");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "WhenMoved,Always"), "set_update_mode", "get_update_mode");
+ ADD_GROUP("Folow Camera", "follow_camera_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_camera_enabled"), "set_follow_camera_mode", "is_follow_camera_mode_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "follow_camera_push_ratio", PROPERTY_HINT_RANGE, "0.01,1,0.01"), "set_follow_camera_push_ratio", "get_follow_camera_push_ratio");
+
+ BIND_ENUM_CONSTANT(RESOLUTION_256);
+ BIND_ENUM_CONSTANT(RESOLUTION_512);
+ BIND_ENUM_CONSTANT(RESOLUTION_1024);
+ BIND_ENUM_CONSTANT(RESOLUTION_2048);
+ BIND_ENUM_CONSTANT(RESOLUTION_4096);
+ BIND_ENUM_CONSTANT(RESOLUTION_8192);
+ BIND_ENUM_CONSTANT(RESOLUTION_MAX);
+
+ BIND_ENUM_CONSTANT(UPDATE_MODE_WHEN_MOVED);
+ BIND_ENUM_CONSTANT(UPDATE_MODE_ALWAYS);
+}
+
+void GPUParticlesCollisionHeightField::set_follow_camera_push_ratio(float p_follow_camera_push_ratio) {
+ follow_camera_push_ratio = p_follow_camera_push_ratio;
+}
+
+float GPUParticlesCollisionHeightField::get_follow_camera_push_ratio() const {
+ return follow_camera_push_ratio;
+}
+
+void GPUParticlesCollisionHeightField::set_extents(const Vector3 &p_extents) {
+ extents = p_extents;
+ RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
+ update_gizmo();
+ RS::get_singleton()->particles_collision_height_field_update(_get_collision());
+}
+
+Vector3 GPUParticlesCollisionHeightField::get_extents() const {
+ return extents;
+}
+
+void GPUParticlesCollisionHeightField::set_resolution(Resolution p_resolution) {
+ resolution = p_resolution;
+ RS::get_singleton()->particles_collision_set_height_field_resolution(_get_collision(), RS::ParticlesCollisionHeightfieldResolution(resolution));
+ update_gizmo();
+ RS::get_singleton()->particles_collision_height_field_update(_get_collision());
+}
+
+GPUParticlesCollisionHeightField::Resolution GPUParticlesCollisionHeightField::get_resolution() const {
+ return resolution;
+}
+
+void GPUParticlesCollisionHeightField::set_update_mode(UpdateMode p_update_mode) {
+ update_mode = p_update_mode;
+ set_process_internal(follow_camera_mode || update_mode == UPDATE_MODE_ALWAYS);
+}
+
+GPUParticlesCollisionHeightField::UpdateMode GPUParticlesCollisionHeightField::get_update_mode() const {
+ return update_mode;
+}
+
+void GPUParticlesCollisionHeightField::set_follow_camera_mode(bool p_enabled) {
+ follow_camera_mode = p_enabled;
+ set_process_internal(follow_camera_mode || update_mode == UPDATE_MODE_ALWAYS);
+}
+
+bool GPUParticlesCollisionHeightField::is_follow_camera_mode_enabled() const {
+ return follow_camera_mode;
+}
+
+AABB GPUParticlesCollisionHeightField::get_aabb() const {
+ return AABB(-extents, extents * 2);
+}
+
+GPUParticlesCollisionHeightField::GPUParticlesCollisionHeightField() :
+ GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE) {
+}
+
+GPUParticlesCollisionHeightField::~GPUParticlesCollisionHeightField() {
+}
+
+////////////////////////////
+////////////////////////////
+
+void GPUParticlesAttractor3D::set_cull_mask(uint32_t p_cull_mask) {
+ cull_mask = p_cull_mask;
+ RS::get_singleton()->particles_collision_set_cull_mask(collision, p_cull_mask);
+}
+
+uint32_t GPUParticlesAttractor3D::get_cull_mask() const {
+ return cull_mask;
+}
+
+void GPUParticlesAttractor3D::set_strength(float p_strength) {
+ strength = p_strength;
+ RS::get_singleton()->particles_collision_set_attractor_strength(collision, p_strength);
+}
+
+float GPUParticlesAttractor3D::get_strength() const {
+ return strength;
+}
+
+void GPUParticlesAttractor3D::set_attenuation(float p_attenuation) {
+ attenuation = p_attenuation;
+ RS::get_singleton()->particles_collision_set_attractor_attenuation(collision, p_attenuation);
+}
+
+float GPUParticlesAttractor3D::get_attenuation() const {
+ return attenuation;
+}
+
+void GPUParticlesAttractor3D::set_directionality(float p_directionality) {
+ directionality = p_directionality;
+ RS::get_singleton()->particles_collision_set_attractor_directionality(collision, p_directionality);
+ update_gizmo();
+}
+
+float GPUParticlesAttractor3D::get_directionality() const {
+ return directionality;
+}
+
+void GPUParticlesAttractor3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &GPUParticlesAttractor3D::set_cull_mask);
+ ClassDB::bind_method(D_METHOD("get_cull_mask"), &GPUParticlesAttractor3D::get_cull_mask);
+
+ ClassDB::bind_method(D_METHOD("set_strength", "strength"), &GPUParticlesAttractor3D::set_strength);
+ ClassDB::bind_method(D_METHOD("get_strength"), &GPUParticlesAttractor3D::get_strength);
+
+ ClassDB::bind_method(D_METHOD("set_attenuation", "attenuation"), &GPUParticlesAttractor3D::set_attenuation);
+ ClassDB::bind_method(D_METHOD("get_attenuation"), &GPUParticlesAttractor3D::get_attenuation);
+
+ ClassDB::bind_method(D_METHOD("set_directionality", "amount"), &GPUParticlesAttractor3D::set_directionality);
+ ClassDB::bind_method(D_METHOD("get_directionality"), &GPUParticlesAttractor3D::get_directionality);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "-128,128,0.01,or_greater,or_lesser"), "set_strength", "get_strength");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attenuation", PROPERTY_HINT_EXP_EASING, "0,8,0.01"), "set_attenuation", "get_attenuation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "directionality", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_directionality", "get_directionality");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
+}
+
+GPUParticlesAttractor3D::GPUParticlesAttractor3D(RS::ParticlesCollisionType p_type) {
+ collision = RS::get_singleton()->particles_collision_create();
+ RS::get_singleton()->particles_collision_set_collision_type(collision, p_type);
+ set_base(collision);
+}
+GPUParticlesAttractor3D::~GPUParticlesAttractor3D() {
+ RS::get_singleton()->free(collision);
+}
+
+/////////////////////////////////
+
+void GPUParticlesAttractorSphere::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_radius", "radius"), &GPUParticlesAttractorSphere::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"), &GPUParticlesAttractorSphere::get_radius);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_radius", "get_radius");
+}
+
+void GPUParticlesAttractorSphere::set_radius(float p_radius) {
+ radius = p_radius;
+ RS::get_singleton()->particles_collision_set_sphere_radius(_get_collision(), radius);
+ update_gizmo();
+}
+
+float GPUParticlesAttractorSphere::get_radius() const {
+ return radius;
+}
+
+AABB GPUParticlesAttractorSphere::get_aabb() const {
+ return AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2, radius * 2, radius * 2));
+}
+
+GPUParticlesAttractorSphere::GPUParticlesAttractorSphere() :
+ GPUParticlesAttractor3D(RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT) {
+}
+
+GPUParticlesAttractorSphere::~GPUParticlesAttractorSphere() {
+}
+
+///////////////////////////
+
+void GPUParticlesAttractorBox::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesAttractorBox::set_extents);
+ ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesAttractorBox::get_extents);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents");
+}
+
+void GPUParticlesAttractorBox::set_extents(const Vector3 &p_extents) {
+ extents = p_extents;
+ RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
+ update_gizmo();
+}
+
+Vector3 GPUParticlesAttractorBox::get_extents() const {
+ return extents;
+}
+
+AABB GPUParticlesAttractorBox::get_aabb() const {
+ return AABB(-extents, extents * 2);
+}
+
+GPUParticlesAttractorBox::GPUParticlesAttractorBox() :
+ GPUParticlesAttractor3D(RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT) {
+}
+
+GPUParticlesAttractorBox::~GPUParticlesAttractorBox() {
+}
+
+///////////////////////////
+
+void GPUParticlesAttractorVectorField::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesAttractorVectorField::set_extents);
+ ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesAttractorVectorField::get_extents);
+
+ ClassDB::bind_method(D_METHOD("set_texture", "texture"), &GPUParticlesAttractorVectorField::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture"), &GPUParticlesAttractorVectorField::get_texture);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture");
+}
+
+void GPUParticlesAttractorVectorField::set_extents(const Vector3 &p_extents) {
+ extents = p_extents;
+ RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
+ update_gizmo();
+}
+
+Vector3 GPUParticlesAttractorVectorField::get_extents() const {
+ return extents;
+}
+
+void GPUParticlesAttractorVectorField::set_texture(const Ref<Texture3D> &p_texture) {
+ texture = p_texture;
+ RID tex = texture.is_valid() ? texture->get_rid() : RID();
+ RS::get_singleton()->particles_collision_set_field_texture(_get_collision(), tex);
+}
+
+Ref<Texture3D> GPUParticlesAttractorVectorField::get_texture() const {
+ return texture;
+}
+
+AABB GPUParticlesAttractorVectorField::get_aabb() const {
+ return AABB(-extents, extents * 2);
+}
+
+GPUParticlesAttractorVectorField::GPUParticlesAttractorVectorField() :
+ GPUParticlesAttractor3D(RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) {
+}
+
+GPUParticlesAttractorVectorField::~GPUParticlesAttractorVectorField() {
+}
diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h
new file mode 100644
index 0000000000..9b644ade6b
--- /dev/null
+++ b/scene/3d/gpu_particles_collision_3d.h
@@ -0,0 +1,342 @@
+/*************************************************************************/
+/* gpu_particles_collision_3d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GPU_PARTICLES_COLLISION_3D_H
+#define GPU_PARTICLES_COLLISION_3D_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid.h"
+#include "scene/3d/visual_instance_3d.h"
+#include "scene/resources/material.h"
+
+class GPUParticlesCollision3D : public VisualInstance3D {
+ GDCLASS(GPUParticlesCollision3D, VisualInstance3D);
+
+ uint32_t cull_mask = 0xFFFFFFFF;
+ RID collision;
+
+protected:
+ _FORCE_INLINE_ RID _get_collision() { return collision; }
+ static void _bind_methods();
+
+ GPUParticlesCollision3D(RS::ParticlesCollisionType p_type);
+
+public:
+ void set_cull_mask(uint32_t p_cull_mask);
+ uint32_t get_cull_mask() const;
+
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); }
+
+ ~GPUParticlesCollision3D();
+};
+
+class GPUParticlesCollisionSphere : public GPUParticlesCollision3D {
+ GDCLASS(GPUParticlesCollisionSphere, GPUParticlesCollision3D);
+
+ float radius = 1.0;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_radius(float p_radius);
+ float get_radius() const;
+
+ virtual AABB get_aabb() const override;
+
+ GPUParticlesCollisionSphere();
+ ~GPUParticlesCollisionSphere();
+};
+
+class GPUParticlesCollisionBox : public GPUParticlesCollision3D {
+ GDCLASS(GPUParticlesCollisionBox, GPUParticlesCollision3D);
+
+ Vector3 extents = Vector3(1, 1, 1);
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_extents(const Vector3 &p_extents);
+ Vector3 get_extents() const;
+
+ virtual AABB get_aabb() const override;
+
+ GPUParticlesCollisionBox();
+ ~GPUParticlesCollisionBox();
+};
+
+class GPUParticlesCollisionSDF : public GPUParticlesCollision3D {
+ GDCLASS(GPUParticlesCollisionSDF, GPUParticlesCollision3D);
+
+public:
+ enum Resolution {
+ RESOLUTION_16,
+ RESOLUTION_32,
+ RESOLUTION_64,
+ RESOLUTION_128,
+ RESOLUTION_256,
+ RESOLUTION_512,
+ RESOLUTION_MAX,
+ };
+
+ typedef void (*BakeBeginFunc)(int);
+ typedef void (*BakeStepFunc)(int, const String &);
+ typedef void (*BakeEndFunc)();
+
+private:
+ Vector3 extents = Vector3(1, 1, 1);
+ Resolution resolution = RESOLUTION_64;
+ Ref<Texture3D> texture;
+ float thickness = 1.0;
+
+ struct PlotMesh {
+ Ref<Mesh> mesh;
+ Transform local_xform;
+ };
+
+ void _find_meshes(const AABB &p_aabb, Node *p_at_node, List<PlotMesh> &plot_meshes);
+
+ struct BVH {
+ enum {
+ LEAF_BIT = 1 << 30,
+ LEAF_MASK = LEAF_BIT - 1
+ };
+ AABB bounds;
+ uint32_t children[2];
+ };
+
+ struct FacePos {
+ Vector3 center;
+ uint32_t index;
+ };
+
+ struct FaceSort {
+ uint32_t axis;
+ bool operator()(const FacePos &p_left, const FacePos &p_right) const {
+ return p_left.center[axis] < p_right.center[axis];
+ }
+ };
+
+ uint32_t _create_bvh(LocalVector<BVH> &bvh_tree, FacePos *p_faces, uint32_t p_face_count, const Face3 *p_triangles, float p_thickness);
+
+ struct ComputeSDFParams {
+ float *cells;
+ Vector3i size;
+ float cell_size;
+ Vector3 cell_offset;
+ const BVH *bvh;
+ const Face3 *triangles;
+ float thickness;
+ };
+
+ void _find_closest_distance(const Vector3 &p_pos, const BVH *bvh, uint32_t p_bvh_cell, const Face3 *triangles, float thickness, float &closest_distance);
+ void _compute_sdf_z(uint32_t p_z, ComputeSDFParams *params);
+ void _compute_sdf(ComputeSDFParams *params);
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_thickness(float p_thickness);
+ float get_thickness() const;
+
+ void set_extents(const Vector3 &p_extents);
+ Vector3 get_extents() const;
+
+ void set_resolution(Resolution p_resolution);
+ Resolution get_resolution() const;
+
+ void set_texture(const Ref<Texture3D> &p_texture);
+ Ref<Texture3D> get_texture() const;
+
+ Vector3i get_estimated_cell_size() const;
+ Ref<Image> bake();
+
+ virtual AABB get_aabb() const override;
+
+ static BakeBeginFunc bake_begin_function;
+ static BakeStepFunc bake_step_function;
+ static BakeEndFunc bake_end_function;
+
+ GPUParticlesCollisionSDF();
+ ~GPUParticlesCollisionSDF();
+};
+
+VARIANT_ENUM_CAST(GPUParticlesCollisionSDF::Resolution)
+
+class GPUParticlesCollisionHeightField : public GPUParticlesCollision3D {
+ GDCLASS(GPUParticlesCollisionHeightField, GPUParticlesCollision3D);
+
+public:
+ enum Resolution {
+ RESOLUTION_256,
+ RESOLUTION_512,
+ RESOLUTION_1024,
+ RESOLUTION_2048,
+ RESOLUTION_4096,
+ RESOLUTION_8192,
+ RESOLUTION_MAX,
+ };
+
+ enum UpdateMode {
+ UPDATE_MODE_WHEN_MOVED,
+ UPDATE_MODE_ALWAYS,
+ };
+
+private:
+ Vector3 extents = Vector3(1, 1, 1);
+ Resolution resolution = RESOLUTION_1024;
+ bool follow_camera_mode = false;
+ float follow_camera_push_ratio = 0.1;
+
+ UpdateMode update_mode = UPDATE_MODE_WHEN_MOVED;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void set_extents(const Vector3 &p_extents);
+ Vector3 get_extents() const;
+
+ void set_resolution(Resolution p_resolution);
+ Resolution get_resolution() const;
+
+ void set_update_mode(UpdateMode p_update_mode);
+ UpdateMode get_update_mode() const;
+
+ void set_follow_camera_mode(bool p_enabled);
+ bool is_follow_camera_mode_enabled() const;
+
+ void set_follow_camera_push_ratio(float p_ratio);
+ float get_follow_camera_push_ratio() const;
+
+ virtual AABB get_aabb() const override;
+
+ GPUParticlesCollisionHeightField();
+ ~GPUParticlesCollisionHeightField();
+};
+
+VARIANT_ENUM_CAST(GPUParticlesCollisionHeightField::Resolution)
+VARIANT_ENUM_CAST(GPUParticlesCollisionHeightField::UpdateMode)
+
+class GPUParticlesAttractor3D : public VisualInstance3D {
+ GDCLASS(GPUParticlesAttractor3D, VisualInstance3D);
+
+ uint32_t cull_mask = 0xFFFFFFFF;
+ RID collision;
+ float strength = 1.0;
+ float attenuation = 1.0;
+ float directionality = 0.0;
+
+protected:
+ _FORCE_INLINE_ RID _get_collision() { return collision; }
+ static void _bind_methods();
+
+ GPUParticlesAttractor3D(RS::ParticlesCollisionType p_type);
+
+public:
+ void set_cull_mask(uint32_t p_cull_mask);
+ uint32_t get_cull_mask() const;
+
+ void set_strength(float p_strength);
+ float get_strength() const;
+
+ void set_attenuation(float p_attenuation);
+ float get_attenuation() const;
+
+ void set_directionality(float p_directionality);
+ float get_directionality() const;
+
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); }
+
+ ~GPUParticlesAttractor3D();
+};
+
+class GPUParticlesAttractorSphere : public GPUParticlesAttractor3D {
+ GDCLASS(GPUParticlesAttractorSphere, GPUParticlesAttractor3D);
+
+ float radius = 1.0;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_radius(float p_radius);
+ float get_radius() const;
+
+ virtual AABB get_aabb() const override;
+
+ GPUParticlesAttractorSphere();
+ ~GPUParticlesAttractorSphere();
+};
+
+class GPUParticlesAttractorBox : public GPUParticlesAttractor3D {
+ GDCLASS(GPUParticlesAttractorBox, GPUParticlesAttractor3D);
+
+ Vector3 extents = Vector3(1, 1, 1);
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_extents(const Vector3 &p_extents);
+ Vector3 get_extents() const;
+
+ virtual AABB get_aabb() const override;
+
+ GPUParticlesAttractorBox();
+ ~GPUParticlesAttractorBox();
+};
+
+class GPUParticlesAttractorVectorField : public GPUParticlesAttractor3D {
+ GDCLASS(GPUParticlesAttractorVectorField, GPUParticlesAttractor3D);
+
+ Vector3 extents = Vector3(1, 1, 1);
+ Ref<Texture3D> texture;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_extents(const Vector3 &p_extents);
+ Vector3 get_extents() const;
+
+ void set_texture(const Ref<Texture3D> &p_texture);
+ Ref<Texture3D> get_texture() const;
+
+ virtual AABB get_aabb() const override;
+
+ GPUParticlesAttractorVectorField();
+ ~GPUParticlesAttractorVectorField();
+};
+
+#endif // GPU_PARTICLES_COLLISION_3D_H
diff --git a/scene/3d/immediate_geometry_3d.cpp b/scene/3d/immediate_geometry_3d.cpp
index 63d4b1ac84..7ccfd527a1 100644
--- a/scene/3d/immediate_geometry_3d.cpp
+++ b/scene/3d/immediate_geometry_3d.cpp
@@ -31,39 +31,33 @@
#include "immediate_geometry_3d.h"
void ImmediateGeometry3D::begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture) {
-
RS::get_singleton()->immediate_begin(im, (RS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID());
- if (p_texture.is_valid())
+ if (p_texture.is_valid()) {
cached_textures.push_back(p_texture);
+ }
}
void ImmediateGeometry3D::set_normal(const Vector3 &p_normal) {
-
RS::get_singleton()->immediate_normal(im, p_normal);
}
void ImmediateGeometry3D::set_tangent(const Plane &p_tangent) {
-
RS::get_singleton()->immediate_tangent(im, p_tangent);
}
void ImmediateGeometry3D::set_color(const Color &p_color) {
-
RS::get_singleton()->immediate_color(im, p_color);
}
void ImmediateGeometry3D::set_uv(const Vector2 &p_uv) {
-
RS::get_singleton()->immediate_uv(im, p_uv);
}
void ImmediateGeometry3D::set_uv2(const Vector2 &p_uv2) {
-
RS::get_singleton()->immediate_uv2(im, p_uv2);
}
void ImmediateGeometry3D::add_vertex(const Vector3 &p_vertex) {
-
RS::get_singleton()->immediate_vertex(im, p_vertex);
if (empty) {
aabb.position = p_vertex;
@@ -75,28 +69,24 @@ void ImmediateGeometry3D::add_vertex(const Vector3 &p_vertex) {
}
void ImmediateGeometry3D::end() {
-
RS::get_singleton()->immediate_end(im);
}
void ImmediateGeometry3D::clear() {
-
RS::get_singleton()->immediate_clear(im);
empty = true;
cached_textures.clear();
}
AABB ImmediateGeometry3D::get_aabb() const {
-
return aabb;
}
-Vector<Face3> ImmediateGeometry3D::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> ImmediateGeometry3D::get_faces(uint32_t p_usage_flags) const {
return Vector<Face3>();
}
void ImmediateGeometry3D::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) {
-
for (int i = 1; i <= p_lats; i++) {
double lat0 = Math_PI * (-0.5 + (double)(i - 1) / p_lats);
double z0 = Math::sin(lat0);
@@ -107,7 +97,6 @@ void ImmediateGeometry3D::add_sphere(int p_lats, int p_lons, float p_radius, boo
double zr1 = Math::cos(lat1);
for (int j = p_lons; j >= 1; j--) {
-
double lng0 = 2 * Math_PI * (double)(j - 1) / p_lons;
double x0 = Math::cos(lng0);
double y0 = Math::sin(lng0);
@@ -143,7 +132,6 @@ void ImmediateGeometry3D::add_sphere(int p_lats, int p_lons, float p_radius, boo
}
void ImmediateGeometry3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry3D::begin, DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("set_normal", "normal"), &ImmediateGeometry3D::set_normal);
ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &ImmediateGeometry3D::set_tangent);
@@ -157,13 +145,11 @@ void ImmediateGeometry3D::_bind_methods() {
}
ImmediateGeometry3D::ImmediateGeometry3D() {
-
im = RenderingServer::get_singleton()->immediate_create();
set_base(im);
empty = true;
}
ImmediateGeometry3D::~ImmediateGeometry3D() {
-
RenderingServer::get_singleton()->free(im);
}
diff --git a/scene/3d/immediate_geometry_3d.h b/scene/3d/immediate_geometry_3d.h
index 6e15450a5b..1403936e22 100644
--- a/scene/3d/immediate_geometry_3d.h
+++ b/scene/3d/immediate_geometry_3d.h
@@ -35,7 +35,6 @@
#include "scene/resources/mesh.h"
class ImmediateGeometry3D : public GeometryInstance3D {
-
GDCLASS(ImmediateGeometry3D, GeometryInstance3D);
RID im;
@@ -63,8 +62,8 @@ public:
void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true);
- virtual AABB get_aabb() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual AABB get_aabb() const override;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
ImmediateGeometry3D();
~ImmediateGeometry3D();
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index c048f60ebd..2dc3cd3230 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -30,17 +30,15 @@
#include "light_3d.h"
-#include "core/engine.h"
-#include "core/project_settings.h"
+#include "core/config/engine.h"
+#include "core/config/project_settings.h"
#include "scene/resources/surface_tool.h"
bool Light3D::_can_gizmo_scale() const {
-
return false;
}
void Light3D::set_param(Param p_param, float p_value) {
-
ERR_FAIL_INDEX(p_param, PARAM_MAX);
param[p_param] = p_value;
@@ -60,13 +58,11 @@ void Light3D::set_param(Param p_param, float p_value) {
}
float Light3D::get_param(Param p_param) const {
-
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return param[p_param];
}
void Light3D::set_shadow(bool p_enable) {
-
shadow = p_enable;
RS::get_singleton()->light_set_shadow(light, p_enable);
@@ -74,51 +70,46 @@ void Light3D::set_shadow(bool p_enable) {
update_configuration_warning();
}
}
-bool Light3D::has_shadow() const {
+bool Light3D::has_shadow() const {
return shadow;
}
void Light3D::set_negative(bool p_enable) {
-
negative = p_enable;
RS::get_singleton()->light_set_negative(light, p_enable);
}
-bool Light3D::is_negative() const {
+bool Light3D::is_negative() const {
return negative;
}
void Light3D::set_cull_mask(uint32_t p_cull_mask) {
-
cull_mask = p_cull_mask;
RS::get_singleton()->light_set_cull_mask(light, p_cull_mask);
}
-uint32_t Light3D::get_cull_mask() const {
+uint32_t Light3D::get_cull_mask() const {
return cull_mask;
}
void Light3D::set_color(const Color &p_color) {
-
color = p_color;
RS::get_singleton()->light_set_color(light, p_color);
// The gizmo color depends on the light color, so update it.
update_gizmo();
}
-Color Light3D::get_color() const {
+Color Light3D::get_color() const {
return color;
}
void Light3D::set_shadow_color(const Color &p_shadow_color) {
-
shadow_color = p_shadow_color;
RS::get_singleton()->light_set_shadow_color(light, p_shadow_color);
}
Color Light3D::get_shadow_color() const {
-
return shadow_color;
}
@@ -128,22 +119,17 @@ void Light3D::set_shadow_reverse_cull_face(bool p_enable) {
}
bool Light3D::get_shadow_reverse_cull_face() const {
-
return reverse_cull;
}
AABB Light3D::get_aabb() const {
-
if (type == RenderingServer::LIGHT_DIRECTIONAL) {
-
return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
} else if (type == RenderingServer::LIGHT_OMNI) {
-
return AABB(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]);
} else if (type == RenderingServer::LIGHT_SPOT) {
-
float len = param[PARAM_RANGE];
float size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len;
return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
@@ -153,13 +139,12 @@ AABB Light3D::get_aabb() const {
}
Vector<Face3> Light3D::get_faces(uint32_t p_usage_flags) const {
-
return Vector<Face3>();
}
void Light3D::set_bake_mode(BakeMode p_mode) {
bake_mode = p_mode;
- RS::get_singleton()->light_set_use_gi(light, p_mode != BAKE_DISABLED);
+ RS::get_singleton()->light_set_bake_mode(light, RS::LightBakeMode(p_mode));
}
Light3D::BakeMode Light3D::get_bake_mode() const {
@@ -167,7 +152,6 @@ Light3D::BakeMode Light3D::get_bake_mode() const {
}
void Light3D::set_projector(const Ref<Texture2D> &p_texture) {
-
projector = p_texture;
RID tex_id = projector.is_valid() ? projector->get_rid() : RID();
RS::get_singleton()->light_set_projector(light, tex_id);
@@ -179,9 +163,9 @@ Ref<Texture2D> Light3D::get_projector() const {
}
void Light3D::_update_visibility() {
-
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
bool editor_ok = true;
@@ -205,9 +189,7 @@ void Light3D::_update_visibility() {
}
void Light3D::_notification(int p_what) {
-
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
-
_update_visibility();
}
@@ -217,18 +199,15 @@ void Light3D::_notification(int p_what) {
}
void Light3D::set_editor_only(bool p_editor_only) {
-
editor_only = p_editor_only;
_update_visibility();
}
bool Light3D::is_editor_only() const {
-
return editor_only;
}
void Light3D::_validate_property(PropertyInfo &property) const {
-
if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_size") {
property.usage = 0;
}
@@ -243,7 +222,6 @@ void Light3D::_validate_property(PropertyInfo &property) const {
}
void Light3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_editor_only", "editor_only"), &Light3D::set_editor_only);
ClassDB::bind_method(D_METHOD("is_editor_only"), &Light3D::is_editor_only);
@@ -283,7 +261,7 @@ void Light3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01"), "set_param", "get_param", PARAM_SIZE);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disable,Indirect,All"), "set_bake_mode", "get_bake_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Dynamic,Static"), "set_bake_mode", "get_bake_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
ADD_GROUP("Shadow", "shadow_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow");
@@ -292,6 +270,7 @@ void Light3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_normal_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_fog_fade", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_param", "get_param", PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0.1,8,0.01"), "set_param", "get_param", PARAM_SHADOW_BLUR);
ADD_GROUP("Editor", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
@@ -314,21 +293,27 @@ void Light3D::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR);
+ BIND_ENUM_CONSTANT(PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS);
BIND_ENUM_CONSTANT(PARAM_MAX);
BIND_ENUM_CONSTANT(BAKE_DISABLED);
- BIND_ENUM_CONSTANT(BAKE_INDIRECT);
- BIND_ENUM_CONSTANT(BAKE_ALL);
+ BIND_ENUM_CONSTANT(BAKE_DYNAMIC);
+ BIND_ENUM_CONSTANT(BAKE_STATIC);
}
Light3D::Light3D(RenderingServer::LightType p_type) {
-
type = p_type;
switch (p_type) {
- case RS::LIGHT_DIRECTIONAL: light = RenderingServer::get_singleton()->directional_light_create(); break;
- case RS::LIGHT_OMNI: light = RenderingServer::get_singleton()->omni_light_create(); break;
- case RS::LIGHT_SPOT: light = RenderingServer::get_singleton()->spot_light_create(); break;
+ case RS::LIGHT_DIRECTIONAL:
+ light = RenderingServer::get_singleton()->directional_light_create();
+ break;
+ case RS::LIGHT_OMNI:
+ light = RenderingServer::get_singleton()->omni_light_create();
+ break;
+ case RS::LIGHT_SPOT:
+ light = RenderingServer::get_singleton()->spot_light_create();
+ break;
default: {
};
}
@@ -336,7 +321,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
RS::get_singleton()->instance_set_base(get_instance(), light);
reverse_cull = false;
- bake_mode = BAKE_INDIRECT;
+ bake_mode = BAKE_DYNAMIC;
editor_only = false;
set_color(Color(1, 1, 1, 1));
@@ -362,33 +347,32 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
set_param(PARAM_SHADOW_BIAS, 0.02);
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
set_param(PARAM_TRANSMITTANCE_BIAS, 0.05);
+ set_param(PARAM_SHADOW_VOLUMETRIC_FOG_FADE, 1.0);
set_param(PARAM_SHADOW_FADE_START, 1);
set_disable_scale(true);
}
Light3D::Light3D() {
-
type = RenderingServer::LIGHT_DIRECTIONAL;
ERR_PRINT("Light3D should not be instanced directly; use the DirectionalLight3D, OmniLight3D or SpotLight3D subtypes instead.");
}
Light3D::~Light3D() {
-
RS::get_singleton()->instance_set_base(get_instance(), RID());
- if (light.is_valid())
+ if (light.is_valid()) {
RenderingServer::get_singleton()->free(light);
+ }
}
+
/////////////////////////////////////////
void DirectionalLight3D::set_shadow_mode(ShadowMode p_mode) {
-
shadow_mode = p_mode;
RS::get_singleton()->light_directional_set_shadow_mode(light, RS::LightDirectionalShadowMode(p_mode));
}
DirectionalLight3D::ShadowMode DirectionalLight3D::get_shadow_mode() const {
-
return shadow_mode;
}
@@ -398,23 +382,19 @@ void DirectionalLight3D::set_shadow_depth_range(ShadowDepthRange p_range) {
}
DirectionalLight3D::ShadowDepthRange DirectionalLight3D::get_shadow_depth_range() const {
-
return shadow_depth_range;
}
void DirectionalLight3D::set_blend_splits(bool p_enable) {
-
blend_splits = p_enable;
RS::get_singleton()->light_directional_set_blend_splits(light, p_enable);
}
bool DirectionalLight3D::is_blend_splits_enabled() const {
-
return blend_splits;
}
void DirectionalLight3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &DirectionalLight3D::set_shadow_mode);
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &DirectionalLight3D::get_shadow_mode);
@@ -425,7 +405,7 @@ void DirectionalLight3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight3D::is_blend_splits_enabled);
ADD_GROUP("Directional Shadow", "directional_shadow_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_mode", PROPERTY_HINT_ENUM, "Orthogonal,PSSM 2 Splits,PSSM 4 Splits"), "set_shadow_mode", "get_shadow_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_mode", PROPERTY_HINT_ENUM, "Orthogonal (Fast),PSSM 2 Splits (Average),PSSM 4 Splits (Slow)"), "set_shadow_mode", "get_shadow_mode");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
@@ -445,23 +425,22 @@ void DirectionalLight3D::_bind_methods() {
DirectionalLight3D::DirectionalLight3D() :
Light3D(RenderingServer::LIGHT_DIRECTIONAL) {
-
set_param(PARAM_SHADOW_MAX_DISTANCE, 100);
set_param(PARAM_SHADOW_FADE_START, 0.8);
+ // Increase the default shadow bias to better suit most scenes.
+ // Leave normal bias untouched as it doesn't benefit DirectionalLight3D as much as OmniLight3D.
+ set_param(PARAM_SHADOW_BIAS, 0.05);
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
-
blend_splits = false;
}
void OmniLight3D::set_shadow_mode(ShadowMode p_mode) {
-
shadow_mode = p_mode;
RS::get_singleton()->light_omni_set_shadow_mode(light, RS::LightOmniShadowMode(p_mode));
}
OmniLight3D::ShadowMode OmniLight3D::get_shadow_mode() const {
-
return shadow_mode;
}
@@ -469,7 +448,7 @@ String OmniLight3D::get_configuration_warning() const {
String warning = Light3D::get_configuration_warning();
if (!has_shadow() && get_projector().is_valid()) {
- if (warning != String()) {
+ if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("Projector texture only works with shadows active.");
@@ -479,7 +458,6 @@ String OmniLight3D::get_configuration_warning() const {
}
void OmniLight3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &OmniLight3D::set_shadow_mode);
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &OmniLight3D::get_shadow_mode);
@@ -494,23 +472,24 @@ void OmniLight3D::_bind_methods() {
OmniLight3D::OmniLight3D() :
Light3D(RenderingServer::LIGHT_OMNI) {
-
set_shadow_mode(SHADOW_CUBE);
+ // Increase the default shadow biases to better suit most scenes.
+ set_param(PARAM_SHADOW_BIAS, 0.1);
+ set_param(PARAM_SHADOW_NORMAL_BIAS, 2.0);
}
String SpotLight3D::get_configuration_warning() const {
String warning = Light3D::get_configuration_warning();
if (has_shadow() && get_param(PARAM_SPOT_ANGLE) >= 90.0) {
- if (warning != String()) {
+ if (!warning.empty()) {
warning += "\n\n";
}
-
warning += TTR("A SpotLight3D with an angle wider than 90 degrees cannot cast shadows.");
}
if (!has_shadow() && get_projector().is_valid()) {
- if (warning != String()) {
+ if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("Projector texture only works with shadows active.");
@@ -520,7 +499,6 @@ String SpotLight3D::get_configuration_warning() const {
}
void SpotLight3D::_bind_methods() {
-
ADD_GROUP("Spot", "spot_");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index 6e78217342..69c0478b86 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -28,15 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef LIGHT_H
-#define LIGHT_H
+#ifndef LIGHT_3D_H
+#define LIGHT_3D_H
#include "scene/3d/visual_instance_3d.h"
#include "scene/resources/texture.h"
#include "servers/rendering_server.h"
class Light3D : public VisualInstance3D {
-
GDCLASS(Light3D, VisualInstance3D);
OBJ_CATEGORY("3D Light Nodes");
@@ -59,14 +58,15 @@ public:
PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS,
PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR,
+ PARAM_SHADOW_VOLUMETRIC_FOG_FADE = RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE,
PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS,
PARAM_MAX = RS::LIGHT_PARAM_MAX
};
enum BakeMode {
BAKE_DISABLED,
- BAKE_INDIRECT,
- BAKE_ALL
+ BAKE_DYNAMIC,
+ BAKE_STATIC
};
private:
@@ -92,7 +92,7 @@ protected:
static void _bind_methods();
void _notification(int p_what);
- virtual void _validate_property(PropertyInfo &property) const;
+ virtual void _validate_property(PropertyInfo &property) const override;
Light3D(RenderingServer::LightType p_type);
@@ -129,8 +129,8 @@ public:
void set_projector(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_projector() const;
- virtual AABB get_aabb() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual AABB get_aabb() const override;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
Light3D();
~Light3D();
@@ -140,14 +140,13 @@ VARIANT_ENUM_CAST(Light3D::Param);
VARIANT_ENUM_CAST(Light3D::BakeMode);
class DirectionalLight3D : public Light3D {
-
GDCLASS(DirectionalLight3D, Light3D);
public:
enum ShadowMode {
SHADOW_ORTHOGONAL,
SHADOW_PARALLEL_2_SPLITS,
- SHADOW_PARALLEL_4_SPLITS
+ SHADOW_PARALLEL_4_SPLITS,
};
enum ShadowDepthRange {
@@ -180,7 +179,6 @@ VARIANT_ENUM_CAST(DirectionalLight3D::ShadowMode)
VARIANT_ENUM_CAST(DirectionalLight3D::ShadowDepthRange)
class OmniLight3D : public Light3D {
-
GDCLASS(OmniLight3D, Light3D);
public:
@@ -200,7 +198,7 @@ public:
void set_shadow_mode(ShadowMode p_mode);
ShadowMode get_shadow_mode() const;
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
OmniLight3D();
};
@@ -208,17 +206,16 @@ public:
VARIANT_ENUM_CAST(OmniLight3D::ShadowMode)
class SpotLight3D : public Light3D {
-
GDCLASS(SpotLight3D, Light3D);
protected:
static void _bind_methods();
public:
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
SpotLight3D() :
Light3D(RenderingServer::LIGHT_SPOT) {}
};
-#endif
+#endif // LIGHT_3D_H
diff --git a/scene/3d/lightmap_probe.cpp b/scene/3d/lightmap_probe.cpp
new file mode 100644
index 0000000000..ee21934b80
--- /dev/null
+++ b/scene/3d/lightmap_probe.cpp
@@ -0,0 +1,34 @@
+/*************************************************************************/
+/* lightmap_probe.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "lightmap_probe.h"
+
+LightmapProbe::LightmapProbe() {
+}
diff --git a/scene/3d/lightmap_probe.h b/scene/3d/lightmap_probe.h
new file mode 100644
index 0000000000..c4bd33556f
--- /dev/null
+++ b/scene/3d/lightmap_probe.h
@@ -0,0 +1,42 @@
+/*************************************************************************/
+/* lightmap_probe.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef LIGHTMAP_PROBE_H
+#define LIGHTMAP_PROBE_H
+
+#include "scene/3d/node_3d.h"
+
+class LightmapProbe : public Node3D {
+ GDCLASS(LightmapProbe, Node3D)
+public:
+ LightmapProbe();
+};
+
+#endif // LIGHTMAP_PROBE_H
diff --git a/scene/3d/lightmapper.cpp b/scene/3d/lightmapper.cpp
new file mode 100644
index 0000000000..26faf5154c
--- /dev/null
+++ b/scene/3d/lightmapper.cpp
@@ -0,0 +1,67 @@
+/*************************************************************************/
+/* lightmapper.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "lightmapper.h"
+
+LightmapDenoiser *(*LightmapDenoiser::create_function)() = nullptr;
+
+Ref<LightmapDenoiser> LightmapDenoiser::create() {
+ if (create_function) {
+ return Ref<LightmapDenoiser>(create_function());
+ }
+ return Ref<LightmapDenoiser>();
+}
+
+Lightmapper::CreateFunc Lightmapper::create_custom = nullptr;
+Lightmapper::CreateFunc Lightmapper::create_gpu = nullptr;
+Lightmapper::CreateFunc Lightmapper::create_cpu = nullptr;
+
+Ref<Lightmapper> Lightmapper::create() {
+ Lightmapper *lm = nullptr;
+ if (create_custom) {
+ lm = create_custom();
+ }
+
+ if (!lm && create_gpu) {
+ lm = create_gpu();
+ }
+
+ if (!lm && create_cpu) {
+ lm = create_cpu();
+ }
+ if (!lm) {
+ return Ref<Lightmapper>();
+ } else {
+ return Ref<Lightmapper>(lm);
+ }
+}
+
+Lightmapper::Lightmapper() {
+}
diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h
new file mode 100644
index 0000000000..ccf9bde279
--- /dev/null
+++ b/scene/3d/lightmapper.h
@@ -0,0 +1,120 @@
+/*************************************************************************/
+/* lightmapper.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef LIGHTMAPPER_H
+#define LIGHTMAPPER_H
+
+#include "scene/resources/mesh.h"
+#include "servers/rendering/rendering_device.h"
+
+class LightmapDenoiser : public Reference {
+ GDCLASS(LightmapDenoiser, Reference)
+protected:
+ static LightmapDenoiser *(*create_function)();
+
+public:
+ virtual Ref<Image> denoise_image(const Ref<Image> &p_image) = 0;
+ static Ref<LightmapDenoiser> create();
+};
+
+class Lightmapper : public Reference {
+ GDCLASS(Lightmapper, Reference)
+public:
+ enum GenerateProbes {
+ GENERATE_PROBES_DISABLED,
+ GENERATE_PROBES_SUBDIV_4,
+ GENERATE_PROBES_SUBDIV_8,
+ GENERATE_PROBES_SUBDIV_16,
+ GENERATE_PROBES_SUBDIV_32,
+
+ };
+
+ enum LightType {
+ LIGHT_TYPE_DIRECTIONAL,
+ LIGHT_TYPE_OMNI,
+ LIGHT_TYPE_SPOT
+ };
+
+ enum BakeError {
+ BAKE_ERROR_LIGHTMAP_TOO_SMALL,
+ BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES,
+ BAKE_OK
+ };
+
+ enum BakeQuality {
+ BAKE_QUALITY_LOW,
+ BAKE_QUALITY_MEDIUM,
+ BAKE_QUALITY_HIGH,
+ BAKE_QUALITY_ULTRA,
+ };
+
+ typedef Lightmapper *(*CreateFunc)();
+
+ static CreateFunc create_custom;
+ static CreateFunc create_gpu;
+ static CreateFunc create_cpu;
+
+protected:
+public:
+ typedef bool (*BakeStepFunc)(float, const String &, void *, bool); //step index, step total, step description, userdata
+
+ struct MeshData {
+ //triangle data
+ Vector<Vector3> points;
+ Vector<Vector2> uv2;
+ Vector<Vector3> normal;
+ Ref<Image> albedo_on_uv2;
+ Ref<Image> emission_on_uv2;
+ Variant userdata;
+ };
+
+ virtual void add_mesh(const MeshData &p_mesh) = 0;
+ virtual void add_directional_light(bool p_static, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_angular_distance) = 0;
+ virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size) = 0;
+ virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size) = 0;
+ virtual void add_probe(const Vector3 &p_position) = 0;
+ virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr) = 0;
+
+ virtual int get_bake_texture_count() const = 0;
+ virtual Ref<Image> get_bake_texture(int p_index) const = 0;
+ virtual int get_bake_mesh_count() const = 0;
+ virtual Variant get_bake_mesh_userdata(int p_index) const = 0;
+ virtual Rect2 get_bake_mesh_uv_scale(int p_index) const = 0;
+ virtual int get_bake_mesh_texture_slice(int p_index) const = 0;
+ virtual int get_bake_probe_count() const = 0;
+ virtual Vector3 get_bake_probe_point(int p_probe) const = 0;
+ virtual Vector<Color> get_bake_probe_sh(int p_probe) const = 0;
+
+ static Ref<Lightmapper> create();
+
+ Lightmapper();
+};
+
+#endif // LIGHTMAPPER_H
diff --git a/scene/3d/listener_3d.cpp b/scene/3d/listener_3d.cpp
index 426e34ea80..0a5b9ad09f 100644
--- a/scene/3d/listener_3d.cpp
+++ b/scene/3d/listener_3d.cpp
@@ -36,63 +36,59 @@ void Listener3D::_update_audio_listener_state() {
}
void Listener3D::_request_listener_update() {
-
_update_listener();
}
bool Listener3D::_set(const StringName &p_name, const Variant &p_value) {
-
if (p_name == "current") {
if (p_value.operator bool()) {
make_current();
} else {
clear_current();
}
- } else
+ } else {
return false;
+ }
return true;
}
-bool Listener3D::_get(const StringName &p_name, Variant &r_ret) const {
+bool Listener3D::_get(const StringName &p_name, Variant &r_ret) const {
if (p_name == "current") {
if (is_inside_tree() && get_tree()->is_node_being_edited(this)) {
r_ret = current;
} else {
r_ret = is_current();
}
- } else
+ } else {
return false;
+ }
return true;
}
void Listener3D::_get_property_list(List<PropertyInfo> *p_list) const {
-
p_list->push_back(PropertyInfo(Variant::BOOL, "current"));
}
void Listener3D::_update_listener() {
-
if (is_inside_tree() && is_current()) {
get_viewport()->_listener_transform_changed_notify();
}
}
void Listener3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_ENTER_WORLD: {
bool first_listener = get_viewport()->_listener_add(this);
- if (!get_tree()->is_node_being_edited(this) && (current || first_listener))
+ if (!get_tree()->is_node_being_edited(this) && (current || first_listener)) {
make_current();
+ }
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
_request_listener_update();
} break;
case NOTIFICATION_EXIT_WORLD: {
-
if (!get_tree()->is_node_being_edited(this)) {
if (is_current()) {
clear_current();
@@ -110,25 +106,24 @@ void Listener3D::_notification(int p_what) {
}
Transform Listener3D::get_listener_transform() const {
-
return get_global_transform().orthonormalized();
}
void Listener3D::make_current() {
-
current = true;
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
get_viewport()->_listener_set(this);
}
void Listener3D::clear_current() {
-
current = false;
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
if (get_viewport()->get_listener() == this) {
get_viewport()->_listener_set(nullptr);
@@ -137,18 +132,16 @@ void Listener3D::clear_current() {
}
bool Listener3D::is_current() const {
-
if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) {
-
return get_viewport()->get_listener() == this;
- } else
+ } else {
return current;
+ }
return false;
}
bool Listener3D::_can_gizmo_scale() const {
-
return false;
}
@@ -159,7 +152,6 @@ RES Listener3D::_get_gizmo_geometry() const {
}
void Listener3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("make_current"), &Listener3D::make_current);
ClassDB::bind_method(D_METHOD("clear_current"), &Listener3D::clear_current);
ClassDB::bind_method(D_METHOD("is_current"), &Listener3D::is_current);
@@ -167,7 +159,6 @@ void Listener3D::_bind_methods() {
}
Listener3D::Listener3D() {
-
current = false;
force_change = false;
set_notify_transform(true);
diff --git a/scene/3d/listener_3d.h b/scene/3d/listener_3d.h
index 3383d6725e..4b6923d6e8 100644
--- a/scene/3d/listener_3d.h
+++ b/scene/3d/listener_3d.h
@@ -35,7 +35,6 @@
#include "scene/main/window.h"
class Listener3D : public Node3D {
-
GDCLASS(Listener3D, Node3D);
private:
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index cdc8db8aea..13f40aed4f 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -37,12 +37,12 @@
#include "skeleton_3d.h"
bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) {
-
//this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else.
//add to it that it's probably found on first call to _set anyway.
- if (!get_instance().is_valid())
+ if (!get_instance().is_valid()) {
return false;
+ }
Map<StringName, BlendShapeTrack>::Element *E = blend_shape_tracks.find(p_name);
if (E) {
@@ -53,8 +53,9 @@ bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) {
if (p_name.operator String().begins_with("material/")) {
int idx = p_name.operator String().get_slicec('/', 1).to_int();
- if (idx >= materials.size() || idx < 0)
+ if (idx >= materials.size() || idx < 0) {
return false;
+ }
set_surface_material(idx, p_value);
return true;
@@ -64,9 +65,9 @@ bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) {
}
bool MeshInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
-
- if (!get_instance().is_valid())
+ if (!get_instance().is_valid()) {
return false;
+ }
const Map<StringName, BlendShapeTrack>::Element *E = blend_shape_tracks.find(p_name);
if (E) {
@@ -76,8 +77,9 @@ bool MeshInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
if (p_name.operator String().begins_with("material/")) {
int idx = p_name.operator String().get_slicec('/', 1).to_int();
- if (idx >= materials.size() || idx < 0)
+ if (idx >= materials.size() || idx < 0) {
return false;
+ }
r_ret = materials[idx];
return true;
}
@@ -85,10 +87,8 @@ bool MeshInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
}
void MeshInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
-
List<String> ls;
for (const Map<StringName, BlendShapeTrack>::Element *E = blend_shape_tracks.front(); E; E = E->next()) {
-
ls.push_back(E->key());
}
@@ -106,9 +106,9 @@ void MeshInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
}
void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) {
-
- if (mesh == p_mesh)
+ if (mesh == p_mesh) {
return;
+ }
if (mesh.is_valid()) {
mesh->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &MeshInstance3D::_mesh_changed));
@@ -119,9 +119,7 @@ void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) {
blend_shape_tracks.clear();
if (mesh.is_valid()) {
-
for (int i = 0; i < mesh->get_blend_shape_count(); i++) {
-
BlendShapeTrack mt;
mt.idx = i;
mt.value = 0;
@@ -133,7 +131,6 @@ void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) {
set_base(mesh->get_rid());
} else {
-
set_base(RID());
}
@@ -141,13 +138,12 @@ void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) {
_change_notify();
}
-Ref<Mesh> MeshInstance3D::get_mesh() const {
+Ref<Mesh> MeshInstance3D::get_mesh() const {
return mesh;
}
void MeshInstance3D::_resolve_skeleton_path() {
-
Ref<SkinReference> new_skin_reference;
if (!skeleton_path.is_empty()) {
@@ -174,8 +170,9 @@ void MeshInstance3D::_resolve_skeleton_path() {
void MeshInstance3D::set_skin(const Ref<Skin> &p_skin) {
skin_internal = p_skin;
skin = p_skin;
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
_resolve_skeleton_path();
}
@@ -184,10 +181,10 @@ Ref<Skin> MeshInstance3D::get_skin() const {
}
void MeshInstance3D::set_skeleton_path(const NodePath &p_skeleton) {
-
skeleton_path = p_skeleton;
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
_resolve_skeleton_path();
}
@@ -196,32 +193,34 @@ NodePath MeshInstance3D::get_skeleton_path() {
}
AABB MeshInstance3D::get_aabb() const {
-
- if (!mesh.is_null())
+ if (!mesh.is_null()) {
return mesh->get_aabb();
+ }
return AABB();
}
Vector<Face3> MeshInstance3D::get_faces(uint32_t p_usage_flags) const {
-
- if (!(p_usage_flags & (FACES_SOLID | FACES_ENCLOSING)))
+ if (!(p_usage_flags & (FACES_SOLID | FACES_ENCLOSING))) {
return Vector<Face3>();
+ }
- if (mesh.is_null())
+ if (mesh.is_null()) {
return Vector<Face3>();
+ }
return mesh->get_faces();
}
Node *MeshInstance3D::create_trimesh_collision_node() {
-
- if (mesh.is_null())
+ if (mesh.is_null()) {
return nullptr;
+ }
Ref<Shape3D> shape = mesh->create_trimesh_shape();
- if (shape.is_null())
+ if (shape.is_null()) {
return nullptr;
+ }
StaticBody3D *static_body = memnew(StaticBody3D);
CollisionShape3D *cshape = memnew(CollisionShape3D);
@@ -231,7 +230,6 @@ Node *MeshInstance3D::create_trimesh_collision_node() {
}
void MeshInstance3D::create_trimesh_collision() {
-
StaticBody3D *static_body = Object::cast_to<StaticBody3D>(create_trimesh_collision_node());
ERR_FAIL_COND(!static_body);
static_body->set_name(String(get_name()) + "_col");
@@ -245,13 +243,14 @@ void MeshInstance3D::create_trimesh_collision() {
}
Node *MeshInstance3D::create_convex_collision_node() {
-
- if (mesh.is_null())
+ if (mesh.is_null()) {
return nullptr;
+ }
Ref<Shape3D> shape = mesh->create_convex_shape();
- if (shape.is_null())
+ if (shape.is_null()) {
return nullptr;
+ }
StaticBody3D *static_body = memnew(StaticBody3D);
CollisionShape3D *cshape = memnew(CollisionShape3D);
@@ -261,7 +260,6 @@ Node *MeshInstance3D::create_convex_collision_node() {
}
void MeshInstance3D::create_convex_collision() {
-
StaticBody3D *static_body = Object::cast_to<StaticBody3D>(create_convex_collision_node());
ERR_FAIL_COND(!static_body);
static_body->set_name(String(get_name()) + "_col");
@@ -275,38 +273,34 @@ void MeshInstance3D::create_convex_collision() {
}
void MeshInstance3D::_notification(int p_what) {
-
if (p_what == NOTIFICATION_ENTER_TREE) {
_resolve_skeleton_path();
}
}
int MeshInstance3D::get_surface_material_count() const {
-
return materials.size();
}
void MeshInstance3D::set_surface_material(int p_surface, const Ref<Material> &p_material) {
-
ERR_FAIL_INDEX(p_surface, materials.size());
materials.write[p_surface] = p_material;
- if (materials[p_surface].is_valid())
+ if (materials[p_surface].is_valid()) {
RS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, materials[p_surface]->get_rid());
- else
+ } else {
RS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, RID());
+ }
}
Ref<Material> MeshInstance3D::get_surface_material(int p_surface) const {
-
ERR_FAIL_INDEX_V(p_surface, materials.size(), Ref<Material>());
return materials[p_surface];
}
Ref<Material> MeshInstance3D::get_active_material(int p_surface) const {
-
Ref<Material> material_override = get_material_override();
if (material_override.is_valid()) {
return material_override;
@@ -326,28 +320,29 @@ Ref<Material> MeshInstance3D::get_active_material(int p_surface) const {
}
void MeshInstance3D::_mesh_changed() {
-
materials.resize(mesh->get_surface_count());
}
void MeshInstance3D::create_debug_tangents() {
-
Vector<Vector3> lines;
Vector<Color> colors;
Ref<Mesh> mesh = get_mesh();
- if (!mesh.is_valid())
+ if (!mesh.is_valid()) {
return;
+ }
for (int i = 0; i < mesh->get_surface_count(); i++) {
Array arrays = mesh->surface_get_arrays(i);
Vector<Vector3> verts = arrays[Mesh::ARRAY_VERTEX];
Vector<Vector3> norms = arrays[Mesh::ARRAY_NORMAL];
- if (norms.size() == 0)
+ if (norms.size() == 0) {
continue;
+ }
Vector<float> tangents = arrays[Mesh::ARRAY_TANGENT];
- if (tangents.size() == 0)
+ if (tangents.size() == 0) {
continue;
+ }
for (int j = 0; j < verts.size(); j++) {
Vector3 v = verts[j];
@@ -373,7 +368,6 @@ void MeshInstance3D::create_debug_tangents() {
}
if (lines.size()) {
-
Ref<StandardMaterial3D> sm;
sm.instance();
@@ -397,16 +391,16 @@ void MeshInstance3D::create_debug_tangents() {
add_child(mi);
#ifdef TOOLS_ENABLED
- if (this == get_tree()->get_edited_scene_root())
+ if (this == get_tree()->get_edited_scene_root()) {
mi->set_owner(this);
- else
+ } else {
mi->set_owner(get_owner());
+ }
#endif
}
}
void MeshInstance3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MeshInstance3D::set_mesh);
ClassDB::bind_method(D_METHOD("get_mesh"), &MeshInstance3D::get_mesh);
ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &MeshInstance3D::set_skeleton_path);
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index 914148f427..4434e305e8 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -37,7 +37,6 @@
#include "scene/resources/skin.h"
class MeshInstance3D : public GeometryInstance3D {
-
GDCLASS(MeshInstance3D, GeometryInstance3D);
protected:
@@ -48,7 +47,6 @@ protected:
NodePath skeleton_path;
struct BlendShapeTrack {
-
int idx;
float value;
BlendShapeTrack() {
@@ -94,8 +92,8 @@ public:
void create_debug_tangents();
- virtual AABB get_aabb() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual AABB get_aabb() const override;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
MeshInstance3D();
~MeshInstance3D();
diff --git a/scene/3d/multimesh_instance_3d.cpp b/scene/3d/multimesh_instance_3d.cpp
index a625a34283..88dff111f7 100644
--- a/scene/3d/multimesh_instance_3d.cpp
+++ b/scene/3d/multimesh_instance_3d.cpp
@@ -31,37 +31,34 @@
#include "multimesh_instance_3d.h"
void MultiMeshInstance3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_multimesh", "multimesh"), &MultiMeshInstance3D::set_multimesh);
ClassDB::bind_method(D_METHOD("get_multimesh"), &MultiMeshInstance3D::get_multimesh);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multimesh", PROPERTY_HINT_RESOURCE_TYPE, "MultiMesh"), "set_multimesh", "get_multimesh");
}
void MultiMeshInstance3D::set_multimesh(const Ref<MultiMesh> &p_multimesh) {
-
multimesh = p_multimesh;
- if (multimesh.is_valid())
+ if (multimesh.is_valid()) {
set_base(multimesh->get_rid());
- else
+ } else {
set_base(RID());
+ }
}
Ref<MultiMesh> MultiMeshInstance3D::get_multimesh() const {
-
return multimesh;
}
Vector<Face3> MultiMeshInstance3D::get_faces(uint32_t p_usage_flags) const {
-
return Vector<Face3>();
}
AABB MultiMeshInstance3D::get_aabb() const {
-
- if (multimesh.is_null())
+ if (multimesh.is_null()) {
return AABB();
- else
+ } else {
return multimesh->get_aabb();
+ }
}
MultiMeshInstance3D::MultiMeshInstance3D() {
diff --git a/scene/3d/multimesh_instance_3d.h b/scene/3d/multimesh_instance_3d.h
index 87ec9e120e..6e075b7f7f 100644
--- a/scene/3d/multimesh_instance_3d.h
+++ b/scene/3d/multimesh_instance_3d.h
@@ -44,12 +44,12 @@ protected:
// bind helpers
public:
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
void set_multimesh(const Ref<MultiMesh> &p_multimesh);
Ref<MultiMesh> get_multimesh() const;
- virtual AABB get_aabb() const;
+ virtual AABB get_aabb() const override;
MultiMeshInstance3D();
~MultiMeshInstance3D();
diff --git a/scene/3d/navigation_3d.cpp b/scene/3d/navigation_3d.cpp
index f880f65d37..851966db2b 100644
--- a/scene/3d/navigation_3d.cpp
+++ b/scene/3d/navigation_3d.cpp
@@ -33,7 +33,6 @@
#include "servers/navigation_server_3d.h"
Vector<Vector3> Navigation3D::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) const {
-
return NavigationServer3D::get_singleton()->map_get_path(map, p_start, p_end, p_optimize);
}
@@ -54,13 +53,11 @@ RID Navigation3D::get_closest_point_owner(const Vector3 &p_point) const {
}
void Navigation3D::set_up_vector(const Vector3 &p_up) {
-
up = p_up;
NavigationServer3D::get_singleton()->map_set_up(map, up);
}
Vector3 Navigation3D::get_up_vector() const {
-
return up;
}
@@ -75,7 +72,6 @@ void Navigation3D::set_edge_connection_margin(float p_edge_connection_margin) {
}
void Navigation3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("get_rid"), &Navigation3D::get_rid);
ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation3D::get_simple_path, DEFVAL(true));
@@ -104,18 +100,16 @@ void Navigation3D::_notification(int p_what) {
NavigationServer3D::get_singleton()->map_set_active(map, true);
} break;
case NOTIFICATION_EXIT_TREE: {
-
NavigationServer3D::get_singleton()->map_set_active(map, false);
} break;
}
}
Navigation3D::Navigation3D() {
-
map = NavigationServer3D::get_singleton()->map_create();
set_cell_size(0.3);
- set_edge_connection_margin(5.0); // Five meters, depends alot on the agents radius
+ set_edge_connection_margin(5.0); // Five meters, depends a lot on the agent's radius
up = Vector3(0, 1, 0);
}
diff --git a/scene/3d/navigation_3d.h b/scene/3d/navigation_3d.h
index daa9558125..890caed171 100644
--- a/scene/3d/navigation_3d.h
+++ b/scene/3d/navigation_3d.h
@@ -35,7 +35,6 @@
#include "scene/3d/node_3d.h"
class Navigation3D : public Node3D {
-
GDCLASS(Navigation3D, Node3D);
RID map;
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index 0449ab15b7..f9f8f276a3 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -30,12 +30,11 @@
#include "navigation_agent_3d.h"
-#include "core/engine.h"
+#include "core/config/engine.h"
#include "scene/3d/navigation_3d.h"
#include "servers/navigation_server_3d.h"
void NavigationAgent3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent3D::set_target_desired_distance);
ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent3D::get_target_desired_distance);
@@ -99,7 +98,6 @@ void NavigationAgent3D::_bind_methods() {
void NavigationAgent3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
-
agent_parent = Object::cast_to<Node3D>(get_parent());
NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
@@ -110,10 +108,11 @@ void NavigationAgent3D::_notification(int p_what) {
Node *p = get_parent();
while (p != nullptr) {
nav = Object::cast_to<Navigation3D>(p);
- if (nav != nullptr)
+ if (nav != nullptr) {
p = nullptr;
- else
+ } else {
p = p->get_parent();
+ }
}
set_navigation(nav);
@@ -128,7 +127,6 @@ void NavigationAgent3D::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (agent_parent) {
-
NavigationServer3D::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().origin);
if (!target_reached) {
if (distance_to_target() < target_desired_distance) {
@@ -141,16 +139,7 @@ void NavigationAgent3D::_notification(int p_what) {
}
}
-NavigationAgent3D::NavigationAgent3D() :
- agent_parent(nullptr),
- navigation(nullptr),
- agent(RID()),
- target_desired_distance(1.0),
- navigation_height_offset(0.0),
- path_max_distance(3.0),
- velocity_submitted(false),
- target_reached(false),
- navigation_finished(true) {
+NavigationAgent3D::NavigationAgent3D() {
agent = NavigationServer3D::get_singleton()->agent_create();
set_neighbor_dist(50.0);
set_max_neighbors(10);
@@ -166,8 +155,9 @@ NavigationAgent3D::~NavigationAgent3D() {
}
void NavigationAgent3D::set_navigation(Navigation3D *p_nav) {
- if (navigation == p_nav)
+ if (navigation == p_nav) {
return; // Pointless
+ }
navigation = p_nav;
NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid());
@@ -297,18 +287,28 @@ void NavigationAgent3D::_avoidance_done(Vector3 p_new_velocity) {
}
String NavigationAgent3D::get_configuration_warning() const {
+ String warning = Node::get_configuration_warning();
+
if (!Object::cast_to<Node3D>(get_parent())) {
- return TTR("The NavigationAgent3D can be used only under a spatial node.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("The NavigationAgent3D can be used only under a spatial node.");
}
- return String();
+ return warning;
}
void NavigationAgent3D::update_navigation() {
-
- if (agent_parent == nullptr) return;
- if (navigation == nullptr) return;
- if (update_frame_id == Engine::get_singleton()->get_physics_frames()) return;
+ if (agent_parent == nullptr) {
+ return;
+ }
+ if (navigation == nullptr) {
+ return;
+ }
+ if (update_frame_id == Engine::get_singleton()->get_physics_frames()) {
+ return;
+ }
update_frame_id = Engine::get_singleton()->get_physics_frames();
@@ -328,7 +328,7 @@ void NavigationAgent3D::update_navigation() {
segment[1] = navigation_path[nav_path_index];
segment[0].y -= navigation_height_offset;
segment[1].y -= navigation_height_offset;
- Vector3 p = Geometry::get_closest_point_to_segment(o, segment);
+ Vector3 p = Geometry3D::get_closest_point_to_segment(o, segment);
if (o.distance_to(p) >= path_max_distance) {
// To faraway, reload path
reload_path = true;
@@ -343,8 +343,9 @@ void NavigationAgent3D::update_navigation() {
emit_signal("path_changed");
}
- if (navigation_path.size() == 0)
+ if (navigation_path.size() == 0) {
return;
+ }
// Check if we can advance the navigation path
if (navigation_finished == false) {
diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h
index 3558b4e51b..dcfd302561 100644
--- a/scene/3d/navigation_agent_3d.h
+++ b/scene/3d/navigation_agent_3d.h
@@ -31,7 +31,7 @@
#ifndef NAVIGATION_AGENT_H
#define NAVIGATION_AGENT_H
-#include "core/vector.h"
+#include "core/templates/vector.h"
#include "scene/main/node.h"
class Node3D;
@@ -40,31 +40,31 @@ class Navigation3D;
class NavigationAgent3D : public Node {
GDCLASS(NavigationAgent3D, Node);
- Node3D *agent_parent;
- Navigation3D *navigation;
+ Node3D *agent_parent = nullptr;
+ Navigation3D *navigation = nullptr;
RID agent;
- real_t target_desired_distance;
+ real_t target_desired_distance = 1.0;
real_t radius;
- real_t navigation_height_offset;
+ real_t navigation_height_offset = 0.0;
bool ignore_y;
real_t neighbor_dist;
int max_neighbors;
real_t time_horizon;
real_t max_speed;
- real_t path_max_distance;
+ real_t path_max_distance = 3.0;
Vector3 target_location;
Vector<Vector3> navigation_path;
int nav_path_index;
- bool velocity_submitted;
+ bool velocity_submitted = false;
Vector3 prev_safe_velocity;
/// The submitted target velocity
Vector3 target_velocity;
- bool target_reached;
- bool navigation_finished;
+ bool target_reached = false;
+ bool navigation_finished = true;
// No initialized on purpose
uint32_t update_frame_id;
@@ -153,7 +153,7 @@ public:
void set_velocity(Vector3 p_velocity);
void _avoidance_done(Vector3 p_new_velocity);
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
private:
void update_navigation();
diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp
index 2ee2008799..adbff06ed6 100644
--- a/scene/3d/navigation_obstacle_3d.cpp
+++ b/scene/3d/navigation_obstacle_3d.cpp
@@ -36,7 +36,6 @@
#include "servers/navigation_server_3d.h"
void NavigationObstacle3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle3D::set_navigation_node);
ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle3D::get_navigation_node);
}
@@ -44,7 +43,6 @@ void NavigationObstacle3D::_bind_methods() {
void NavigationObstacle3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
-
update_agent_shape();
// Search the navigation node and set it
@@ -53,10 +51,11 @@ void NavigationObstacle3D::_notification(int p_what) {
Node *p = get_parent();
while (p != nullptr) {
nav = Object::cast_to<Navigation3D>(p);
- if (nav != nullptr)
+ if (nav != nullptr) {
p = nullptr;
- else
+ } else {
p = p->get_parent();
+ }
}
set_navigation(nav);
@@ -76,7 +75,6 @@ void NavigationObstacle3D::_notification(int p_what) {
PhysicsBody3D *rigid = Object::cast_to<PhysicsBody3D>(get_parent());
if (rigid) {
-
Vector3 v = rigid->get_linear_velocity();
NavigationServer3D::get_singleton()->agent_set_velocity(agent, v);
NavigationServer3D::get_singleton()->agent_set_target_velocity(agent, v);
@@ -86,9 +84,7 @@ void NavigationObstacle3D::_notification(int p_what) {
}
}
-NavigationObstacle3D::NavigationObstacle3D() :
- navigation(nullptr),
- agent(RID()) {
+NavigationObstacle3D::NavigationObstacle3D() {
agent = NavigationServer3D::get_singleton()->agent_create();
}
@@ -98,8 +94,9 @@ NavigationObstacle3D::~NavigationObstacle3D() {
}
void NavigationObstacle3D::set_navigation(Navigation3D *p_nav) {
- if (navigation == p_nav)
+ if (navigation == p_nav) {
return; // Pointless
+ }
navigation = p_nav;
NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid());
@@ -116,12 +113,16 @@ Node *NavigationObstacle3D::get_navigation_node() const {
}
String NavigationObstacle3D::get_configuration_warning() const {
- if (!Object::cast_to<Node3D>(get_parent())) {
+ String warning = Node::get_configuration_warning();
- return TTR("The NavigationObstacle3D only serves to provide collision avoidance to a spatial object.");
+ if (!Object::cast_to<Node3D>(get_parent())) {
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("The NavigationObstacle3D only serves to provide collision avoidance to a spatial object.");
}
- return String();
+ return warning;
}
void NavigationObstacle3D::update_agent_shape() {
@@ -151,8 +152,9 @@ void NavigationObstacle3D::update_agent_shape() {
radius *= MAX(s.x, MAX(s.y, s.z));
}
- if (radius == 0.0)
+ if (radius == 0.0) {
radius = 1.0; // Never a 0 radius
+ }
// Initialize the Agent as an object
NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
diff --git a/scene/3d/navigation_obstacle_3d.h b/scene/3d/navigation_obstacle_3d.h
index b58d7c4991..f2dc9182ca 100644
--- a/scene/3d/navigation_obstacle_3d.h
+++ b/scene/3d/navigation_obstacle_3d.h
@@ -38,7 +38,7 @@ class Navigation3D;
class NavigationObstacle3D : public Node {
GDCLASS(NavigationObstacle3D, Node);
- Navigation3D *navigation;
+ Navigation3D *navigation = nullptr;
RID agent;
@@ -62,7 +62,7 @@ public:
return agent;
}
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
private:
void update_agent_shape();
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index 043b816033..3d3467583d 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -36,21 +36,19 @@
#include "servers/navigation_server_3d.h"
void NavigationRegion3D::set_enabled(bool p_enabled) {
-
- if (enabled == p_enabled)
+ if (enabled == p_enabled) {
return;
+ }
enabled = p_enabled;
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
if (!enabled) {
-
NavigationServer3D::get_singleton()->region_set_map(region, RID());
} else {
-
if (navigation) {
-
NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid());
}
}
@@ -68,25 +66,19 @@ void NavigationRegion3D::set_enabled(bool p_enabled) {
}
bool NavigationRegion3D::is_enabled() const {
-
return enabled;
}
/////////////////////////////
void NavigationRegion3D::_notification(int p_what) {
-
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
-
Node3D *c = this;
while (c) {
-
navigation = Object::cast_to<Navigation3D>(c);
if (navigation) {
-
if (enabled) {
-
NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid());
}
break;
@@ -96,7 +88,6 @@ void NavigationRegion3D::_notification(int p_what) {
}
if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) {
-
MeshInstance3D *dm = memnew(MeshInstance3D);
dm->set_mesh(navmesh->get_debug_mesh());
if (is_enabled()) {
@@ -110,14 +101,11 @@ void NavigationRegion3D::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
-
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform());
} break;
case NOTIFICATION_EXIT_TREE: {
-
if (navigation) {
-
NavigationServer3D::get_singleton()->region_set_map(region, RID());
}
@@ -131,9 +119,9 @@ void NavigationRegion3D::_notification(int p_what) {
}
void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh) {
-
- if (p_navmesh == navmesh)
+ if (p_navmesh == navmesh) {
return;
+ }
if (navmesh.is_valid()) {
navmesh->remove_change_receptor(this);
@@ -158,7 +146,6 @@ void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmes
}
Ref<NavigationMesh> NavigationRegion3D::get_navigation_mesh() const {
-
return navmesh;
}
@@ -176,7 +163,6 @@ void _bake_navigation_mesh(void *p_user_data) {
args->nav_region->call_deferred("_bake_finished", nav_mesh);
memdelete(args);
} else {
-
ERR_PRINT("Can't bake the navigation mesh if the `NavigationMesh` resource doesn't exist");
args->nav_region->call_deferred("_bake_finished", Ref<NavigationMesh>());
memdelete(args);
@@ -199,27 +185,35 @@ void NavigationRegion3D::_bake_finished(Ref<NavigationMesh> p_nav_mesh) {
}
String NavigationRegion3D::get_configuration_warning() const {
-
- if (!is_visible_in_tree() || !is_inside_tree())
+ if (!is_visible_in_tree() || !is_inside_tree()) {
return String();
+ }
+
+ String warning = Node3D::get_configuration_warning();
if (!navmesh.is_valid()) {
- return TTR("A NavigationMesh resource must be set or created for this node to work.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("A NavigationMesh resource must be set or created for this node to work.");
}
+
const Node3D *c = this;
while (c) {
-
- if (Object::cast_to<Navigation3D>(c))
- return String();
+ if (Object::cast_to<Navigation3D>(c)) {
+ return warning;
+ }
c = Object::cast_to<Node3D>(c->get_parent());
}
- return TTR("NavigationRegion3D must be a child or grandchild to a Navigation3D node. It only provides navigation data.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ return warning + TTR("NavigationRegion3D must be a child or grandchild to a Navigation3D node. It only provides navigation data.");
}
void NavigationRegion3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationRegion3D::set_navigation_mesh);
ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationRegion3D::get_navigation_mesh);
@@ -242,18 +236,13 @@ void NavigationRegion3D::_changed_callback(Object *p_changed, const char *p_prop
}
NavigationRegion3D::NavigationRegion3D() {
-
- enabled = true;
set_notify_transform(true);
region = NavigationServer3D::get_singleton()->region_create();
-
- navigation = nullptr;
- debug_view = nullptr;
- bake_thread = nullptr;
}
NavigationRegion3D::~NavigationRegion3D() {
- if (navmesh.is_valid())
+ if (navmesh.is_valid()) {
navmesh->remove_change_receptor(this);
+ }
NavigationServer3D::get_singleton()->free(region);
}
diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h
index ae071e6b7a..4b1d59206b 100644
--- a/scene/3d/navigation_region_3d.h
+++ b/scene/3d/navigation_region_3d.h
@@ -38,21 +38,20 @@
class Navigation3D;
class NavigationRegion3D : public Node3D {
-
GDCLASS(NavigationRegion3D, Node3D);
- bool enabled;
+ bool enabled = true;
RID region;
Ref<NavigationMesh> navmesh;
- Navigation3D *navigation;
- Node *debug_view;
- Thread *bake_thread;
+ Navigation3D *navigation = nullptr;
+ Node *debug_view = nullptr;
+ Thread *bake_thread = nullptr;
protected:
void _notification(int p_what);
static void _bind_methods();
- void _changed_callback(Object *p_changed, const char *p_prop);
+ void _changed_callback(Object *p_changed, const char *p_prop) override;
public:
void set_enabled(bool p_enabled);
@@ -66,7 +65,7 @@ public:
void bake_navigation_mesh();
void _bake_finished(Ref<NavigationMesh> p_nav_mesh);
- String get_configuration_warning() const;
+ String get_configuration_warning() const override;
NavigationRegion3D();
~NavigationRegion3D();
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 0b7407e049..e8005f38ed 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -30,8 +30,8 @@
#include "node_3d.h"
-#include "core/engine.h"
-#include "core/message_queue.h"
+#include "core/config/engine.h"
+#include "core/object/message_queue.h"
#include "scene/main/scene_tree.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
@@ -74,7 +74,6 @@ Node3DGizmo::Node3DGizmo() {
}
void Node3D::_notify_dirty() {
-
#ifdef TOOLS_ENABLED
if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) {
#else
@@ -90,8 +89,8 @@ void Node3D::_update_local_transform() const {
data.dirty &= ~DIRTY_LOCAL;
}
-void Node3D::_propagate_transform_changed(Node3D *p_origin) {
+void Node3D::_propagate_transform_changed(Node3D *p_origin) {
if (!is_inside_tree()) {
return;
}
@@ -104,9 +103,9 @@ void Node3D::_propagate_transform_changed(Node3D *p_origin) {
data.children_lock++;
for (List<Node3D *>::Element *E = data.children.front(); E; E = E->next()) {
-
- if (E->get()->data.toplevel_active)
- continue; //don't propagate to a toplevel
+ if (E->get()->data.top_level_active) {
+ continue; //don't propagate to a top_level
+ }
E->get()->_propagate_transform_changed(p_origin);
}
#ifdef TOOLS_ENABLED
@@ -122,27 +121,27 @@ void Node3D::_propagate_transform_changed(Node3D *p_origin) {
}
void Node3D::_notification(int p_what) {
-
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
ERR_FAIL_COND(!get_tree());
Node *p = get_parent();
- if (p)
+ if (p) {
data.parent = Object::cast_to<Node3D>(p);
+ }
- if (data.parent)
+ if (data.parent) {
data.C = data.parent->data.children.push_back(this);
- else
+ } else {
data.C = nullptr;
+ }
- if (data.toplevel && !Engine::get_singleton()->is_editor_hint()) {
-
+ if (data.top_level && !Engine::get_singleton()->is_editor_hint()) {
if (data.parent) {
data.local_transform = data.parent->get_global_transform() * get_transform();
data.dirty = DIRTY_VECTORS; //global is always dirty upon entering a scene
}
- data.toplevel_active = true;
+ data.top_level_active = true;
}
data.dirty |= DIRTY_GLOBAL; //global is always dirty upon entering a scene
@@ -152,18 +151,18 @@ void Node3D::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
-
notification(NOTIFICATION_EXIT_WORLD, true);
- if (xform_change.in_list())
+ if (xform_change.in_list()) {
get_tree()->xform_change_list.remove(&xform_change);
- if (data.C)
+ }
+ if (data.C) {
data.parent->data.children.erase(data.C);
+ }
data.parent = nullptr;
data.C = nullptr;
- data.toplevel_active = false;
+ data.top_level_active = false;
} break;
case NOTIFICATION_ENTER_WORLD: {
-
data.inside_world = true;
data.viewport = nullptr;
Node *parent = get_parent();
@@ -175,16 +174,13 @@ void Node3D::_notification(int p_what) {
ERR_FAIL_COND(!data.viewport);
if (get_script_instance()) {
-
- get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_enter_world, nullptr, 0);
+ get_script_instance()->call(SceneStringNames::get_singleton()->_enter_world);
}
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) {
-
//get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,SceneStringNames::get_singleton()->_spatial_editor_group,SceneStringNames::get_singleton()->_request_gizmo,this);
get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
if (!data.gizmo_disabled) {
-
if (data.gizmo.is_valid()) {
data.gizmo->create();
if (is_visible_in_tree()) {
@@ -198,7 +194,6 @@ void Node3D::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_WORLD: {
-
#ifdef TOOLS_ENABLED
if (data.gizmo.is_valid()) {
data.gizmo->free();
@@ -207,8 +202,7 @@ void Node3D::_notification(int p_what) {
#endif
if (get_script_instance()) {
-
- get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_exit_world, nullptr, 0);
+ get_script_instance()->call(SceneStringNames::get_singleton()->_exit_world);
}
data.viewport = nullptr;
@@ -217,7 +211,6 @@ void Node3D::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
-
#ifdef TOOLS_ENABLED
if (data.gizmo.is_valid()) {
data.gizmo->transform();
@@ -231,7 +224,6 @@ void Node3D::_notification(int p_what) {
}
void Node3D::set_transform(const Transform &p_transform) {
-
data.local_transform = p_transform;
data.dirty |= DIRTY_VECTORS;
_change_notify("translation");
@@ -245,9 +237,8 @@ void Node3D::set_transform(const Transform &p_transform) {
}
void Node3D::set_global_transform(const Transform &p_transform) {
-
Transform xform =
- (data.parent && !data.toplevel_active) ?
+ (data.parent && !data.top_level_active) ?
data.parent->get_global_transform().affine_inverse() * p_transform :
p_transform;
@@ -255,30 +246,24 @@ void Node3D::set_global_transform(const Transform &p_transform) {
}
Transform Node3D::get_transform() const {
-
if (data.dirty & DIRTY_LOCAL) {
-
_update_local_transform();
}
return data.local_transform;
}
-Transform Node3D::get_global_transform() const {
+Transform Node3D::get_global_transform() const {
ERR_FAIL_COND_V(!is_inside_tree(), Transform());
if (data.dirty & DIRTY_GLOBAL) {
-
if (data.dirty & DIRTY_LOCAL) {
-
_update_local_transform();
}
- if (data.parent && !data.toplevel_active) {
-
+ if (data.parent && !data.top_level_active) {
data.global_transform = data.parent->get_global_transform() * data.local_transform;
} else {
-
data.global_transform = data.local_transform;
}
@@ -303,25 +288,24 @@ Transform Node3D::get_local_gizmo_transform() const {
#endif
Node3D *Node3D::get_parent_spatial() const {
-
return data.parent;
}
Transform Node3D::get_relative_transform(const Node *p_parent) const {
-
- if (p_parent == this)
+ if (p_parent == this) {
return Transform();
+ }
ERR_FAIL_COND_V(!data.parent, Transform());
- if (p_parent == data.parent)
+ if (p_parent == data.parent) {
return get_transform();
- else
+ } else {
return data.parent->get_relative_transform(p_parent) * get_transform();
+ }
}
void Node3D::set_translation(const Vector3 &p_translation) {
-
data.local_transform.origin = p_translation;
_change_notify("transform");
_propagate_transform_changed(this);
@@ -331,7 +315,6 @@ void Node3D::set_translation(const Vector3 &p_translation) {
}
void Node3D::set_rotation(const Vector3 &p_euler_rad) {
-
if (data.dirty & DIRTY_VECTORS) {
data.scale = data.local_transform.basis.get_scale();
data.dirty &= ~DIRTY_VECTORS;
@@ -347,12 +330,10 @@ void Node3D::set_rotation(const Vector3 &p_euler_rad) {
}
void Node3D::set_rotation_degrees(const Vector3 &p_euler_deg) {
-
set_rotation(p_euler_deg * Math_PI / 180.0);
}
void Node3D::set_scale(const Vector3 &p_scale) {
-
if (data.dirty & DIRTY_VECTORS) {
data.rotation = data.local_transform.basis.get_rotation();
data.dirty &= ~DIRTY_VECTORS;
@@ -368,12 +349,10 @@ void Node3D::set_scale(const Vector3 &p_scale) {
}
Vector3 Node3D::get_translation() const {
-
return data.local_transform.origin;
}
Vector3 Node3D::get_rotation() const {
-
if (data.dirty & DIRTY_VECTORS) {
data.scale = data.local_transform.basis.get_scale();
data.rotation = data.local_transform.basis.get_rotation();
@@ -385,12 +364,10 @@ Vector3 Node3D::get_rotation() const {
}
Vector3 Node3D::get_rotation_degrees() const {
-
return get_rotation() * 180.0 / Math_PI;
}
Vector3 Node3D::get_scale() const {
-
if (data.dirty & DIRTY_VECTORS) {
data.scale = data.local_transform.basis.get_scale();
data.rotation = data.local_transform.basis.get_rotation();
@@ -402,32 +379,35 @@ Vector3 Node3D::get_scale() const {
}
void Node3D::update_gizmo() {
-
#ifdef TOOLS_ENABLED
- if (!is_inside_world())
+ if (!is_inside_world()) {
return;
- if (!data.gizmo.is_valid())
+ }
+ if (!data.gizmo.is_valid()) {
get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
- if (!data.gizmo.is_valid())
+ }
+ if (!data.gizmo.is_valid()) {
return;
- if (data.gizmo_dirty)
+ }
+ if (data.gizmo_dirty) {
return;
+ }
data.gizmo_dirty = true;
MessageQueue::get_singleton()->push_call(this, "_update_gizmo");
#endif
}
void Node3D::set_gizmo(const Ref<Node3DGizmo> &p_gizmo) {
-
#ifdef TOOLS_ENABLED
- if (data.gizmo_disabled)
+ if (data.gizmo_disabled) {
return;
- if (data.gizmo.is_valid() && is_inside_world())
+ }
+ if (data.gizmo.is_valid() && is_inside_world()) {
data.gizmo->free();
+ }
data.gizmo = p_gizmo;
if (data.gizmo.is_valid() && is_inside_world()) {
-
data.gizmo->create();
if (is_visible_in_tree()) {
data.gizmo->redraw();
@@ -439,7 +419,6 @@ void Node3D::set_gizmo(const Ref<Node3DGizmo> &p_gizmo) {
}
Ref<Node3DGizmo> Node3D::get_gizmo() const {
-
#ifdef TOOLS_ENABLED
return data.gizmo;
@@ -450,32 +429,32 @@ Ref<Node3DGizmo> Node3D::get_gizmo() const {
}
void Node3D::_update_gizmo() {
-
#ifdef TOOLS_ENABLED
- if (!is_inside_world())
+ if (!is_inside_world()) {
return;
+ }
data.gizmo_dirty = false;
if (data.gizmo.is_valid()) {
- if (is_visible_in_tree())
+ if (is_visible_in_tree()) {
data.gizmo->redraw();
- else
+ } else {
data.gizmo->clear();
+ }
}
#endif
}
#ifdef TOOLS_ENABLED
void Node3D::set_disable_gizmo(bool p_enabled) {
-
data.gizmo_disabled = p_enabled;
- if (!p_enabled && data.gizmo.is_valid())
+ if (!p_enabled && data.gizmo.is_valid()) {
data.gizmo = Ref<Node3DGizmo>();
+ }
}
#endif
void Node3D::set_disable_scale(bool p_enabled) {
-
data.disable_scale = p_enabled;
}
@@ -483,85 +462,84 @@ bool Node3D::is_scale_disabled() const {
return data.disable_scale;
}
-void Node3D::set_as_toplevel(bool p_enabled) {
-
- if (data.toplevel == p_enabled)
+void Node3D::set_as_top_level(bool p_enabled) {
+ if (data.top_level == p_enabled) {
return;
+ }
if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) {
-
- if (p_enabled)
+ if (p_enabled) {
set_transform(get_global_transform());
- else if (data.parent)
+ } else if (data.parent) {
set_transform(data.parent->get_global_transform().affine_inverse() * get_global_transform());
+ }
- data.toplevel = p_enabled;
- data.toplevel_active = p_enabled;
+ data.top_level = p_enabled;
+ data.top_level_active = p_enabled;
} else {
- data.toplevel = p_enabled;
+ data.top_level = p_enabled;
}
}
-bool Node3D::is_set_as_toplevel() const {
-
- return data.toplevel;
+bool Node3D::is_set_as_top_level() const {
+ return data.top_level;
}
-Ref<World3D> Node3D::get_world() const {
-
+Ref<World3D> Node3D::get_world_3d() const {
ERR_FAIL_COND_V(!is_inside_world(), Ref<World3D>());
ERR_FAIL_COND_V(!data.viewport, Ref<World3D>());
- return data.viewport->find_world();
+ return data.viewport->find_world_3d();
}
void Node3D::_propagate_visibility_changed() {
-
notification(NOTIFICATION_VISIBILITY_CHANGED);
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
_change_notify("visible");
#ifdef TOOLS_ENABLED
- if (data.gizmo.is_valid())
+ if (data.gizmo.is_valid()) {
_update_gizmo();
+ }
#endif
for (List<Node3D *>::Element *E = data.children.front(); E; E = E->next()) {
-
Node3D *c = E->get();
- if (!c || !c->data.visible)
+ if (!c || !c->data.visible) {
continue;
+ }
c->_propagate_visibility_changed();
}
}
void Node3D::show() {
-
- if (data.visible)
+ if (data.visible) {
return;
+ }
data.visible = true;
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
_propagate_visibility_changed();
}
void Node3D::hide() {
-
- if (!data.visible)
+ if (!data.visible) {
return;
+ }
data.visible = false;
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
_propagate_visibility_changed();
}
bool Node3D::is_visible_in_tree() const {
-
const Node3D *s = this;
while (s) {
@@ -575,15 +553,14 @@ bool Node3D::is_visible_in_tree() const {
}
void Node3D::set_visible(bool p_visible) {
-
- if (p_visible)
+ if (p_visible) {
show();
- else
+ } else {
hide();
+ }
}
bool Node3D::is_visible() const {
-
return data.visible;
}
@@ -594,34 +571,30 @@ void Node3D::rotate_object_local(const Vector3 &p_axis, float p_angle) {
}
void Node3D::rotate(const Vector3 &p_axis, float p_angle) {
-
Transform t = get_transform();
t.basis.rotate(p_axis, p_angle);
set_transform(t);
}
void Node3D::rotate_x(float p_angle) {
-
Transform t = get_transform();
t.basis.rotate(Vector3(1, 0, 0), p_angle);
set_transform(t);
}
void Node3D::rotate_y(float p_angle) {
-
Transform t = get_transform();
t.basis.rotate(Vector3(0, 1, 0), p_angle);
set_transform(t);
}
-void Node3D::rotate_z(float p_angle) {
+void Node3D::rotate_z(float p_angle) {
Transform t = get_transform();
t.basis.rotate(Vector3(0, 0, 1), p_angle);
set_transform(t);
}
void Node3D::translate(const Vector3 &p_offset) {
-
Transform t = get_transform();
t.translate(p_offset);
set_transform(t);
@@ -636,7 +609,6 @@ void Node3D::translate_object_local(const Vector3 &p_offset) {
}
void Node3D::scale(const Vector3 &p_ratio) {
-
Transform t = get_transform();
t.basis.scale(p_ratio);
set_transform(t);
@@ -649,14 +621,12 @@ void Node3D::scale_object_local(const Vector3 &p_scale) {
}
void Node3D::global_rotate(const Vector3 &p_axis, float p_angle) {
-
Transform t = get_global_transform();
t.basis.rotate(p_axis, p_angle);
set_global_transform(t);
}
void Node3D::global_scale(const Vector3 &p_scale) {
-
Transform t = get_global_transform();
t.basis.scale(p_scale);
set_global_transform(t);
@@ -669,25 +639,21 @@ void Node3D::global_translate(const Vector3 &p_offset) {
}
void Node3D::orthonormalize() {
-
Transform t = get_transform();
t.orthonormalize();
set_transform(t);
}
void Node3D::set_identity() {
-
set_transform(Transform());
}
void Node3D::look_at(const Vector3 &p_target, const Vector3 &p_up) {
-
Vector3 origin(get_global_transform().origin);
look_at_from_position(origin, p_target, p_up);
}
void Node3D::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up) {
-
ERR_FAIL_COND_MSG(p_pos == p_target, "Node origin and target are in the same position, look_at() failed.");
ERR_FAIL_COND_MSG(p_up.cross(p_target - p_pos) == Vector3(), "Up vector and direction between node origin and target are aligned, look_at() failed.");
@@ -701,12 +667,10 @@ void Node3D::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target
}
Vector3 Node3D::to_local(Vector3 p_global) const {
-
return get_global_transform().affine_inverse().xform(p_global);
}
Vector3 Node3D::to_global(Vector3 p_local) const {
-
return get_global_transform().xform(p_local);
}
@@ -737,7 +701,6 @@ void Node3D::force_update_transform() {
}
void Node3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_transform", "local"), &Node3D::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &Node3D::get_transform);
ClassDB::bind_method(D_METHOD("set_translation", "translation"), &Node3D::set_translation);
@@ -752,11 +715,11 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_global_transform"), &Node3D::get_global_transform);
ClassDB::bind_method(D_METHOD("get_parent_spatial"), &Node3D::get_parent_spatial);
ClassDB::bind_method(D_METHOD("set_ignore_transform_notification", "enabled"), &Node3D::set_ignore_transform_notification);
- ClassDB::bind_method(D_METHOD("set_as_toplevel", "enable"), &Node3D::set_as_toplevel);
- ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Node3D::is_set_as_toplevel);
+ ClassDB::bind_method(D_METHOD("set_as_top_level", "enable"), &Node3D::set_as_top_level);
+ ClassDB::bind_method(D_METHOD("is_set_as_top_level"), &Node3D::is_set_as_top_level);
ClassDB::bind_method(D_METHOD("set_disable_scale", "disable"), &Node3D::set_disable_scale);
ClassDB::bind_method(D_METHOD("is_scale_disabled"), &Node3D::is_scale_disabled);
- ClassDB::bind_method(D_METHOD("get_world"), &Node3D::get_world);
+ ClassDB::bind_method(D_METHOD("get_world_3d"), &Node3D::get_world_3d);
ClassDB::bind_method(D_METHOD("force_update_transform"), &Node3D::force_update_transform);
@@ -810,6 +773,7 @@ void Node3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_NONE, "", 0), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level");
ADD_GROUP("Matrix", "");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform");
ADD_GROUP("Visibility", "");
@@ -821,13 +785,12 @@ void Node3D::_bind_methods() {
Node3D::Node3D() :
xform_change(this) {
-
data.dirty = DIRTY_NONE;
data.children_lock = 0;
data.ignore_notification = false;
- data.toplevel = false;
- data.toplevel_active = false;
+ data.top_level = false;
+ data.top_level_active = false;
data.scale = Vector3(1, 1, 1);
data.viewport = nullptr;
data.inside_world = false;
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index f97a8a97dc..5fb421c930 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -35,7 +35,6 @@
#include "scene/main/scene_tree.h"
class Node3DGizmo : public Reference {
-
GDCLASS(Node3DGizmo, Reference);
public:
@@ -50,7 +49,6 @@ public:
};
class Node3D : public Node {
-
GDCLASS(Node3D, Node);
OBJ_CATEGORY("3D");
@@ -64,7 +62,6 @@ class Node3D : public Node {
mutable SelfList<Node> xform_change;
struct Data {
-
mutable Transform global_transform;
mutable Transform local_transform;
mutable Vector3 rotation;
@@ -74,8 +71,8 @@ class Node3D : public Node {
Viewport *viewport;
- bool toplevel_active;
- bool toplevel;
+ bool top_level_active;
+ bool top_level;
bool inside_world;
int children_lock;
@@ -114,7 +111,6 @@ protected:
public:
enum {
-
NOTIFICATION_TRANSFORM_CHANGED = SceneTree::NOTIFICATION_TRANSFORM_CHANGED,
NOTIFICATION_ENTER_WORLD = 41,
NOTIFICATION_EXIT_WORLD = 42,
@@ -124,7 +120,7 @@ public:
Node3D *get_parent_spatial() const;
- Ref<World3D> get_world() const;
+ Ref<World3D> get_world_3d() const;
void set_translation(const Vector3 &p_translation);
void set_rotation(const Vector3 &p_euler_rad);
@@ -147,8 +143,8 @@ public:
virtual Transform get_local_gizmo_transform() const;
#endif
- void set_as_toplevel(bool p_enabled);
- bool is_set_as_toplevel() const;
+ void set_as_top_level(bool p_enabled);
+ bool is_set_as_top_level() const;
void set_disable_scale(bool p_enabled);
bool is_scale_disabled() const;
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index 4a425d1e0e..f25a64c567 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -30,16 +30,16 @@
#include "path_3d.h"
-#include "core/engine.h"
+#include "core/config/engine.h"
#include "scene/scene_string_names.h"
void Path3D::_notification(int p_what) {
}
void Path3D::_curve_changed() {
-
- if (is_inside_tree() && Engine::get_singleton()->is_editor_hint())
+ if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) {
update_gizmo();
+ }
if (is_inside_tree()) {
emit_signal("curve_changed");
}
@@ -57,7 +57,6 @@ void Path3D::_curve_changed() {
}
void Path3D::set_curve(const Ref<Curve3D> &p_curve) {
-
if (curve.is_valid()) {
curve->disconnect("changed", callable_mp(this, &Path3D::_curve_changed));
}
@@ -71,35 +70,29 @@ void Path3D::set_curve(const Ref<Curve3D> &p_curve) {
}
Ref<Curve3D> Path3D::get_curve() const {
-
return curve;
}
void Path3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_curve", "curve"), &Path3D::set_curve);
ClassDB::bind_method(D_METHOD("get_curve"), &Path3D::get_curve);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), "set_curve", "get_curve");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT), "set_curve", "get_curve");
ADD_SIGNAL(MethodInfo("curve_changed"));
}
-Path3D::Path3D() {
-
- set_curve(Ref<Curve3D>(memnew(Curve3D))); //create one by default
-}
-
//////////////
-void PathFollow3D::_update_transform() {
-
- if (!path)
+void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
+ if (!path) {
return;
+ }
Ref<Curve3D> c = path->get_curve();
- if (!c.is_valid())
+ if (!c.is_valid()) {
return;
+ }
if (delta_offset == 0) {
return;
@@ -124,13 +117,13 @@ void PathFollow3D::_update_transform() {
// will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used
if (rotation_mode == ROTATION_ORIENTED) {
-
Vector3 forward = c->interpolate_baked(o_next, cubic) - pos;
- if (forward.length_squared() < CMP_EPSILON2)
+ if (forward.length_squared() < CMP_EPSILON2) {
forward = Vector3(0, 0, 1);
- else
+ } else {
forward.normalize();
+ }
Vector3 up = c->interpolate_baked_up_vector(offset, true);
@@ -138,10 +131,11 @@ void PathFollow3D::_update_transform() {
Vector3 up1 = c->interpolate_baked_up_vector(o_next, true);
Vector3 axis = up.cross(up1);
- if (axis.length_squared() < CMP_EPSILON2)
+ if (axis.length_squared() < CMP_EPSILON2) {
axis = forward;
- else
+ } else {
axis.normalize();
+ }
up.rotate(axis, up.angle_to(up1) * 0.5f);
}
@@ -162,45 +156,47 @@ void PathFollow3D::_update_transform() {
t.origin = pos;
- Vector3 t_prev = (pos - c->interpolate_baked(offset - delta_offset, cubic)).normalized();
- Vector3 t_cur = (c->interpolate_baked(offset + delta_offset, cubic) - pos).normalized();
-
- Vector3 axis = t_prev.cross(t_cur);
- float dot = t_prev.dot(t_cur);
- float angle = Math::acos(CLAMP(dot, -1, 1));
-
- if (likely(!Math::is_zero_approx(angle))) {
- if (rotation_mode == ROTATION_Y) {
- // assuming we're referring to global Y-axis. is this correct?
- axis.x = 0;
- axis.z = 0;
- } else if (rotation_mode == ROTATION_XY) {
- axis.z = 0;
- } else if (rotation_mode == ROTATION_XYZ) {
- // all components are allowed
- }
+ if (p_update_xyz_rot) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree
+ Vector3 t_prev = (pos - c->interpolate_baked(offset - delta_offset, cubic)).normalized();
+ Vector3 t_cur = (c->interpolate_baked(offset + delta_offset, cubic) - pos).normalized();
+
+ Vector3 axis = t_prev.cross(t_cur);
+ float dot = t_prev.dot(t_cur);
+ float angle = Math::acos(CLAMP(dot, -1, 1));
+
+ if (likely(!Math::is_zero_approx(angle))) {
+ if (rotation_mode == ROTATION_Y) {
+ // assuming we're referring to global Y-axis. is this correct?
+ axis.x = 0;
+ axis.z = 0;
+ } else if (rotation_mode == ROTATION_XY) {
+ axis.z = 0;
+ } else if (rotation_mode == ROTATION_XYZ) {
+ // all components are allowed
+ }
- if (likely(!Math::is_zero_approx(axis.length()))) {
- t.rotate_basis(axis.normalized(), angle);
+ if (likely(!Math::is_zero_approx(axis.length()))) {
+ t.rotate_basis(axis.normalized(), angle);
+ }
}
- }
- // do the additional tilting
- float tilt_angle = c->interpolate_baked_tilt(offset);
- Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
-
- if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) {
- 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 allowed
- }
+ // do the additional tilting
+ float tilt_angle = c->interpolate_baked_tilt(offset);
+ Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
+
+ if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) {
+ 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 allowed
+ }
- if (likely(!Math::is_zero_approx(tilt_axis.length()))) {
- t.rotate_basis(tilt_axis.normalized(), tilt_angle);
+ if (likely(!Math::is_zero_approx(tilt_axis.length()))) {
+ t.rotate_basis(tilt_axis.normalized(), tilt_angle);
+ }
}
}
@@ -213,68 +209,68 @@ void PathFollow3D::_update_transform() {
}
void PathFollow3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_ENTER_TREE: {
-
Node *parent = get_parent();
if (parent) {
path = Object::cast_to<Path3D>(parent);
if (path) {
- _update_transform();
+ _update_transform(false);
}
}
} break;
case NOTIFICATION_EXIT_TREE: {
-
path = nullptr;
} break;
}
}
void PathFollow3D::set_cubic_interpolation(bool p_enable) {
-
cubic = p_enable;
}
bool PathFollow3D::get_cubic_interpolation() const {
-
return cubic;
}
void PathFollow3D::_validate_property(PropertyInfo &property) const {
-
if (property.name == "offset") {
-
float max = 10000;
- if (path && path->get_curve().is_valid())
+ if (path && path->get_curve().is_valid()) {
max = path->get_curve()->get_baked_length();
+ }
property.hint_string = "0," + rtos(max) + ",0.01,or_lesser,or_greater";
}
}
String PathFollow3D::get_configuration_warning() const {
-
- if (!is_visible_in_tree() || !is_inside_tree())
+ if (!is_visible_in_tree() || !is_inside_tree()) {
return String();
+ }
+
+ String warning = Node3D::get_configuration_warning();
if (!Object::cast_to<Path3D>(get_parent())) {
- return TTR("PathFollow3D only works when set as a child of a Path3D node.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("PathFollow3D only works when set as a child of a Path3D node.");
} else {
Path3D *path = Object::cast_to<Path3D>(get_parent());
if (path->get_curve().is_valid() && !path->get_curve()->is_up_vector_enabled() && rotation_mode == ROTATION_ORIENTED) {
- return TTR("PathFollow3D's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its parent Path3D's Curve resource.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("PathFollow3D's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its parent Path3D's Curve resource.");
}
}
- return String();
+ return warning;
}
void PathFollow3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_offset", "offset"), &PathFollow3D::set_offset);
ClassDB::bind_method(D_METHOD("get_offset"), &PathFollow3D::get_offset);
@@ -336,50 +332,46 @@ void PathFollow3D::set_offset(float p_offset) {
}
void PathFollow3D::set_h_offset(float p_h_offset) {
-
h_offset = p_h_offset;
- if (path)
+ if (path) {
_update_transform();
+ }
}
float PathFollow3D::get_h_offset() const {
-
return h_offset;
}
void PathFollow3D::set_v_offset(float p_v_offset) {
-
v_offset = p_v_offset;
- if (path)
+ if (path) {
_update_transform();
+ }
}
float PathFollow3D::get_v_offset() const {
-
return v_offset;
}
float PathFollow3D::get_offset() const {
-
return offset;
}
void PathFollow3D::set_unit_offset(float p_unit_offset) {
-
- if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length())
+ if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
set_offset(p_unit_offset * path->get_curve()->get_baked_length());
+ }
}
float PathFollow3D::get_unit_offset() const {
-
- if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length())
+ if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
return get_offset() / path->get_curve()->get_baked_length();
- else
+ } else {
return 0;
+ }
}
void PathFollow3D::set_rotation_mode(RotationMode p_rotation_mode) {
-
rotation_mode = p_rotation_mode;
update_configuration_warning();
@@ -387,22 +379,18 @@ void PathFollow3D::set_rotation_mode(RotationMode p_rotation_mode) {
}
PathFollow3D::RotationMode PathFollow3D::get_rotation_mode() const {
-
return rotation_mode;
}
void PathFollow3D::set_loop(bool p_loop) {
-
loop = p_loop;
}
bool PathFollow3D::has_loop() const {
-
return loop;
}
PathFollow3D::PathFollow3D() {
-
offset = 0;
delta_offset = 0;
h_offset = 0;
diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h
index 6f0db8c5c2..1b0f5fa4e0 100644
--- a/scene/3d/path_3d.h
+++ b/scene/3d/path_3d.h
@@ -35,7 +35,6 @@
#include "scene/resources/curve.h"
class Path3D : public Node3D {
-
GDCLASS(Path3D, Node3D);
Ref<Curve3D> curve;
@@ -50,16 +49,14 @@ public:
void set_curve(const Ref<Curve3D> &p_curve);
Ref<Curve3D> get_curve() const;
- Path3D();
+ Path3D() {}
};
class PathFollow3D : public Node3D {
-
GDCLASS(PathFollow3D, Node3D);
public:
enum RotationMode {
-
ROTATION_NONE,
ROTATION_Y,
ROTATION_XY,
@@ -77,10 +74,10 @@ private:
bool loop;
RotationMode rotation_mode;
- void _update_transform();
+ void _update_transform(bool p_update_xyz_rot = true);
protected:
- virtual void _validate_property(PropertyInfo &property) const;
+ virtual void _validate_property(PropertyInfo &property) const override;
void _notification(int p_what);
static void _bind_methods();
@@ -107,7 +104,7 @@ public:
void set_cubic_interpolation(bool p_enable);
bool get_cubic_interpolation() const;
- String get_configuration_warning() const;
+ String get_configuration_warning() const override;
PathFollow3D();
};
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 3991efc7c0..a3e00d2cc3 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -30,12 +30,11 @@
#include "physics_body_3d.h"
+#include "core/config/engine.h"
#include "core/core_string_names.h"
-#include "core/engine.h"
-#include "core/list.h"
-#include "core/method_bind_ext.gen.inc"
-#include "core/object.h"
-#include "core/rid.h"
+#include "core/object/class_db.h"
+#include "core/templates/list.h"
+#include "core/templates/rid.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/scene_string_names.h"
#include "servers/navigation_server_3d.h"
@@ -45,68 +44,60 @@
#endif
Vector3 PhysicsBody3D::get_linear_velocity() const {
-
return Vector3();
}
-Vector3 PhysicsBody3D::get_angular_velocity() const {
+Vector3 PhysicsBody3D::get_angular_velocity() const {
return Vector3();
}
float PhysicsBody3D::get_inverse_mass() const {
-
return 0;
}
void PhysicsBody3D::set_collision_layer(uint32_t p_layer) {
-
collision_layer = p_layer;
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), p_layer);
}
uint32_t PhysicsBody3D::get_collision_layer() const {
-
return collision_layer;
}
void PhysicsBody3D::set_collision_mask(uint32_t p_mask) {
-
collision_mask = p_mask;
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), p_mask);
}
uint32_t PhysicsBody3D::get_collision_mask() const {
-
return collision_mask;
}
void PhysicsBody3D::set_collision_mask_bit(int p_bit, bool p_value) {
-
uint32_t mask = get_collision_mask();
- if (p_value)
+ if (p_value) {
mask |= 1 << p_bit;
- else
+ } else {
mask &= ~(1 << p_bit);
+ }
set_collision_mask(mask);
}
bool PhysicsBody3D::get_collision_mask_bit(int p_bit) const {
-
return get_collision_mask() & (1 << p_bit);
}
void PhysicsBody3D::set_collision_layer_bit(int p_bit, bool p_value) {
-
uint32_t mask = get_collision_layer();
- if (p_value)
+ if (p_value) {
mask |= 1 << p_bit;
- else
+ } else {
mask &= ~(1 << p_bit);
+ }
set_collision_layer(mask);
}
bool PhysicsBody3D::get_collision_layer_bit(int p_bit) const {
-
return get_collision_layer() & (1 << p_bit);
}
@@ -125,7 +116,6 @@ TypedArray<PhysicsBody3D> PhysicsBody3D::get_collision_exceptions() {
}
void PhysicsBody3D::add_collision_exception_with(Node *p_node) {
-
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
@@ -133,23 +123,12 @@ void PhysicsBody3D::add_collision_exception_with(Node *p_node) {
}
void PhysicsBody3D::remove_collision_exception_with(Node *p_node) {
-
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid());
}
-void PhysicsBody3D::_set_layers(uint32_t p_mask) {
- set_collision_layer(p_mask);
- set_collision_mask(p_mask);
-}
-
-uint32_t PhysicsBody3D::_get_layers() const {
-
- return get_collision_layer();
-}
-
void PhysicsBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &PhysicsBody3D::set_collision_layer);
ClassDB::bind_method(D_METHOD("get_collision_layer"), &PhysicsBody3D::get_collision_layer);
@@ -163,9 +142,6 @@ void PhysicsBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &PhysicsBody3D::set_collision_layer_bit);
ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &PhysicsBody3D::get_collision_layer_bit);
- ClassDB::bind_method(D_METHOD("_set_layers", "mask"), &PhysicsBody3D::_set_layers);
- ClassDB::bind_method(D_METHOD("_get_layers"), &PhysicsBody3D::_get_layers);
-
ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
@@ -173,7 +149,6 @@ void PhysicsBody3D::_bind_methods() {
PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) :
CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(p_mode), false) {
-
collision_layer = 1;
collision_mask = 1;
}
@@ -198,28 +173,24 @@ Ref<PhysicsMaterial> StaticBody3D::get_physics_material_override() const {
}
void StaticBody3D::set_constant_linear_velocity(const Vector3 &p_vel) {
-
constant_linear_velocity = p_vel;
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
}
void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) {
-
constant_angular_velocity = p_vel;
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
}
Vector3 StaticBody3D::get_constant_linear_velocity() const {
-
return constant_linear_velocity;
}
-Vector3 StaticBody3D::get_constant_angular_velocity() const {
+Vector3 StaticBody3D::get_constant_angular_velocity() const {
return constant_angular_velocity;
}
void StaticBody3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity);
ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody3D::get_constant_linear_velocity);
@@ -254,7 +225,6 @@ void StaticBody3D::_reload_physics_characteristics() {
}
void RigidBody3D::_body_enter_tree(ObjectID p_id) {
-
Object *obj = ObjectDB::get_instance(p_id);
Node *node = Object::cast_to<Node>(obj);
ERR_FAIL_COND(!node);
@@ -271,7 +241,6 @@ void RigidBody3D::_body_enter_tree(ObjectID p_id) {
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
-
emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape);
}
@@ -279,7 +248,6 @@ void RigidBody3D::_body_enter_tree(ObjectID p_id) {
}
void RigidBody3D::_body_exit_tree(ObjectID p_id) {
-
Object *obj = ObjectDB::get_instance(p_id);
Node *node = Object::cast_to<Node>(obj);
ERR_FAIL_COND(!node);
@@ -294,7 +262,6 @@ void RigidBody3D::_body_exit_tree(ObjectID p_id) {
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
-
emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape);
}
@@ -302,7 +269,6 @@ void RigidBody3D::_body_exit_tree(ObjectID p_id) {
}
void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape) {
-
bool body_in = p_status == 1;
ObjectID objid = p_instance;
@@ -316,7 +282,6 @@ void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
if (body_in) {
if (!E) {
-
E = contact_monitor->body_map.insert(objid, BodyState());
//E->get().rc=0;
E->get().in_tree = node && node->is_inside_tree();
@@ -329,29 +294,30 @@ void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
}
}
//E->get().rc++;
- if (node)
+ if (node) {
E->get().shapes.insert(ShapePair(p_body_shape, p_local_shape));
+ }
if (E->get().in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_local_shape);
}
} else {
-
//E->get().rc--;
- if (node)
+ if (node) {
E->get().shapes.erase(ShapePair(p_body_shape, p_local_shape));
+ }
bool in_tree = E->get().in_tree;
if (E->get().shapes.empty()) {
-
if (node) {
node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree));
node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree));
- if (in_tree)
+ if (in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+ }
}
contact_monitor->body_map.erase(E);
@@ -363,14 +329,12 @@ void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
}
struct _RigidBodyInOut {
-
ObjectID id;
int shape;
int local_shape;
};
void RigidBody3D::_direct_state_changed(Object *p_state) {
-
#ifdef DEBUG_ENABLED
state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
#else
@@ -381,24 +345,23 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
set_global_transform(state->get_transform());
linear_velocity = state->get_linear_velocity();
angular_velocity = state->get_angular_velocity();
+ inverse_inertia_tensor = state->get_inverse_inertia_tensor();
if (sleeping != state->is_sleeping()) {
sleeping = state->is_sleeping();
emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed);
}
- if (get_script_instance())
+ if (get_script_instance()) {
get_script_instance()->call("_integrate_forces", state);
+ }
set_ignore_transform_notification(false);
if (contact_monitor) {
-
contact_monitor->locked = true;
//untag all
int rc = 0;
for (Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.front(); E; E = E->next()) {
-
for (int i = 0; i < E->get().shapes.size(); i++) {
-
E->get().shapes[i].tagged = false;
rc++;
}
@@ -412,7 +375,6 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
//put the ones to add
for (int i = 0; i < state->get_contact_count(); i++) {
-
ObjectID obj = state->get_contact_collider_id(i);
int local_shape = state->get_contact_local_shape(i);
int shape = state->get_contact_collider_shape(i);
@@ -431,7 +393,6 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
ShapePair sp(shape, local_shape);
int idx = E->get().shapes.find(sp);
if (idx == -1) {
-
toadd[toadd_count].local_shape = local_shape;
toadd[toadd_count].id = obj;
toadd[toadd_count].shape = shape;
@@ -445,11 +406,8 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
//put the ones to remove
for (Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.front(); E; E = E->next()) {
-
for (int i = 0; i < E->get().shapes.size(); i++) {
-
if (!E->get().shapes[i].tagged) {
-
toremove[toremove_count].body_id = E->key();
toremove[toremove_count].pair = E->get().shapes[i];
toremove_count++;
@@ -460,14 +418,12 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
//process remotions
for (int i = 0; i < toremove_count; i++) {
-
_body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
}
//process aditions
for (int i = 0; i < toadd_count; i++) {
-
_body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
}
@@ -478,7 +434,6 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
}
void RigidBody3D::_notification(int p_what) {
-
#ifdef TOOLS_ENABLED
if (p_what == NOTIFICATION_ENTER_TREE) {
if (Engine::get_singleton()->is_editor_hint()) {
@@ -496,16 +451,12 @@ void RigidBody3D::_notification(int p_what) {
}
void RigidBody3D::set_mode(Mode p_mode) {
-
mode = p_mode;
switch (p_mode) {
-
case MODE_RIGID: {
-
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_RIGID);
} break;
case MODE_STATIC: {
-
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC);
} break;
@@ -514,7 +465,6 @@ void RigidBody3D::set_mode(Mode p_mode) {
} break;
case MODE_KINEMATIC: {
-
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC);
} break;
}
@@ -522,29 +472,26 @@ void RigidBody3D::set_mode(Mode p_mode) {
}
RigidBody3D::Mode RigidBody3D::get_mode() const {
-
return mode;
}
void RigidBody3D::set_mass(real_t p_mass) {
-
ERR_FAIL_COND(p_mass <= 0);
mass = p_mass;
_change_notify("mass");
_change_notify("weight");
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass);
}
-real_t RigidBody3D::get_mass() const {
+real_t RigidBody3D::get_mass() const {
return mass;
}
void RigidBody3D::set_weight(real_t p_weight) {
-
set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)));
}
-real_t RigidBody3D::get_weight() const {
+real_t RigidBody3D::get_weight() const {
return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8));
}
@@ -568,39 +515,35 @@ Ref<PhysicsMaterial> RigidBody3D::get_physics_material_override() const {
}
void RigidBody3D::set_gravity_scale(real_t p_gravity_scale) {
-
gravity_scale = p_gravity_scale;
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE, gravity_scale);
}
-real_t RigidBody3D::get_gravity_scale() const {
+real_t RigidBody3D::get_gravity_scale() const {
return gravity_scale;
}
void RigidBody3D::set_linear_damp(real_t p_linear_damp) {
-
ERR_FAIL_COND(p_linear_damp < -1);
linear_damp = p_linear_damp;
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP, linear_damp);
}
-real_t RigidBody3D::get_linear_damp() const {
+real_t RigidBody3D::get_linear_damp() const {
return linear_damp;
}
void RigidBody3D::set_angular_damp(real_t p_angular_damp) {
-
ERR_FAIL_COND(p_angular_damp < -1);
angular_damp = p_angular_damp;
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
}
-real_t RigidBody3D::get_angular_damp() const {
+real_t RigidBody3D::get_angular_damp() const {
return angular_damp;
}
void RigidBody3D::set_axis_velocity(const Vector3 &p_axis) {
-
Vector3 v = state ? state->get_linear_velocity() : linear_velocity;
Vector3 axis = p_axis.normalized();
v -= axis * axis.dot(v);
@@ -614,75 +557,72 @@ void RigidBody3D::set_axis_velocity(const Vector3 &p_axis) {
}
void RigidBody3D::set_linear_velocity(const Vector3 &p_velocity) {
-
linear_velocity = p_velocity;
- if (state)
+ if (state) {
state->set_linear_velocity(linear_velocity);
- else
+ } else {
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
+ }
}
Vector3 RigidBody3D::get_linear_velocity() const {
-
return linear_velocity;
}
void RigidBody3D::set_angular_velocity(const Vector3 &p_velocity) {
-
angular_velocity = p_velocity;
- if (state)
+ if (state) {
state->set_angular_velocity(angular_velocity);
- else
+ } else {
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity);
+ }
}
-Vector3 RigidBody3D::get_angular_velocity() const {
+Vector3 RigidBody3D::get_angular_velocity() const {
return angular_velocity;
}
-void RigidBody3D::set_use_custom_integrator(bool p_enable) {
+Basis RigidBody3D::get_inverse_inertia_tensor() {
+ return inverse_inertia_tensor;
+}
- if (custom_integrator == p_enable)
+void RigidBody3D::set_use_custom_integrator(bool p_enable) {
+ if (custom_integrator == p_enable) {
return;
+ }
custom_integrator = p_enable;
PhysicsServer3D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable);
}
-bool RigidBody3D::is_using_custom_integrator() {
+bool RigidBody3D::is_using_custom_integrator() {
return custom_integrator;
}
void RigidBody3D::set_sleeping(bool p_sleeping) {
-
sleeping = p_sleeping;
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_SLEEPING, sleeping);
}
void RigidBody3D::set_can_sleep(bool p_active) {
-
can_sleep = p_active;
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_CAN_SLEEP, p_active);
}
bool RigidBody3D::is_able_to_sleep() const {
-
return can_sleep;
}
bool RigidBody3D::is_sleeping() const {
-
return sleeping;
}
void RigidBody3D::set_max_contacts_reported(int p_amount) {
-
max_contacts_reported = p_amount;
PhysicsServer3D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount);
}
int RigidBody3D::get_max_contacts_reported() const {
-
return max_contacts_reported;
}
@@ -690,8 +630,9 @@ void RigidBody3D::add_central_force(const Vector3 &p_force) {
PhysicsServer3D::get_singleton()->body_add_central_force(get_rid(), p_force);
}
-void RigidBody3D::add_force(const Vector3 &p_force, const Vector3 &p_pos) {
- PhysicsServer3D::get_singleton()->body_add_force(get_rid(), p_force, p_pos);
+void RigidBody3D::add_force(const Vector3 &p_force, const Vector3 &p_position) {
+ PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
+ singleton->body_add_force(get_rid(), p_force, p_position);
}
void RigidBody3D::add_torque(const Vector3 &p_torque) {
@@ -702,9 +643,9 @@ void RigidBody3D::apply_central_impulse(const Vector3 &p_impulse) {
PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
}
-void RigidBody3D::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) {
-
- PhysicsServer3D::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse);
+void RigidBody3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
+ PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
+ singleton->body_apply_impulse(get_rid(), p_impulse, p_position);
}
void RigidBody3D::apply_torque_impulse(const Vector3 &p_impulse) {
@@ -712,27 +653,23 @@ void RigidBody3D::apply_torque_impulse(const Vector3 &p_impulse) {
}
void RigidBody3D::set_use_continuous_collision_detection(bool p_enable) {
-
ccd = p_enable;
PhysicsServer3D::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(), p_enable);
}
bool RigidBody3D::is_using_continuous_collision_detection() const {
-
return ccd;
}
void RigidBody3D::set_contact_monitor(bool p_enabled) {
-
- if (p_enabled == is_contact_monitor_enabled())
+ if (p_enabled == is_contact_monitor_enabled()) {
return;
+ }
if (!p_enabled) {
-
ERR_FAIL_COND_MSG(contact_monitor->locked, "Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\", false) instead.");
for (Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.front(); E; E = E->next()) {
-
//clean up mess
Object *obj = ObjectDB::get_instance(E->key());
Node *node = Object::cast_to<Node>(obj);
@@ -746,14 +683,12 @@ void RigidBody3D::set_contact_monitor(bool p_enabled) {
memdelete(contact_monitor);
contact_monitor = nullptr;
} else {
-
contact_monitor = memnew(ContactMonitor);
contact_monitor->locked = false;
}
}
bool RigidBody3D::is_contact_monitor_enabled() const {
-
return contact_monitor != nullptr;
}
@@ -766,7 +701,6 @@ bool RigidBody3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
}
Array RigidBody3D::get_colliding_bodies() const {
-
ERR_FAIL_COND_V(!contact_monitor, Array());
Array ret;
@@ -785,13 +719,12 @@ Array RigidBody3D::get_colliding_bodies() const {
}
String RigidBody3D::get_configuration_warning() const {
-
Transform t = get_transform();
String warning = CollisionObject3D::get_configuration_warning();
if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) {
- if (warning != String()) {
+ if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("Size changes to RigidBody3D (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.");
@@ -801,7 +734,6 @@ String RigidBody3D::get_configuration_warning() const {
}
void RigidBody3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &RigidBody3D::set_mode);
ClassDB::bind_method(D_METHOD("get_mode"), &RigidBody3D::get_mode);
@@ -820,6 +752,8 @@ void RigidBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody3D::set_angular_velocity);
ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody3D::get_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_inverse_inertia_tensor"), &RigidBody3D::get_inverse_inertia_tensor);
+
ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody3D::set_gravity_scale);
ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody3D::get_gravity_scale);
@@ -844,11 +778,11 @@ void RigidBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody3D::set_axis_velocity);
ClassDB::bind_method(D_METHOD("add_central_force", "force"), &RigidBody3D::add_central_force);
- ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidBody3D::add_force);
+ ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidBody3D::add_force, Vector3());
ClassDB::bind_method(D_METHOD("add_torque", "torque"), &RigidBody3D::add_torque);
ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody3D::apply_central_impulse);
- ClassDB::bind_method(D_METHOD("apply_impulse", "position", "impulse"), &RigidBody3D::apply_impulse);
+ ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody3D::apply_impulse, Vector3());
ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidBody3D::apply_torque_impulse);
ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody3D::set_sleeping);
@@ -905,7 +839,6 @@ void RigidBody3D::_bind_methods() {
RigidBody3D::RigidBody3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) {
-
mode = MODE_RIGID;
mass = 1;
@@ -928,9 +861,9 @@ RigidBody3D::RigidBody3D() :
}
RigidBody3D::~RigidBody3D() {
-
- if (contact_monitor)
+ if (contact_monitor) {
memdelete(contact_monitor);
+ }
}
void RigidBody3D::_reload_physics_characteristics() {
@@ -947,7 +880,6 @@ void RigidBody3D::_reload_physics_characteristics() {
//////////////////////////
Ref<KinematicCollision3D> KinematicBody3D::_move(const Vector3 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only) {
-
Collision col;
if (move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only)) {
if (motion_cache.is_null()) {
@@ -972,7 +904,6 @@ Vector3 KinematicBody3D::get_angular_velocity() const {
}
bool KinematicBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) {
-
Transform gt = get_global_transform();
PhysicsServer3D::MotionResult result;
bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result, p_exclude_raycast_shapes);
@@ -1008,9 +939,9 @@ bool KinematicBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_
#define FLOOR_ANGLE_THRESHOLD 0.01
Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
-
Vector3 body_velocity = p_linear_velocity;
Vector3 body_velocity_normal = body_velocity.normalized();
+ Vector3 up_direction = p_up_direction.normalized();
for (int i = 0; i < 3; i++) {
if (locked_axis & (1 << i)) {
@@ -1030,7 +961,6 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const
floor_velocity = Vector3();
while (p_max_slides) {
-
Collision collision;
bool found_collision = false;
@@ -1055,11 +985,11 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const
colliders.push_back(collision);
motion = collision.remainder;
- if (p_up_direction == Vector3()) {
+ if (up_direction == Vector3()) {
//all is a wall
on_wall = true;
} else {
- if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+ if (Math::acos(collision.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
on_floor = true;
floor_normal = collision.normal;
@@ -1067,14 +997,14 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const
floor_velocity = collision.collider_vel;
if (p_stop_on_slope) {
- if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) {
+ if ((body_velocity_normal + up_direction).length() < 0.01 && collision.travel.length() < 1) {
Transform gt = get_global_transform();
- gt.origin -= collision.travel.slide(p_up_direction);
+ gt.origin -= collision.travel.slide(up_direction);
set_global_transform(gt);
return Vector3();
}
}
- } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+ } else if (Math::acos(collision.normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
on_ceiling = true;
} else {
on_wall = true;
@@ -1092,8 +1022,9 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const
}
}
- if (!found_collision || motion == Vector3())
+ if (!found_collision || motion == Vector3()) {
break;
+ }
--p_max_slides;
}
@@ -1102,10 +1033,10 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const
}
Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
-
+ Vector3 up_direction = p_up_direction.normalized();
bool was_on_floor = on_floor;
- Vector3 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
+ Vector3 ret = move_and_slide(p_linear_velocity, up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
if (!was_on_floor || p_snap == Vector3()) {
return ret;
}
@@ -1114,10 +1045,9 @@ Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_veloci
Transform gt = get_global_transform();
if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
-
bool apply = true;
- if (p_up_direction != Vector3()) {
- if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) {
+ if (up_direction != Vector3()) {
+ if (Math::acos(col.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
on_floor = true;
floor_normal = col.normal;
on_floor_body = col.collider_rid;
@@ -1125,7 +1055,7 @@ Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_veloci
if (p_stop_on_slope) {
// move and collide may stray the object a bit because of pre un-stucking,
// so only ensure that motion happens on floor direction in this case.
- col.travel = col.travel.project(p_up_direction);
+ col.travel = col.travel.project(up_direction);
}
} else {
apply = false; //snapped with floor direction, but did not snap to a floor, do not snap.
@@ -1141,38 +1071,32 @@ Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_veloci
}
bool KinematicBody3D::is_on_floor() const {
-
return on_floor;
}
bool KinematicBody3D::is_on_wall() const {
-
return on_wall;
}
-bool KinematicBody3D::is_on_ceiling() const {
+bool KinematicBody3D::is_on_ceiling() const {
return on_ceiling;
}
Vector3 KinematicBody3D::get_floor_normal() const {
-
return floor_normal;
}
Vector3 KinematicBody3D::get_floor_velocity() const {
-
return floor_velocity;
}
bool KinematicBody3D::test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia) {
-
ERR_FAIL_COND_V(!is_inside_tree(), false);
return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia);
}
bool KinematicBody3D::separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision) {
-
PhysicsServer3D::SeparationResult sep_res[8]; //max 8 rays
Transform gt = get_global_transform();
@@ -1209,6 +1133,11 @@ bool KinematicBody3D::separate_raycast_shapes(bool p_infinite_inertia, Collision
}
void KinematicBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
+ if (p_lock) {
+ locked_axis |= p_axis;
+ } else {
+ locked_axis &= (~p_axis);
+ }
PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
}
@@ -1217,17 +1146,15 @@ bool KinematicBody3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
}
void KinematicBody3D::set_safe_margin(float p_margin) {
-
margin = p_margin;
PhysicsServer3D::get_singleton()->body_set_kinematic_safe_margin(get_rid(), margin);
}
float KinematicBody3D::get_safe_margin() const {
-
return margin;
}
-int KinematicBody3D::get_slide_count() const {
+int KinematicBody3D::get_slide_count() const {
return colliders.size();
}
@@ -1237,7 +1164,6 @@ KinematicBody3D::Collision KinematicBody3D::get_slide_collision(int p_bounce) co
}
Ref<KinematicCollision3D> KinematicBody3D::_get_slide_collision(int p_bounce) {
-
ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Ref<KinematicCollision3D>());
if (p_bounce >= slide_colliders.size()) {
slide_colliders.resize(p_bounce + 1);
@@ -1265,7 +1191,6 @@ void KinematicBody3D::_notification(int p_what) {
}
void KinematicBody3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("_direct_state_changed"), &KinematicBody3D::_direct_state_changed);
ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody3D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false));
@@ -1289,9 +1214,10 @@ void KinematicBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody3D::get_slide_count);
ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody3D::_get_slide_collision);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_x", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_y", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_z", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z);
+ ADD_GROUP("Axis Lock", "axis_lock_");
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_motion_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_motion_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_motion_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
@@ -1309,17 +1235,16 @@ void KinematicBody3D::_direct_state_changed(Object *p_state) {
KinematicBody3D::KinematicBody3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
-
- margin = 0.001;
locked_axis = 0;
on_floor = false;
on_ceiling = false;
on_wall = false;
+ set_safe_margin(0.001);
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
}
-KinematicBody3D::~KinematicBody3D() {
+KinematicBody3D::~KinematicBody3D() {
if (motion_cache.is_valid()) {
motion_cache->owner = nullptr;
}
@@ -1330,41 +1255,46 @@ KinematicBody3D::~KinematicBody3D() {
}
}
}
+
///////////////////////////////////////
Vector3 KinematicCollision3D::get_position() const {
-
return collision.collision;
}
+
Vector3 KinematicCollision3D::get_normal() const {
return collision.normal;
}
+
Vector3 KinematicCollision3D::get_travel() const {
return collision.travel;
}
+
Vector3 KinematicCollision3D::get_remainder() const {
return collision.remainder;
}
+
Object *KinematicCollision3D::get_local_shape() const {
- if (!owner) return nullptr;
+ if (!owner) {
+ return nullptr;
+ }
uint32_t ownerid = owner->shape_find_owner(collision.local_shape);
return owner->shape_owner_get_owner(ownerid);
}
Object *KinematicCollision3D::get_collider() const {
-
if (collision.collider.is_valid()) {
return ObjectDB::get_instance(collision.collider);
}
return nullptr;
}
-ObjectID KinematicCollision3D::get_collider_id() const {
+ObjectID KinematicCollision3D::get_collider_id() const {
return collision.collider;
}
-Object *KinematicCollision3D::get_collider_shape() const {
+Object *KinematicCollision3D::get_collider_shape() const {
Object *collider = get_collider();
if (collider) {
CollisionObject3D *obj2d = Object::cast_to<CollisionObject3D>(collider);
@@ -1376,21 +1306,20 @@ Object *KinematicCollision3D::get_collider_shape() const {
return nullptr;
}
-int KinematicCollision3D::get_collider_shape_index() const {
+int KinematicCollision3D::get_collider_shape_index() const {
return collision.collider_shape;
}
-Vector3 KinematicCollision3D::get_collider_velocity() const {
+Vector3 KinematicCollision3D::get_collider_velocity() const {
return collision.collider_vel;
}
-Variant KinematicCollision3D::get_collider_metadata() const {
+Variant KinematicCollision3D::get_collider_metadata() const {
return Variant();
}
void KinematicCollision3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("get_position"), &KinematicCollision3D::get_position);
ClassDB::bind_method(D_METHOD("get_normal"), &KinematicCollision3D::get_normal);
ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision3D::get_travel);
@@ -1417,7 +1346,6 @@ void KinematicCollision3D::_bind_methods() {
}
KinematicCollision3D::KinematicCollision3D() {
-
collision.collider_shape = 0;
collision.local_shape = 0;
owner = nullptr;
@@ -1440,8 +1368,8 @@ void PhysicalBone3D::apply_central_impulse(const Vector3 &p_impulse) {
PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
}
-void PhysicalBone3D::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) {
- PhysicsServer3D::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse);
+void PhysicalBone3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
+ PhysicsServer3D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position);
}
void PhysicalBone3D::reset_physics_simulation_state() {
@@ -1469,18 +1397,21 @@ bool PhysicalBone3D::PinJointData::_set(const StringName &p_name, const Variant
if ("joint_constraints/bias" == p_name) {
bias = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_BIAS, bias);
+ }
} else if ("joint_constraints/damping" == p_name) {
damping = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_DAMPING, damping);
+ }
} else if ("joint_constraints/impulse_clamp" == p_name) {
impulse_clamp = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP, impulse_clamp);
+ }
} else {
return false;
@@ -1522,28 +1453,33 @@ bool PhysicalBone3D::ConeJointData::_set(const StringName &p_name, const Variant
if ("joint_constraints/swing_span" == p_name) {
swing_span = Math::deg2rad(real_t(p_value));
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, swing_span);
+ }
} else if ("joint_constraints/twist_span" == p_name) {
twist_span = Math::deg2rad(real_t(p_value));
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, twist_span);
+ }
} else if ("joint_constraints/bias" == p_name) {
bias = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_BIAS, bias);
+ }
} else if ("joint_constraints/softness" == p_name) {
softness = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS, softness);
+ }
} else if ("joint_constraints/relaxation" == p_name) {
relaxation = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION, relaxation);
+ }
} else {
return false;
@@ -1591,33 +1527,39 @@ bool PhysicalBone3D::HingeJointData::_set(const StringName &p_name, const Varian
if ("joint_constraints/angular_limit_enabled" == p_name) {
angular_limit_enabled = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->hinge_joint_set_flag(j, PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, angular_limit_enabled);
+ }
} else if ("joint_constraints/angular_limit_upper" == p_name) {
angular_limit_upper = Math::deg2rad(real_t(p_value));
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, angular_limit_upper);
+ }
} else if ("joint_constraints/angular_limit_lower" == p_name) {
angular_limit_lower = Math::deg2rad(real_t(p_value));
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER, angular_limit_lower);
+ }
} else if ("joint_constraints/angular_limit_bias" == p_name) {
angular_limit_bias = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS, angular_limit_bias);
+ }
} else if ("joint_constraints/angular_limit_softness" == p_name) {
angular_limit_softness = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS, angular_limit_softness);
+ }
} else if ("joint_constraints/angular_limit_relaxation" == p_name) {
angular_limit_relaxation = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION, angular_limit_relaxation);
+ }
} else {
return false;
@@ -1668,53 +1610,63 @@ bool PhysicalBone3D::SliderJointData::_set(const StringName &p_name, const Varia
if ("joint_constraints/linear_limit_upper" == p_name) {
linear_limit_upper = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, linear_limit_upper);
+ }
} else if ("joint_constraints/linear_limit_lower" == p_name) {
linear_limit_lower = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER, linear_limit_lower);
+ }
} else if ("joint_constraints/linear_limit_softness" == p_name) {
linear_limit_softness = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, linear_limit_softness);
+ }
} else if ("joint_constraints/linear_limit_restitution" == p_name) {
linear_limit_restitution = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, linear_limit_restitution);
+ }
} else if ("joint_constraints/linear_limit_damping" == p_name) {
linear_limit_damping = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, linear_limit_restitution);
+ }
} else if ("joint_constraints/angular_limit_upper" == p_name) {
angular_limit_upper = Math::deg2rad(real_t(p_value));
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, angular_limit_upper);
+ }
} else if ("joint_constraints/angular_limit_lower" == p_name) {
angular_limit_lower = Math::deg2rad(real_t(p_value));
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, angular_limit_lower);
+ }
} else if ("joint_constraints/angular_limit_softness" == p_name) {
angular_limit_softness = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness);
+ }
} else if ("joint_constraints/angular_limit_restitution" == p_name) {
angular_limit_restitution = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness);
+ }
} else if ("joint_constraints/angular_limit_damping" == p_name) {
angular_limit_damping = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, angular_limit_damping);
+ }
} else {
return false;
@@ -1796,108 +1748,129 @@ bool PhysicalBone3D::SixDOFJointData::_set(const StringName &p_name, const Varia
if ("linear_limit_enabled" == var_name) {
axis_data[axis].linear_limit_enabled = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, axis_data[axis].linear_limit_enabled);
+ }
} else if ("linear_limit_upper" == var_name) {
axis_data[axis].linear_limit_upper = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT, axis_data[axis].linear_limit_upper);
+ }
} else if ("linear_limit_lower" == var_name) {
axis_data[axis].linear_limit_lower = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT, axis_data[axis].linear_limit_lower);
+ }
} else if ("linear_limit_softness" == var_name) {
axis_data[axis].linear_limit_softness = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, axis_data[axis].linear_limit_softness);
+ }
} else if ("linear_spring_enabled" == var_name) {
axis_data[axis].linear_spring_enabled = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, axis_data[axis].linear_spring_enabled);
+ }
} else if ("linear_spring_stiffness" == var_name) {
axis_data[axis].linear_spring_stiffness = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, axis_data[axis].linear_spring_stiffness);
+ }
} else if ("linear_spring_damping" == var_name) {
axis_data[axis].linear_spring_damping = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING, axis_data[axis].linear_spring_damping);
+ }
} else if ("linear_equilibrium_point" == var_name) {
axis_data[axis].linear_equilibrium_point = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].linear_equilibrium_point);
+ }
} else if ("linear_restitution" == var_name) {
axis_data[axis].linear_restitution = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION, axis_data[axis].linear_restitution);
+ }
} else if ("linear_damping" == var_name) {
axis_data[axis].linear_damping = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING, axis_data[axis].linear_damping);
+ }
} else if ("angular_limit_enabled" == var_name) {
axis_data[axis].angular_limit_enabled = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, axis_data[axis].angular_limit_enabled);
+ }
} else if ("angular_limit_upper" == var_name) {
axis_data[axis].angular_limit_upper = Math::deg2rad(real_t(p_value));
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, axis_data[axis].angular_limit_upper);
+ }
} else if ("angular_limit_lower" == var_name) {
axis_data[axis].angular_limit_lower = Math::deg2rad(real_t(p_value));
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, axis_data[axis].angular_limit_lower);
+ }
} else if ("angular_limit_softness" == var_name) {
axis_data[axis].angular_limit_softness = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, axis_data[axis].angular_limit_softness);
+ }
} else if ("angular_restitution" == var_name) {
axis_data[axis].angular_restitution = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION, axis_data[axis].angular_restitution);
+ }
} else if ("angular_damping" == var_name) {
axis_data[axis].angular_damping = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING, axis_data[axis].angular_damping);
+ }
} else if ("erp" == var_name) {
axis_data[axis].erp = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp);
+ }
} else if ("angular_spring_enabled" == var_name) {
axis_data[axis].angular_spring_enabled = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, axis_data[axis].angular_spring_enabled);
+ }
} else if ("angular_spring_stiffness" == var_name) {
axis_data[axis].angular_spring_stiffness = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, axis_data[axis].angular_spring_stiffness);
+ }
} else if ("angular_spring_damping" == var_name) {
axis_data[axis].angular_spring_damping = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, axis_data[axis].angular_spring_damping);
+ }
} else if ("angular_equilibrium_point" == var_name) {
axis_data[axis].angular_equilibrium_point = p_value;
- if (j.is_valid())
+ if (j.is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].angular_equilibrium_point);
+ }
} else {
return false;
@@ -2014,8 +1987,9 @@ bool PhysicalBone3D::_set(const StringName &p_name, const Variant &p_value) {
if (joint_data) {
if (joint_data->_set(p_name, p_value)) {
#ifdef TOOLS_ENABLED
- if (get_gizmo().is_valid())
+ if (get_gizmo().is_valid()) {
get_gizmo()->redraw();
+ }
#endif
return true;
}
@@ -2038,21 +2012,19 @@ bool PhysicalBone3D::_get(const StringName &p_name, Variant &r_ret) const {
}
void PhysicalBone3D::_get_property_list(List<PropertyInfo> *p_list) const {
-
Skeleton3D *parent = find_skeleton_parent(get_parent());
if (parent) {
-
String names;
for (int i = 0; i < parent->get_bone_count(); i++) {
- if (i > 0)
+ if (i > 0) {
names += ",";
+ }
names += parent->get_bone_name(i);
}
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "bone_name", PROPERTY_HINT_ENUM, names));
} else {
-
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "bone_name"));
}
@@ -2086,7 +2058,6 @@ void PhysicalBone3D::_notification(int p_what) {
break;
case NOTIFICATION_TRANSFORM_CHANGED:
if (Engine::get_singleton()->is_editor_hint()) {
-
update_offset();
}
break;
@@ -2094,7 +2065,6 @@ void PhysicalBone3D::_notification(int p_what) {
}
void PhysicalBone3D::_direct_state_changed(Object *p_state) {
-
if (!simulate_physics || !_internal_simulate_physics) {
return;
}
@@ -2125,7 +2095,7 @@ void PhysicalBone3D::_direct_state_changed(Object *p_state) {
void PhysicalBone3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicalBone3D::apply_central_impulse);
- ClassDB::bind_method(D_METHOD("apply_impulse", "position", "impulse"), &PhysicalBone3D::apply_impulse);
+ ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicalBone3D::apply_impulse, Vector3());
ClassDB::bind_method(D_METHOD("_direct_state_changed"), &PhysicalBone3D::_direct_state_changed);
@@ -2224,8 +2194,9 @@ void PhysicalBone3D::_update_joint_offset() {
set_ignore_transform_notification(false);
#ifdef TOOLS_ENABLED
- if (get_gizmo().is_valid())
+ if (get_gizmo().is_valid()) {
get_gizmo()->redraw();
+ }
#endif
}
@@ -2237,7 +2208,6 @@ void PhysicalBone3D::_fix_joint_offset() {
}
void PhysicalBone3D::_reload_joint() {
-
if (joint.is_valid()) {
PhysicsServer3D::get_singleton()->free(joint);
joint = RID();
@@ -2258,7 +2228,6 @@ void PhysicalBone3D::_reload_joint() {
switch (get_joint_type()) {
case JOINT_TYPE_PIN: {
-
joint = PhysicsServer3D::get_singleton()->joint_create_pin(body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin);
const PinJointData *pjd(static_cast<const PinJointData *>(joint_data));
PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_BIAS, pjd->bias);
@@ -2267,7 +2236,6 @@ void PhysicalBone3D::_reload_joint() {
} break;
case JOINT_TYPE_CONE: {
-
joint = PhysicsServer3D::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, get_rid(), joint_offset);
const ConeJointData *cjd(static_cast<const ConeJointData *>(joint_data));
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, cjd->swing_span);
@@ -2278,7 +2246,6 @@ void PhysicalBone3D::_reload_joint() {
} break;
case JOINT_TYPE_HINGE: {
-
joint = PhysicsServer3D::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, get_rid(), joint_offset);
const HingeJointData *hjd(static_cast<const HingeJointData *>(joint_data));
PhysicsServer3D::get_singleton()->hinge_joint_set_flag(joint, PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, hjd->angular_limit_enabled);
@@ -2290,7 +2257,6 @@ void PhysicalBone3D::_reload_joint() {
} break;
case JOINT_TYPE_SLIDER: {
-
joint = PhysicsServer3D::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, get_rid(), joint_offset);
const SliderJointData *sjd(static_cast<const SliderJointData *>(joint_data));
PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, sjd->linear_limit_upper);
@@ -2306,7 +2272,6 @@ void PhysicalBone3D::_reload_joint() {
} break;
case JOINT_TYPE_6DOF: {
-
joint = PhysicsServer3D::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, get_rid(), joint_offset);
const SixDOFJointData *g6dofjd(static_cast<const SixDOFJointData *>(joint_data));
for (int axis = 0; axis < 3; ++axis) {
@@ -2369,12 +2334,13 @@ Skeleton3D *PhysicalBone3D::find_skeleton_parent() {
}
void PhysicalBone3D::set_joint_type(JointType p_joint_type) {
-
- if (p_joint_type == get_joint_type())
+ if (p_joint_type == get_joint_type()) {
return;
+ }
- if (joint_data)
+ if (joint_data) {
memdelete(joint_data);
+ }
joint_data = nullptr;
switch (p_joint_type) {
case JOINT_TYPE_PIN:
@@ -2400,8 +2366,9 @@ void PhysicalBone3D::set_joint_type(JointType p_joint_type) {
#ifdef TOOLS_ENABLED
_change_notify();
- if (get_gizmo().is_valid())
+ if (get_gizmo().is_valid()) {
get_gizmo()->redraw();
+ }
#endif
}
@@ -2468,7 +2435,6 @@ bool PhysicalBone3D::is_simulating_physics() {
}
void PhysicalBone3D::set_bone_name(const String &p_name) {
-
bone_name = p_name;
bone_id = -1;
@@ -2477,34 +2443,28 @@ void PhysicalBone3D::set_bone_name(const String &p_name) {
}
const String &PhysicalBone3D::get_bone_name() const {
-
return bone_name;
}
void PhysicalBone3D::set_mass(real_t p_mass) {
-
ERR_FAIL_COND(p_mass <= 0);
mass = p_mass;
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass);
}
real_t PhysicalBone3D::get_mass() const {
-
return mass;
}
void PhysicalBone3D::set_weight(real_t p_weight) {
-
set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)));
}
real_t PhysicalBone3D::get_weight() const {
-
return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8));
}
void PhysicalBone3D::set_friction(real_t p_friction) {
-
ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
friction = p_friction;
@@ -2512,12 +2472,10 @@ void PhysicalBone3D::set_friction(real_t p_friction) {
}
real_t PhysicalBone3D::get_friction() const {
-
return friction;
}
void PhysicalBone3D::set_bounce(real_t p_bounce) {
-
ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
bounce = p_bounce;
@@ -2525,18 +2483,15 @@ void PhysicalBone3D::set_bounce(real_t p_bounce) {
}
real_t PhysicalBone3D::get_bounce() const {
-
return bounce;
}
void PhysicalBone3D::set_gravity_scale(real_t p_gravity_scale) {
-
gravity_scale = p_gravity_scale;
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE, gravity_scale);
}
real_t PhysicalBone3D::get_gravity_scale() const {
-
return gravity_scale;
}
@@ -2578,30 +2533,14 @@ bool PhysicalBone3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
}
PhysicalBone3D::PhysicalBone3D() :
- PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC),
-#ifdef TOOLS_ENABLED
- gizmo_move_joint(false),
-#endif
- joint_data(nullptr),
- parent_skeleton(nullptr),
- simulate_physics(false),
- _internal_simulate_physics(false),
- bone_id(-1),
- bone_name(""),
- bounce(0),
- mass(1),
- friction(1),
- gravity_scale(1),
- linear_damp(-1),
- angular_damp(-1),
- can_sleep(true) {
-
+ PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) {
reset_physics_simulation_state();
}
PhysicalBone3D::~PhysicalBone3D() {
- if (joint_data)
+ if (joint_data) {
memdelete(joint_data);
+ }
}
void PhysicalBone3D::update_bone_id() {
@@ -2630,10 +2569,10 @@ void PhysicalBone3D::update_bone_id() {
void PhysicalBone3D::update_offset() {
#ifdef TOOLS_ENABLED
if (parent_skeleton) {
-
Transform bone_transform(parent_skeleton->get_global_transform());
- if (-1 != bone_id)
+ if (-1 != bone_id) {
bone_transform *= parent_skeleton->get_bone_global_pose(bone_id);
+ }
if (gizmo_move_joint) {
bone_transform *= body_offset;
@@ -2654,7 +2593,7 @@ void PhysicalBone3D::_start_physics_simulation() {
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
- set_as_toplevel(true);
+ set_as_top_level(true);
_internal_simulate_physics = true;
}
@@ -2674,7 +2613,7 @@ void PhysicalBone3D::_stop_physics_simulation() {
if (_internal_simulate_physics) {
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), nullptr, "");
parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false);
- set_as_toplevel(false);
+ set_as_top_level(false);
_internal_simulate_physics = false;
}
}
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 0e719f5108..da947ba02e 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -31,22 +31,18 @@
#ifndef PHYSICS_BODY_3D_H
#define PHYSICS_BODY_3D_H
-#include "core/vset.h"
+#include "core/templates/vset.h"
#include "scene/3d/collision_object_3d.h"
#include "scene/resources/physics_material.h"
#include "servers/physics_server_3d.h"
#include "skeleton_3d.h"
class PhysicsBody3D : public CollisionObject3D {
-
GDCLASS(PhysicsBody3D, CollisionObject3D);
uint32_t collision_layer;
uint32_t collision_mask;
- void _set_layers(uint32_t p_mask);
- uint32_t _get_layers() const;
-
protected:
static void _bind_methods();
PhysicsBody3D(PhysicsServer3D::BodyMode p_mode);
@@ -76,7 +72,6 @@ public:
};
class StaticBody3D : public PhysicsBody3D {
-
GDCLASS(StaticBody3D, PhysicsBody3D);
Vector3 constant_linear_velocity;
@@ -105,7 +100,6 @@ private:
};
class RigidBody3D : public PhysicsBody3D {
-
GDCLASS(RigidBody3D, PhysicsBody3D);
public:
@@ -126,6 +120,7 @@ protected:
Vector3 linear_velocity;
Vector3 angular_velocity;
+ Basis inverse_inertia_tensor;
real_t gravity_scale;
real_t linear_damp;
real_t angular_damp;
@@ -138,15 +133,15 @@ protected:
bool custom_integrator;
struct ShapePair {
-
int body_shape;
int local_shape;
bool tagged;
bool operator<(const ShapePair &p_sp) const {
- if (body_shape == p_sp.body_shape)
+ if (body_shape == p_sp.body_shape) {
return local_shape < p_sp.local_shape;
- else
+ } else {
return body_shape < p_sp.body_shape;
+ }
}
ShapePair() {}
@@ -157,19 +152,16 @@ protected:
}
};
struct RigidBody3D_RemoveAction {
-
ObjectID body_id;
ShapePair pair;
};
struct BodyState {
-
//int rc;
bool in_tree;
VSet<ShapePair> shapes;
};
struct ContactMonitor {
-
bool locked;
Map<ObjectID, BodyState> body_map;
};
@@ -191,7 +183,7 @@ public:
void set_mass(real_t p_mass);
real_t get_mass() const;
- virtual float get_inverse_mass() const { return 1.0 / mass; }
+ virtual float get_inverse_mass() const override { return 1.0 / mass; }
void set_weight(real_t p_weight);
real_t get_weight() const;
@@ -200,12 +192,14 @@ public:
Ref<PhysicsMaterial> get_physics_material_override() const;
void set_linear_velocity(const Vector3 &p_velocity);
- Vector3 get_linear_velocity() const;
+ Vector3 get_linear_velocity() const override;
void set_axis_velocity(const Vector3 &p_axis);
void set_angular_velocity(const Vector3 &p_velocity);
- Vector3 get_angular_velocity() const;
+ Vector3 get_angular_velocity() const override;
+
+ Basis get_inverse_inertia_tensor();
void set_gravity_scale(real_t p_gravity_scale);
real_t get_gravity_scale() const;
@@ -240,14 +234,14 @@ public:
Array get_colliding_bodies() const;
void add_central_force(const Vector3 &p_force);
- void add_force(const Vector3 &p_force, const Vector3 &p_pos);
+ void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3());
void add_torque(const Vector3 &p_torque);
void apply_central_impulse(const Vector3 &p_impulse);
- void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse);
+ void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3());
void apply_torque_impulse(const Vector3 &p_impulse);
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
RigidBody3D();
~RigidBody3D();
@@ -261,7 +255,6 @@ VARIANT_ENUM_CAST(RigidBody3D::Mode);
class KinematicCollision3D;
class KinematicBody3D : public PhysicsBody3D {
-
GDCLASS(KinematicBody3D, PhysicsBody3D);
public:
@@ -308,8 +301,8 @@ protected:
virtual void _direct_state_changed(Object *p_state);
public:
- virtual Vector3 get_linear_velocity() const;
- virtual Vector3 get_angular_velocity() const;
+ virtual Vector3 get_linear_velocity() const override;
+ virtual Vector3 get_angular_velocity() const override;
bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
bool test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia);
@@ -338,7 +331,6 @@ public:
};
class KinematicCollision3D : public Reference {
-
GDCLASS(KinematicCollision3D, Reference);
KinematicBody3D *owner;
@@ -365,7 +357,6 @@ public:
};
class PhysicalBone3D : public PhysicsBody3D {
-
GDCLASS(PhysicalBone3D, PhysicsBody3D);
public:
@@ -396,14 +387,11 @@ public:
virtual bool _get(const StringName &p_name, Variant &r_ret) const;
virtual void _get_property_list(List<PropertyInfo> *p_list) const;
- real_t bias;
- real_t damping;
- real_t impulse_clamp;
+ real_t bias = 0.3;
+ real_t damping = 1.;
+ real_t impulse_clamp = 0;
- PinJointData() :
- bias(0.3),
- damping(1.),
- impulse_clamp(0) {}
+ PinJointData() {}
};
struct ConeJointData : public JointData {
@@ -414,17 +402,13 @@ public:
virtual void _get_property_list(List<PropertyInfo> *p_list) const;
real_t swing_span;
- real_t twist_span;
- real_t bias;
- real_t softness;
- real_t relaxation;
+ real_t twist_span = Math_PI;
+ real_t bias = 0.3;
+ real_t softness = 0.8;
+ real_t relaxation = 1.;
ConeJointData() :
- swing_span(Math_PI * 0.25),
- twist_span(Math_PI),
- bias(0.3),
- softness(0.8),
- relaxation(1.) {}
+ swing_span(Math_PI * 0.25) {}
};
struct HingeJointData : public JointData {
@@ -434,20 +418,17 @@ public:
virtual bool _get(const StringName &p_name, Variant &r_ret) const;
virtual void _get_property_list(List<PropertyInfo> *p_list) const;
- bool angular_limit_enabled;
+ bool angular_limit_enabled = false;
real_t angular_limit_upper;
real_t angular_limit_lower;
- real_t angular_limit_bias;
- real_t angular_limit_softness;
- real_t angular_limit_relaxation;
+ real_t angular_limit_bias = 0.3;
+ real_t angular_limit_softness = 0.9;
+ real_t angular_limit_relaxation = 1.;
HingeJointData() :
- angular_limit_enabled(false),
+
angular_limit_upper(Math_PI * 0.5),
- angular_limit_lower(-Math_PI * 0.5),
- angular_limit_bias(0.3),
- angular_limit_softness(0.9),
- angular_limit_relaxation(1.) {}
+ angular_limit_lower(-Math_PI * 0.5) {}
};
struct SliderJointData : public JointData {
@@ -457,76 +438,45 @@ public:
virtual bool _get(const StringName &p_name, Variant &r_ret) const;
virtual void _get_property_list(List<PropertyInfo> *p_list) const;
- real_t linear_limit_upper;
- real_t linear_limit_lower;
- real_t linear_limit_softness;
- real_t linear_limit_restitution;
- real_t linear_limit_damping;
- real_t angular_limit_upper;
- real_t angular_limit_lower;
- real_t angular_limit_softness;
- real_t angular_limit_restitution;
- real_t angular_limit_damping;
-
- SliderJointData() :
- linear_limit_upper(1.),
- linear_limit_lower(-1.),
- linear_limit_softness(1.),
- linear_limit_restitution(0.7),
- linear_limit_damping(1.),
- angular_limit_upper(0),
- angular_limit_lower(0),
- angular_limit_softness(1.),
- angular_limit_restitution(0.7),
- angular_limit_damping(1.) {}
+ real_t linear_limit_upper = 1.;
+ real_t linear_limit_lower = -1.;
+ real_t linear_limit_softness = 1.;
+ real_t linear_limit_restitution = 0.7;
+ real_t linear_limit_damping = 1.;
+ real_t angular_limit_upper = 0;
+ real_t angular_limit_lower = 0;
+ real_t angular_limit_softness = 1.;
+ real_t angular_limit_restitution = 0.7;
+ real_t angular_limit_damping = 1.;
+
+ SliderJointData() {}
};
struct SixDOFJointData : public JointData {
struct SixDOFAxisData {
- bool linear_limit_enabled;
- real_t linear_limit_upper;
- real_t linear_limit_lower;
- real_t linear_limit_softness;
- real_t linear_restitution;
- real_t linear_damping;
- bool linear_spring_enabled;
- real_t linear_spring_stiffness;
- real_t linear_spring_damping;
- real_t linear_equilibrium_point;
- bool angular_limit_enabled;
- real_t angular_limit_upper;
- real_t angular_limit_lower;
- real_t angular_limit_softness;
- real_t angular_restitution;
- real_t angular_damping;
- real_t erp;
- bool angular_spring_enabled;
- real_t angular_spring_stiffness;
- real_t angular_spring_damping;
- real_t angular_equilibrium_point;
-
- SixDOFAxisData() :
- linear_limit_enabled(true),
- linear_limit_upper(0),
- linear_limit_lower(0),
- linear_limit_softness(0.7),
- linear_restitution(0.5),
- linear_damping(1.),
- linear_spring_enabled(false),
- linear_spring_stiffness(0),
- linear_spring_damping(0),
- linear_equilibrium_point(0),
- angular_limit_enabled(true),
- angular_limit_upper(0),
- angular_limit_lower(0),
- angular_limit_softness(0.5),
- angular_restitution(0),
- angular_damping(1.),
- erp(0.5),
- angular_spring_enabled(false),
- angular_spring_stiffness(0),
- angular_spring_damping(0.),
- angular_equilibrium_point(0) {}
+ bool linear_limit_enabled = true;
+ real_t linear_limit_upper = 0;
+ real_t linear_limit_lower = 0;
+ real_t linear_limit_softness = 0.7;
+ real_t linear_restitution = 0.5;
+ real_t linear_damping = 1.;
+ bool linear_spring_enabled = false;
+ real_t linear_spring_stiffness = 0;
+ real_t linear_spring_damping = 0;
+ real_t linear_equilibrium_point = 0;
+ bool angular_limit_enabled = true;
+ real_t angular_limit_upper = 0;
+ real_t angular_limit_lower = 0;
+ real_t angular_limit_softness = 0.5;
+ real_t angular_restitution = 0;
+ real_t angular_damping = 1.;
+ real_t erp = 0.5;
+ bool angular_spring_enabled = false;
+ real_t angular_spring_stiffness = 0;
+ real_t angular_spring_damping = 0.;
+ real_t angular_equilibrium_point = 0;
+
+ SixDOFAxisData() {}
};
virtual JointType get_joint_type() { return JOINT_TYPE_6DOF; }
@@ -543,28 +493,28 @@ public:
private:
#ifdef TOOLS_ENABLED
// if false gizmo move body
- bool gizmo_move_joint;
+ bool gizmo_move_joint = false;
#endif
- JointData *joint_data;
+ JointData *joint_data = nullptr;
Transform joint_offset;
RID joint;
- Skeleton3D *parent_skeleton;
+ Skeleton3D *parent_skeleton = nullptr;
Transform body_offset;
Transform body_offset_inverse;
- bool simulate_physics;
- bool _internal_simulate_physics;
- int bone_id;
+ bool simulate_physics = false;
+ bool _internal_simulate_physics = false;
+ int bone_id = -1;
String bone_name;
- real_t bounce;
- real_t mass;
- real_t friction;
- real_t gravity_scale;
- real_t linear_damp;
- real_t angular_damp;
- bool can_sleep;
+ real_t bounce = 0;
+ real_t mass = 1;
+ real_t friction = 1;
+ real_t gravity_scale = 1;
+ real_t linear_damp = -1;
+ real_t angular_damp = -1;
+ bool can_sleep = true;
protected:
bool _set(const StringName &p_name, const Variant &p_value);
@@ -588,8 +538,8 @@ public:
public:
#ifdef TOOLS_ENABLED
- virtual Transform get_global_gizmo_transform() const;
- virtual Transform get_local_gizmo_transform() const;
+ virtual Transform get_global_gizmo_transform() const override;
+ virtual Transform get_local_gizmo_transform() const override;
#endif
const JointData *get_joint_data() const;
@@ -647,7 +597,7 @@ public:
bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
void apply_central_impulse(const Vector3 &p_impulse);
- void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse);
+ void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3());
void reset_physics_simulation_state();
void reset_to_rest_position();
diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp
index 591c17a91e..af4d6ae152 100644
--- a/scene/3d/physics_joint_3d.cpp
+++ b/scene/3d/physics_joint_3d.cpp
@@ -31,10 +31,10 @@
#include "physics_joint_3d.h"
void Joint3D::_update_joint(bool p_only_free) {
-
if (joint.is_valid()) {
- if (ba.is_valid() && bb.is_valid())
+ if (ba.is_valid() && bb.is_valid()) {
PhysicsServer3D::get_singleton()->body_remove_collision_exception(ba, bb);
+ }
PhysicsServer3D::get_singleton()->free(joint);
joint = RID();
@@ -42,8 +42,9 @@ void Joint3D::_update_joint(bool p_only_free) {
bb = RID();
}
- if (p_only_free || !is_inside_tree())
+ if (p_only_free || !is_inside_tree()) {
return;
+ }
Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)nullptr;
Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)nullptr;
@@ -51,68 +52,68 @@ void Joint3D::_update_joint(bool p_only_free) {
PhysicsBody3D *body_a = Object::cast_to<PhysicsBody3D>(node_a);
PhysicsBody3D *body_b = Object::cast_to<PhysicsBody3D>(node_b);
- if (!body_a && body_b)
+ if (!body_a && body_b) {
SWAP(body_a, body_b);
+ }
- if (!body_a)
+ if (!body_a) {
return;
+ }
joint = _configure_joint(body_a, body_b);
- if (!joint.is_valid())
+ if (!joint.is_valid()) {
return;
+ }
PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority);
ba = body_a->get_rid();
- if (body_b)
+ if (body_b) {
bb = body_b->get_rid();
+ }
PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision);
}
void Joint3D::set_node_a(const NodePath &p_node_a) {
-
- if (a == p_node_a)
+ if (a == p_node_a) {
return;
+ }
a = p_node_a;
_update_joint();
}
NodePath Joint3D::get_node_a() const {
-
return a;
}
void Joint3D::set_node_b(const NodePath &p_node_b) {
-
- if (b == p_node_b)
+ if (b == p_node_b) {
return;
+ }
b = p_node_b;
_update_joint();
}
-NodePath Joint3D::get_node_b() const {
+NodePath Joint3D::get_node_b() const {
return b;
}
void Joint3D::set_solver_priority(int p_priority) {
-
solver_priority = p_priority;
- if (joint.is_valid())
+ if (joint.is_valid()) {
PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority);
+ }
}
int Joint3D::get_solver_priority() const {
-
return solver_priority;
}
void Joint3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_READY: {
_update_joint();
} break;
@@ -125,20 +126,18 @@ void Joint3D::_notification(int p_what) {
}
void Joint3D::set_exclude_nodes_from_collision(bool p_enable) {
-
- if (exclude_from_collision == p_enable)
+ if (exclude_from_collision == p_enable) {
return;
+ }
exclude_from_collision = p_enable;
_update_joint();
}
bool Joint3D::get_exclude_nodes_from_collision() const {
-
return exclude_from_collision;
}
void Joint3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_node_a", "node"), &Joint3D::set_node_a);
ClassDB::bind_method(D_METHOD("get_node_a"), &Joint3D::get_node_a);
@@ -159,7 +158,6 @@ void Joint3D::_bind_methods() {
}
Joint3D::Joint3D() {
-
exclude_from_collision = true;
solver_priority = 1;
set_notify_transform(true);
@@ -168,7 +166,6 @@ Joint3D::Joint3D() {
///////////////////////////////////
void PinJoint3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &PinJoint3D::set_param);
ClassDB::bind_method(D_METHOD("get_param", "param"), &PinJoint3D::get_param);
@@ -182,28 +179,28 @@ void PinJoint3D::_bind_methods() {
}
void PinJoint3D::set_param(Param p_param, float p_value) {
-
ERR_FAIL_INDEX(p_param, 3);
params[p_param] = p_value;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->pin_joint_set_param(get_joint(), PhysicsServer3D::PinJointParam(p_param), p_value);
+ }
}
-float PinJoint3D::get_param(Param p_param) const {
+float PinJoint3D::get_param(Param p_param) const {
ERR_FAIL_INDEX_V(p_param, 3, 0);
return params[p_param];
}
RID PinJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
-
Vector3 pinpos = get_global_transform().origin;
Vector3 local_a = body_a->get_global_transform().affine_inverse().xform(pinpos);
Vector3 local_b;
- if (body_b)
+ if (body_b) {
local_b = body_b->get_global_transform().affine_inverse().xform(pinpos);
- else
+ } else {
local_b = pinpos;
+ }
RID j = PhysicsServer3D::get_singleton()->joint_create_pin(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
for (int i = 0; i < 3; i++) {
@@ -213,7 +210,6 @@ RID PinJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
}
PinJoint3D::PinJoint3D() {
-
params[PARAM_BIAS] = 0.3;
params[PARAM_DAMPING] = 1;
params[PARAM_IMPULSE_CLAMP] = 0;
@@ -224,27 +220,22 @@ PinJoint3D::PinJoint3D() {
///////////////////////////////////
void HingeJoint3D::_set_upper_limit(float p_limit) {
-
set_param(PARAM_LIMIT_UPPER, Math::deg2rad(p_limit));
}
float HingeJoint3D::_get_upper_limit() const {
-
return Math::rad2deg(get_param(PARAM_LIMIT_UPPER));
}
void HingeJoint3D::_set_lower_limit(float p_limit) {
-
set_param(PARAM_LIMIT_LOWER, Math::deg2rad(p_limit));
}
float HingeJoint3D::_get_lower_limit() const {
-
return Math::rad2deg(get_param(PARAM_LIMIT_LOWER));
}
void HingeJoint3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &HingeJoint3D::set_param);
ClassDB::bind_method(D_METHOD("get_param", "param"), &HingeJoint3D::get_param);
@@ -286,37 +277,36 @@ void HingeJoint3D::_bind_methods() {
}
void HingeJoint3D::set_param(Param p_param, float p_value) {
-
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params[p_param] = p_value;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->hinge_joint_set_param(get_joint(), PhysicsServer3D::HingeJointParam(p_param), p_value);
+ }
update_gizmo();
}
-float HingeJoint3D::get_param(Param p_param) const {
+float HingeJoint3D::get_param(Param p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return params[p_param];
}
void HingeJoint3D::set_flag(Flag p_flag, bool p_value) {
-
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
flags[p_flag] = p_value;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->hinge_joint_set_flag(get_joint(), PhysicsServer3D::HingeJointFlag(p_flag), p_value);
+ }
update_gizmo();
}
-bool HingeJoint3D::get_flag(Flag p_flag) const {
+bool HingeJoint3D::get_flag(Flag p_flag) const {
ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
return flags[p_flag];
}
RID HingeJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
-
Transform gt = get_global_transform();
Transform ainv = body_a->get_global_transform().affine_inverse();
@@ -343,7 +333,6 @@ RID HingeJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b)
}
HingeJoint3D::HingeJoint3D() {
-
params[PARAM_BIAS] = 0.3;
params[PARAM_LIMIT_UPPER] = Math_PI * 0.5;
params[PARAM_LIMIT_LOWER] = -Math_PI * 0.5;
@@ -362,27 +351,22 @@ HingeJoint3D::HingeJoint3D() {
//////////////////////////////////
void SliderJoint3D::_set_upper_limit_angular(float p_limit_angular) {
-
set_param(PARAM_ANGULAR_LIMIT_UPPER, Math::deg2rad(p_limit_angular));
}
float SliderJoint3D::_get_upper_limit_angular() const {
-
return Math::rad2deg(get_param(PARAM_ANGULAR_LIMIT_UPPER));
}
void SliderJoint3D::_set_lower_limit_angular(float p_limit_angular) {
-
set_param(PARAM_ANGULAR_LIMIT_LOWER, Math::deg2rad(p_limit_angular));
}
float SliderJoint3D::_get_lower_limit_angular() const {
-
return Math::rad2deg(get_param(PARAM_ANGULAR_LIMIT_LOWER));
}
void SliderJoint3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &SliderJoint3D::set_param);
ClassDB::bind_method(D_METHOD("get_param", "param"), &SliderJoint3D::get_param);
@@ -444,21 +428,20 @@ void SliderJoint3D::_bind_methods() {
}
void SliderJoint3D::set_param(Param p_param, float p_value) {
-
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params[p_param] = p_value;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(get_joint(), PhysicsServer3D::SliderJointParam(p_param), p_value);
+ }
update_gizmo();
}
-float SliderJoint3D::get_param(Param p_param) const {
+float SliderJoint3D::get_param(Param p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return params[p_param];
}
RID SliderJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
-
Transform gt = get_global_transform();
Transform ainv = body_a->get_global_transform().affine_inverse();
@@ -482,7 +465,6 @@ RID SliderJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b
}
SliderJoint3D::SliderJoint3D() {
-
params[PARAM_LINEAR_LIMIT_UPPER] = 1.0;
params[PARAM_LINEAR_LIMIT_LOWER] = -1.0;
params[PARAM_LINEAR_LIMIT_SOFTNESS] = 1.0;
@@ -511,27 +493,22 @@ SliderJoint3D::SliderJoint3D() {
//////////////////////////////////
void ConeTwistJoint3D::_set_swing_span(float p_limit_angular) {
-
set_param(PARAM_SWING_SPAN, Math::deg2rad(p_limit_angular));
}
float ConeTwistJoint3D::_get_swing_span() const {
-
return Math::rad2deg(get_param(PARAM_SWING_SPAN));
}
void ConeTwistJoint3D::_set_twist_span(float p_limit_angular) {
-
set_param(PARAM_TWIST_SPAN, Math::deg2rad(p_limit_angular));
}
float ConeTwistJoint3D::_get_twist_span() const {
-
return Math::rad2deg(get_param(PARAM_TWIST_SPAN));
}
void ConeTwistJoint3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &ConeTwistJoint3D::set_param);
ClassDB::bind_method(D_METHOD("get_param", "param"), &ConeTwistJoint3D::get_param);
@@ -557,22 +534,21 @@ void ConeTwistJoint3D::_bind_methods() {
}
void ConeTwistJoint3D::set_param(Param p_param, float p_value) {
-
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params[p_param] = p_value;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(get_joint(), PhysicsServer3D::ConeTwistJointParam(p_param), p_value);
+ }
update_gizmo();
}
-float ConeTwistJoint3D::get_param(Param p_param) const {
+float ConeTwistJoint3D::get_param(Param p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return params[p_param];
}
RID ConeTwistJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
-
Transform gt = get_global_transform();
//Vector3 cone_twistpos = gt.origin;
//Vector3 cone_twistdir = gt.basis.get_axis(2);
@@ -599,7 +575,6 @@ RID ConeTwistJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *bod
}
ConeTwistJoint3D::ConeTwistJoint3D() {
-
params[PARAM_SWING_SPAN] = Math_PI * 0.25;
params[PARAM_TWIST_SPAN] = Math_PI;
params[PARAM_BIAS] = 0.3;
@@ -610,67 +585,54 @@ ConeTwistJoint3D::ConeTwistJoint3D() {
/////////////////////////////////////////////////////////////////////
void Generic6DOFJoint3D::_set_angular_hi_limit_x(float p_limit_angular) {
-
set_param_x(PARAM_ANGULAR_UPPER_LIMIT, Math::deg2rad(p_limit_angular));
}
float Generic6DOFJoint3D::_get_angular_hi_limit_x() const {
-
return Math::rad2deg(get_param_x(PARAM_ANGULAR_UPPER_LIMIT));
}
void Generic6DOFJoint3D::_set_angular_lo_limit_x(float p_limit_angular) {
-
set_param_x(PARAM_ANGULAR_LOWER_LIMIT, Math::deg2rad(p_limit_angular));
}
float Generic6DOFJoint3D::_get_angular_lo_limit_x() const {
-
return Math::rad2deg(get_param_x(PARAM_ANGULAR_LOWER_LIMIT));
}
void Generic6DOFJoint3D::_set_angular_hi_limit_y(float p_limit_angular) {
-
set_param_y(PARAM_ANGULAR_UPPER_LIMIT, Math::deg2rad(p_limit_angular));
}
float Generic6DOFJoint3D::_get_angular_hi_limit_y() const {
-
return Math::rad2deg(get_param_y(PARAM_ANGULAR_UPPER_LIMIT));
}
void Generic6DOFJoint3D::_set_angular_lo_limit_y(float p_limit_angular) {
-
set_param_y(PARAM_ANGULAR_LOWER_LIMIT, Math::deg2rad(p_limit_angular));
}
float Generic6DOFJoint3D::_get_angular_lo_limit_y() const {
-
return Math::rad2deg(get_param_y(PARAM_ANGULAR_LOWER_LIMIT));
}
void Generic6DOFJoint3D::_set_angular_hi_limit_z(float p_limit_angular) {
-
set_param_z(PARAM_ANGULAR_UPPER_LIMIT, Math::deg2rad(p_limit_angular));
}
float Generic6DOFJoint3D::_get_angular_hi_limit_z() const {
-
return Math::rad2deg(get_param_z(PARAM_ANGULAR_UPPER_LIMIT));
}
void Generic6DOFJoint3D::_set_angular_lo_limit_z(float p_limit_angular) {
-
set_param_z(PARAM_ANGULAR_LOWER_LIMIT, Math::deg2rad(p_limit_angular));
}
float Generic6DOFJoint3D::_get_angular_lo_limit_z() const {
-
return Math::rad2deg(get_param_z(PARAM_ANGULAR_LOWER_LIMIT));
}
void Generic6DOFJoint3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("_set_angular_hi_limit_x", "angle"), &Generic6DOFJoint3D::_set_angular_hi_limit_x);
ClassDB::bind_method(D_METHOD("_get_angular_hi_limit_x"), &Generic6DOFJoint3D::_get_angular_hi_limit_x);
@@ -807,6 +769,9 @@ void Generic6DOFJoint3D::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_LINEAR_DAMPING);
BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_SPRING_STIFFNESS);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_SPRING_DAMPING);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
BIND_ENUM_CONSTANT(PARAM_ANGULAR_LOWER_LIMIT);
BIND_ENUM_CONSTANT(PARAM_ANGULAR_UPPER_LIMIT);
BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_SOFTNESS);
@@ -816,6 +781,9 @@ void Generic6DOFJoint3D::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_ANGULAR_ERP);
BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_SPRING_STIFFNESS);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_SPRING_DAMPING);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
BIND_ENUM_CONSTANT(PARAM_MAX);
BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_LIMIT);
@@ -828,86 +796,86 @@ void Generic6DOFJoint3D::_bind_methods() {
}
void Generic6DOFJoint3D::set_param_x(Param p_param, float p_value) {
-
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params_x[p_param] = p_value;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
+ }
update_gizmo();
}
-float Generic6DOFJoint3D::get_param_x(Param p_param) const {
+float Generic6DOFJoint3D::get_param_x(Param p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return params_x[p_param];
}
void Generic6DOFJoint3D::set_param_y(Param p_param, float p_value) {
-
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params_y[p_param] = p_value;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
+ }
update_gizmo();
}
-float Generic6DOFJoint3D::get_param_y(Param p_param) const {
+float Generic6DOFJoint3D::get_param_y(Param p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return params_y[p_param];
}
void Generic6DOFJoint3D::set_param_z(Param p_param, float p_value) {
-
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params_z[p_param] = p_value;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
+ }
update_gizmo();
}
-float Generic6DOFJoint3D::get_param_z(Param p_param) const {
+float Generic6DOFJoint3D::get_param_z(Param p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return params_z[p_param];
}
void Generic6DOFJoint3D::set_flag_x(Flag p_flag, bool p_enabled) {
-
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
flags_x[p_flag] = p_enabled;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
+ }
update_gizmo();
}
-bool Generic6DOFJoint3D::get_flag_x(Flag p_flag) const {
+bool Generic6DOFJoint3D::get_flag_x(Flag p_flag) const {
ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
return flags_x[p_flag];
}
void Generic6DOFJoint3D::set_flag_y(Flag p_flag, bool p_enabled) {
-
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
flags_y[p_flag] = p_enabled;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
+ }
update_gizmo();
}
-bool Generic6DOFJoint3D::get_flag_y(Flag p_flag) const {
+bool Generic6DOFJoint3D::get_flag_y(Flag p_flag) const {
ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
return flags_y[p_flag];
}
void Generic6DOFJoint3D::set_flag_z(Flag p_flag, bool p_enabled) {
-
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
flags_z[p_flag] = p_enabled;
- if (get_joint().is_valid())
+ if (get_joint().is_valid()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
+ }
update_gizmo();
}
-bool Generic6DOFJoint3D::get_flag_z(Flag p_flag) const {
+bool Generic6DOFJoint3D::get_flag_z(Flag p_flag) const {
ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
return flags_z[p_flag];
}
@@ -921,7 +889,6 @@ void Generic6DOFJoint3D::set_precision(int p_precision) {
}
RID Generic6DOFJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
-
Transform gt = get_global_transform();
//Vector3 cone_twistpos = gt.origin;
//Vector3 cone_twistdir = gt.basis.get_axis(2);
@@ -954,9 +921,7 @@ RID Generic6DOFJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *b
return j;
}
-Generic6DOFJoint3D::Generic6DOFJoint3D() :
- precision(1) {
-
+Generic6DOFJoint3D::Generic6DOFJoint3D() {
set_param_x(PARAM_LINEAR_LOWER_LIMIT, 0);
set_param_x(PARAM_LINEAR_UPPER_LIMIT, 0);
set_param_x(PARAM_LINEAR_LIMIT_SOFTNESS, 0.7);
diff --git a/scene/3d/physics_joint_3d.h b/scene/3d/physics_joint_3d.h
index ce0c7af5d1..d1a375ca5d 100644
--- a/scene/3d/physics_joint_3d.h
+++ b/scene/3d/physics_joint_3d.h
@@ -35,7 +35,6 @@
#include "scene/3d/physics_body_3d.h"
class Joint3D : public Node3D {
-
GDCLASS(Joint3D, Node3D);
RID ba, bb;
@@ -77,7 +76,6 @@ public:
///////////////////////////////////////////
class PinJoint3D : public Joint3D {
-
GDCLASS(PinJoint3D, Joint3D);
public:
@@ -89,7 +87,7 @@ public:
protected:
float params[3];
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b);
+ virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
static void _bind_methods();
public:
@@ -102,7 +100,6 @@ public:
VARIANT_ENUM_CAST(PinJoint3D::Param);
class HingeJoint3D : public Joint3D {
-
GDCLASS(HingeJoint3D, Joint3D);
public:
@@ -127,7 +124,7 @@ public:
protected:
float params[PARAM_MAX];
bool flags[FLAG_MAX];
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b);
+ virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
static void _bind_methods();
void _set_upper_limit(float p_limit);
@@ -150,7 +147,6 @@ VARIANT_ENUM_CAST(HingeJoint3D::Param);
VARIANT_ENUM_CAST(HingeJoint3D::Flag);
class SliderJoint3D : public Joint3D {
-
GDCLASS(SliderJoint3D, Joint3D);
public:
@@ -190,7 +186,7 @@ protected:
float _get_lower_limit_angular() const;
float params[PARAM_MAX];
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b);
+ virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
static void _bind_methods();
public:
@@ -203,12 +199,10 @@ public:
VARIANT_ENUM_CAST(SliderJoint3D::Param);
class ConeTwistJoint3D : public Joint3D {
-
GDCLASS(ConeTwistJoint3D, Joint3D);
public:
enum Param {
-
PARAM_SWING_SPAN,
PARAM_TWIST_SPAN,
PARAM_BIAS,
@@ -225,7 +219,7 @@ protected:
float _get_twist_span() const;
float params[PARAM_MAX];
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b);
+ virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
static void _bind_methods();
public:
@@ -238,12 +232,10 @@ public:
VARIANT_ENUM_CAST(ConeTwistJoint3D::Param);
class Generic6DOFJoint3D : public Joint3D {
-
GDCLASS(Generic6DOFJoint3D, Joint3D);
public:
enum Param {
-
PARAM_LINEAR_LOWER_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT,
PARAM_LINEAR_UPPER_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT,
PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS,
@@ -305,9 +297,9 @@ protected:
float params_z[PARAM_MAX];
bool flags_z[FLAG_MAX];
- int precision;
+ int precision = 1;
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b);
+ virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
static void _bind_methods();
public:
diff --git a/scene/3d/position_3d.h b/scene/3d/position_3d.h
index 9c806723fb..1c5f05ef95 100644
--- a/scene/3d/position_3d.h
+++ b/scene/3d/position_3d.h
@@ -34,7 +34,6 @@
#include "scene/3d/node_3d.h"
class Position3D : public Node3D {
-
GDCLASS(Position3D, Node3D);
public:
diff --git a/scene/3d/proximity_group_3d.cpp b/scene/3d/proximity_group_3d.cpp
index 44ffabb655..1a0677c603 100644
--- a/scene/3d/proximity_group_3d.cpp
+++ b/scene/3d/proximity_group_3d.cpp
@@ -33,7 +33,6 @@
#include "core/math/math_funcs.h"
void ProximityGroup3D::clear_groups() {
-
Map<StringName, uint32_t>::Element *E;
{
@@ -42,7 +41,6 @@ void ProximityGroup3D::clear_groups() {
E = groups.front();
int num = 0;
while (E && num < size) {
-
if (E->get() != group_version) {
remove_list[num++] = E->key();
};
@@ -50,7 +48,6 @@ void ProximityGroup3D::clear_groups() {
E = E->next();
};
for (int i = 0; i < num; i++) {
-
groups.erase(remove_list[i]);
};
};
@@ -61,9 +58,9 @@ void ProximityGroup3D::clear_groups() {
};
void ProximityGroup3D::update_groups() {
-
- if (grid_radius == Vector3(0, 0, 0))
+ if (grid_radius == Vector3(0, 0, 0)) {
return;
+ }
++group_version;
@@ -77,10 +74,8 @@ void ProximityGroup3D::update_groups() {
};
void ProximityGroup3D::add_groups(int *p_cell, String p_base, int p_depth) {
-
p_base = p_base + "|";
if (grid_radius[p_depth] == 0) {
-
if (p_depth == 2) {
_new_group(p_base);
} else {
@@ -92,7 +87,6 @@ void ProximityGroup3D::add_groups(int *p_cell, String p_base, int p_depth) {
int end = p_cell[p_depth] + grid_radius[p_depth];
for (int i = start; i <= end; i++) {
-
String gname = p_base + itos(i);
if (p_depth == 2) {
_new_group(gname);
@@ -103,7 +97,6 @@ void ProximityGroup3D::add_groups(int *p_cell, String p_base, int p_depth) {
};
void ProximityGroup3D::_new_group(StringName p_name) {
-
const Map<StringName, uint32_t>::Element *E = groups.find(p_name);
if (!E) {
add_to_group(p_name);
@@ -113,9 +106,7 @@ void ProximityGroup3D::_new_group(StringName p_name) {
};
void ProximityGroup3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_EXIT_TREE:
++group_version;
clear_groups();
@@ -127,59 +118,47 @@ void ProximityGroup3D::_notification(int p_what) {
};
void ProximityGroup3D::broadcast(String p_name, Variant p_params) {
-
Map<StringName, uint32_t>::Element *E;
E = groups.front();
while (E) {
-
get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFAULT, E->key(), "_proximity_group_broadcast", p_name, p_params);
E = E->next();
};
};
void ProximityGroup3D::_proximity_group_broadcast(String p_name, Variant p_params) {
-
if (dispatch_mode == MODE_PROXY) {
-
get_parent()->call(p_name, p_params);
} else {
-
emit_signal("broadcast", p_name, p_params);
};
};
void ProximityGroup3D::set_group_name(const String &p_group_name) {
-
group_name = p_group_name;
};
String ProximityGroup3D::get_group_name() const {
-
return group_name;
};
void ProximityGroup3D::set_dispatch_mode(DispatchMode p_mode) {
-
dispatch_mode = p_mode;
};
ProximityGroup3D::DispatchMode ProximityGroup3D::get_dispatch_mode() const {
-
return dispatch_mode;
};
void ProximityGroup3D::set_grid_radius(const Vector3 &p_radius) {
-
grid_radius = p_radius;
};
Vector3 ProximityGroup3D::get_grid_radius() const {
-
return grid_radius;
};
void ProximityGroup3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_group_name", "name"), &ProximityGroup3D::set_group_name);
ClassDB::bind_method(D_METHOD("get_group_name"), &ProximityGroup3D::get_group_name);
ClassDB::bind_method(D_METHOD("set_dispatch_mode", "mode"), &ProximityGroup3D::set_dispatch_mode);
@@ -200,15 +179,5 @@ void ProximityGroup3D::_bind_methods() {
};
ProximityGroup3D::ProximityGroup3D() {
-
- group_version = 0;
- dispatch_mode = MODE_PROXY;
-
- cell_size = 1.0;
- grid_radius = Vector3(1, 1, 1);
set_notify_transform(true);
};
-
-ProximityGroup3D::~ProximityGroup3D(){
-
-};
diff --git a/scene/3d/proximity_group_3d.h b/scene/3d/proximity_group_3d.h
index 751bfbdb52..dd3a2f0a87 100644
--- a/scene/3d/proximity_group_3d.h
+++ b/scene/3d/proximity_group_3d.h
@@ -34,7 +34,6 @@
#include "node_3d.h"
class ProximityGroup3D : public Node3D {
-
GDCLASS(ProximityGroup3D, Node3D);
OBJ_CATEGORY("3D");
@@ -50,14 +49,14 @@ public:
void _notification(int p_what);
- DispatchMode dispatch_mode;
+ DispatchMode dispatch_mode = MODE_PROXY;
Map<StringName, uint32_t> groups;
String group_name;
- float cell_size;
- Vector3 grid_radius;
- uint32_t group_version;
+ float cell_size = 1.0;
+ Vector3 grid_radius = Vector3(1, 1, 1);
+ uint32_t group_version = 0;
void add_groups(int *p_cell, String p_base, int p_depth);
void _new_group(StringName p_name);
@@ -79,7 +78,7 @@ public:
void broadcast(String p_name, Variant p_params);
ProximityGroup3D();
- ~ProximityGroup3D();
+ ~ProximityGroup3D() {}
};
VARIANT_ENUM_CAST(ProximityGroup3D::DispatchMode);
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp
index a18da61656..811e8a331b 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/ray_cast_3d.cpp
@@ -31,156 +31,154 @@
#include "ray_cast_3d.h"
#include "collision_object_3d.h"
-#include "core/engine.h"
+#include "core/config/engine.h"
#include "mesh_instance_3d.h"
#include "servers/physics_server_3d.h"
-void RayCast3D::set_cast_to(const Vector3 &p_point) {
-
- cast_to = p_point;
- if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint()))
+void RayCast3D::set_target_position(const Vector3 &p_point) {
+ target_position = p_point;
+ if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) {
update_gizmo();
- if (is_inside_tree() && get_tree()->is_debugging_collisions_hint())
+ }
+ if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) {
_update_debug_shape();
+ }
}
-Vector3 RayCast3D::get_cast_to() const {
-
- return cast_to;
+Vector3 RayCast3D::get_target_position() const {
+ return target_position;
}
void RayCast3D::set_collision_mask(uint32_t p_mask) {
-
collision_mask = p_mask;
}
uint32_t RayCast3D::get_collision_mask() const {
-
return collision_mask;
}
void RayCast3D::set_collision_mask_bit(int p_bit, bool p_value) {
-
uint32_t mask = get_collision_mask();
- if (p_value)
+ if (p_value) {
mask |= 1 << p_bit;
- else
+ } else {
mask &= ~(1 << p_bit);
+ }
set_collision_mask(mask);
}
bool RayCast3D::get_collision_mask_bit(int p_bit) const {
-
return get_collision_mask() & (1 << p_bit);
}
bool RayCast3D::is_colliding() const {
-
return collided;
}
-Object *RayCast3D::get_collider() const {
- if (against.is_null())
+Object *RayCast3D::get_collider() const {
+ if (against.is_null()) {
return nullptr;
+ }
return ObjectDB::get_instance(against);
}
int RayCast3D::get_collider_shape() const {
-
return against_shape;
}
-Vector3 RayCast3D::get_collision_point() const {
+Vector3 RayCast3D::get_collision_point() const {
return collision_point;
}
-Vector3 RayCast3D::get_collision_normal() const {
+Vector3 RayCast3D::get_collision_normal() const {
return collision_normal;
}
void RayCast3D::set_enabled(bool p_enabled) {
-
enabled = p_enabled;
update_gizmo();
- if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint())
+ if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) {
set_physics_process_internal(p_enabled);
- if (!p_enabled)
+ }
+ if (!p_enabled) {
collided = false;
+ }
if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) {
- if (p_enabled)
+ if (p_enabled) {
_update_debug_shape();
- else
+ } else {
_clear_debug_shape();
+ }
}
}
bool RayCast3D::is_enabled() const {
-
return enabled;
}
void RayCast3D::set_exclude_parent_body(bool p_exclude_parent_body) {
-
- if (exclude_parent_body == p_exclude_parent_body)
+ if (exclude_parent_body == p_exclude_parent_body) {
return;
+ }
exclude_parent_body = p_exclude_parent_body;
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
if (Object::cast_to<CollisionObject3D>(get_parent())) {
- if (exclude_parent_body)
+ if (exclude_parent_body) {
exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
- else
+ } else {
exclude.erase(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
+ }
}
}
bool RayCast3D::get_exclude_parent_body() const {
-
return exclude_parent_body;
}
void RayCast3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_ENTER_TREE: {
-
if (enabled && !Engine::get_singleton()->is_editor_hint()) {
set_physics_process_internal(true);
- if (get_tree()->is_debugging_collisions_hint())
+ if (get_tree()->is_debugging_collisions_hint()) {
_update_debug_shape();
- } else
+ }
+ } else {
set_physics_process_internal(false);
+ }
if (Object::cast_to<CollisionObject3D>(get_parent())) {
- if (exclude_parent_body)
+ if (exclude_parent_body) {
exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
- else
+ } else {
exclude.erase(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
+ }
}
} break;
case NOTIFICATION_EXIT_TREE: {
-
if (enabled) {
set_physics_process_internal(false);
}
- if (debug_shape)
+ if (debug_shape) {
_clear_debug_shape();
+ }
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
-
- if (!enabled)
+ if (!enabled) {
break;
+ }
bool prev_collision_state = collided;
_update_raycast_state();
@@ -196,7 +194,7 @@ void RayCast3D::_notification(int p_what) {
}
void RayCast3D::_update_raycast_state() {
- Ref<World3D> w3d = get_world();
+ Ref<World3D> w3d = get_world_3d();
ERR_FAIL_COND(w3d.is_null());
PhysicsDirectSpaceState3D *dss = PhysicsServer3D::get_singleton()->space_get_direct_state(w3d->get_space());
@@ -204,14 +202,14 @@ void RayCast3D::_update_raycast_state() {
Transform gt = get_global_transform();
- Vector3 to = cast_to;
- if (to == Vector3())
+ Vector3 to = target_position;
+ if (to == Vector3()) {
to = Vector3(0, 0.01, 0);
+ }
PhysicsDirectSpaceState3D::RayResult rr;
if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, collide_with_bodies, collide_with_areas)) {
-
collided = true;
against = rr.collider_id;
collision_point = rr.position;
@@ -229,65 +227,57 @@ void RayCast3D::force_raycast_update() {
}
void RayCast3D::add_exception_rid(const RID &p_rid) {
-
exclude.insert(p_rid);
}
void RayCast3D::add_exception(const Object *p_object) {
-
ERR_FAIL_NULL(p_object);
const CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_object);
- if (!co)
+ if (!co) {
return;
+ }
add_exception_rid(co->get_rid());
}
void RayCast3D::remove_exception_rid(const RID &p_rid) {
-
exclude.erase(p_rid);
}
void RayCast3D::remove_exception(const Object *p_object) {
-
ERR_FAIL_NULL(p_object);
const CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_object);
- if (!co)
+ if (!co) {
return;
+ }
remove_exception_rid(co->get_rid());
}
void RayCast3D::clear_exceptions() {
-
exclude.clear();
}
void RayCast3D::set_collide_with_areas(bool p_clip) {
-
collide_with_areas = p_clip;
}
bool RayCast3D::is_collide_with_areas_enabled() const {
-
return collide_with_areas;
}
void RayCast3D::set_collide_with_bodies(bool p_clip) {
-
collide_with_bodies = p_clip;
}
bool RayCast3D::is_collide_with_bodies_enabled() const {
-
return collide_with_bodies;
}
void RayCast3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast3D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast3D::is_enabled);
- ClassDB::bind_method(D_METHOD("set_cast_to", "local_point"), &RayCast3D::set_cast_to);
- ClassDB::bind_method(D_METHOD("get_cast_to"), &RayCast3D::get_cast_to);
+ ClassDB::bind_method(D_METHOD("set_target_position", "local_point"), &RayCast3D::set_target_position);
+ ClassDB::bind_method(D_METHOD("get_target_position"), &RayCast3D::get_target_position);
ClassDB::bind_method(D_METHOD("is_colliding"), &RayCast3D::is_colliding);
ClassDB::bind_method(D_METHOD("force_raycast_update"), &RayCast3D::force_raycast_update);
@@ -322,7 +312,7 @@ void RayCast3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cast_to"), "set_cast_to", "get_cast_to");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_GROUP("Collide With", "collide_with");
@@ -331,7 +321,6 @@ void RayCast3D::_bind_methods() {
}
void RayCast3D::_create_debug_shape() {
-
if (!debug_material.is_valid()) {
debug_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
@@ -350,16 +339,18 @@ void RayCast3D::_create_debug_shape() {
}
void RayCast3D::_update_debug_shape() {
-
- if (!enabled)
+ if (!enabled) {
return;
+ }
- if (!debug_shape)
+ if (!debug_shape) {
_create_debug_shape();
+ }
MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
- if (!mi->get_mesh().is_valid())
+ if (!mi->get_mesh().is_valid()) {
return;
+ }
Ref<ArrayMesh> mesh = mi->get_mesh();
mesh->clear_surfaces();
@@ -369,7 +360,7 @@ void RayCast3D::_update_debug_shape() {
Vector<Vector3> verts;
verts.push_back(Vector3());
- verts.push_back(cast_to);
+ verts.push_back(target_position);
a[Mesh::ARRAY_VERTEX] = verts;
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a);
@@ -377,27 +368,26 @@ void RayCast3D::_update_debug_shape() {
}
void RayCast3D::_clear_debug_shape() {
-
- if (!debug_shape)
+ if (!debug_shape) {
return;
+ }
MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
- if (mi->is_inside_tree())
+ if (mi->is_inside_tree()) {
mi->queue_delete();
- else
+ } else {
memdelete(mi);
+ }
debug_shape = nullptr;
}
RayCast3D::RayCast3D() {
-
- enabled = false;
-
+ enabled = true;
collided = false;
against_shape = 0;
collision_mask = 1;
- cast_to = Vector3(0, -1, 0);
+ target_position = Vector3(0, -1, 0);
debug_shape = nullptr;
exclude_parent_body = true;
collide_with_areas = false;
diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h
index f8bfb7846a..f4fe7ba621 100644
--- a/scene/3d/ray_cast_3d.h
+++ b/scene/3d/ray_cast_3d.h
@@ -34,7 +34,6 @@
#include "scene/3d/node_3d.h"
class RayCast3D : public Node3D {
-
GDCLASS(RayCast3D, Node3D);
bool enabled;
@@ -44,7 +43,7 @@ class RayCast3D : public Node3D {
Vector3 collision_point;
Vector3 collision_normal;
- Vector3 cast_to;
+ Vector3 target_position;
Set<RID> exclude;
uint32_t collision_mask;
@@ -75,8 +74,8 @@ public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
- void set_cast_to(const Vector3 &p_point);
- Vector3 get_cast_to() const;
+ void set_target_position(const Vector3 &p_point);
+ Vector3 get_target_position() const;
void set_collision_mask(uint32_t p_mask);
uint32_t get_collision_mask() const;
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index 24bf8b43d1..c7948395d3 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -31,59 +31,52 @@
#include "reflection_probe.h"
void ReflectionProbe::set_intensity(float p_intensity) {
-
intensity = p_intensity;
RS::get_singleton()->reflection_probe_set_intensity(probe, p_intensity);
}
float ReflectionProbe::get_intensity() const {
-
return intensity;
}
-void ReflectionProbe::set_interior_ambient(Color p_ambient) {
-
- interior_ambient = p_ambient;
- RS::get_singleton()->reflection_probe_set_interior_ambient(probe, p_ambient);
+void ReflectionProbe::set_ambient_mode(AmbientMode p_mode) {
+ ambient_mode = p_mode;
+ RS::get_singleton()->reflection_probe_set_ambient_mode(probe, RS::ReflectionProbeAmbientMode(p_mode));
+ _change_notify();
}
-void ReflectionProbe::set_interior_ambient_energy(float p_energy) {
- interior_ambient_energy = p_energy;
- RS::get_singleton()->reflection_probe_set_interior_ambient_energy(probe, p_energy);
+ReflectionProbe::AmbientMode ReflectionProbe::get_ambient_mode() const {
+ return ambient_mode;
}
-float ReflectionProbe::get_interior_ambient_energy() const {
- return interior_ambient_energy;
+void ReflectionProbe::set_ambient_color(Color p_ambient) {
+ ambient_color = p_ambient;
+ RS::get_singleton()->reflection_probe_set_ambient_color(probe, p_ambient);
}
-Color ReflectionProbe::get_interior_ambient() const {
-
- return interior_ambient;
+void ReflectionProbe::set_ambient_color_energy(float p_energy) {
+ ambient_color_energy = p_energy;
+ RS::get_singleton()->reflection_probe_set_ambient_energy(probe, p_energy);
}
-void ReflectionProbe::set_interior_ambient_probe_contribution(float p_contribution) {
-
- interior_ambient_probe_contribution = p_contribution;
- RS::get_singleton()->reflection_probe_set_interior_ambient_probe_contribution(probe, p_contribution);
+float ReflectionProbe::get_ambient_color_energy() const {
+ return ambient_color_energy;
}
-float ReflectionProbe::get_interior_ambient_probe_contribution() const {
-
- return interior_ambient_probe_contribution;
+Color ReflectionProbe::get_ambient_color() const {
+ return ambient_color;
}
void ReflectionProbe::set_max_distance(float p_distance) {
-
max_distance = p_distance;
RS::get_singleton()->reflection_probe_set_max_distance(probe, p_distance);
}
-float ReflectionProbe::get_max_distance() const {
+float ReflectionProbe::get_max_distance() const {
return max_distance;
}
void ReflectionProbe::set_extents(const Vector3 &p_extents) {
-
extents = p_extents;
for (int i = 0; i < 3; i++) {
@@ -102,17 +95,15 @@ void ReflectionProbe::set_extents(const Vector3 &p_extents) {
_change_notify("extents");
update_gizmo();
}
-Vector3 ReflectionProbe::get_extents() const {
+Vector3 ReflectionProbe::get_extents() const {
return extents;
}
void ReflectionProbe::set_origin_offset(const Vector3 &p_extents) {
-
origin_offset = p_extents;
for (int i = 0; i < 3; i++) {
-
if (extents[i] - 0.01 < ABS(origin_offset[i])) {
origin_offset[i] = SGN(origin_offset[i]) * (extents[i] - 0.01);
}
@@ -123,50 +114,44 @@ void ReflectionProbe::set_origin_offset(const Vector3 &p_extents) {
_change_notify("origin_offset");
update_gizmo();
}
-Vector3 ReflectionProbe::get_origin_offset() const {
+Vector3 ReflectionProbe::get_origin_offset() const {
return origin_offset;
}
void ReflectionProbe::set_enable_box_projection(bool p_enable) {
-
box_projection = p_enable;
RS::get_singleton()->reflection_probe_set_enable_box_projection(probe, p_enable);
}
-bool ReflectionProbe::is_box_projection_enabled() const {
+bool ReflectionProbe::is_box_projection_enabled() const {
return box_projection;
}
void ReflectionProbe::set_as_interior(bool p_enable) {
-
interior = p_enable;
RS::get_singleton()->reflection_probe_set_as_interior(probe, interior);
- _change_notify();
}
bool ReflectionProbe::is_set_as_interior() const {
-
return interior;
}
void ReflectionProbe::set_enable_shadows(bool p_enable) {
-
enable_shadows = p_enable;
RS::get_singleton()->reflection_probe_set_enable_shadows(probe, p_enable);
}
-bool ReflectionProbe::are_shadows_enabled() const {
+bool ReflectionProbe::are_shadows_enabled() const {
return enable_shadows;
}
void ReflectionProbe::set_cull_mask(uint32_t p_layers) {
-
cull_mask = p_layers;
RS::get_singleton()->reflection_probe_set_cull_mask(probe, p_layers);
}
-uint32_t ReflectionProbe::get_cull_mask() const {
+uint32_t ReflectionProbe::get_cull_mask() const {
return cull_mask;
}
@@ -180,39 +165,36 @@ ReflectionProbe::UpdateMode ReflectionProbe::get_update_mode() const {
}
AABB ReflectionProbe::get_aabb() const {
-
AABB aabb;
aabb.position = -origin_offset;
aabb.size = origin_offset + extents;
return aabb;
}
-Vector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const {
return Vector<Face3>();
}
void ReflectionProbe::_validate_property(PropertyInfo &property) const {
-
- if (property.name == "interior/ambient_color" || property.name == "interior/ambient_energy" || property.name == "interior/ambient_contrib") {
- if (!interior) {
+ if (property.name == "interior/ambient_color" || property.name == "interior/ambient_color_energy") {
+ if (ambient_mode != AMBIENT_COLOR) {
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
}
}
}
void ReflectionProbe::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_intensity", "intensity"), &ReflectionProbe::set_intensity);
ClassDB::bind_method(D_METHOD("get_intensity"), &ReflectionProbe::get_intensity);
- ClassDB::bind_method(D_METHOD("set_interior_ambient", "ambient"), &ReflectionProbe::set_interior_ambient);
- ClassDB::bind_method(D_METHOD("get_interior_ambient"), &ReflectionProbe::get_interior_ambient);
+ ClassDB::bind_method(D_METHOD("set_ambient_mode", "ambient"), &ReflectionProbe::set_ambient_mode);
+ ClassDB::bind_method(D_METHOD("get_ambient_mode"), &ReflectionProbe::get_ambient_mode);
- ClassDB::bind_method(D_METHOD("set_interior_ambient_energy", "ambient_energy"), &ReflectionProbe::set_interior_ambient_energy);
- ClassDB::bind_method(D_METHOD("get_interior_ambient_energy"), &ReflectionProbe::get_interior_ambient_energy);
+ ClassDB::bind_method(D_METHOD("set_ambient_color", "ambient"), &ReflectionProbe::set_ambient_color);
+ ClassDB::bind_method(D_METHOD("get_ambient_color"), &ReflectionProbe::get_ambient_color);
- ClassDB::bind_method(D_METHOD("set_interior_ambient_probe_contribution", "ambient_probe_contribution"), &ReflectionProbe::set_interior_ambient_probe_contribution);
- ClassDB::bind_method(D_METHOD("get_interior_ambient_probe_contribution"), &ReflectionProbe::get_interior_ambient_probe_contribution);
+ ClassDB::bind_method(D_METHOD("set_ambient_color_energy", "ambient_energy"), &ReflectionProbe::set_ambient_color_energy);
+ ClassDB::bind_method(D_METHOD("get_ambient_color_energy"), &ReflectionProbe::get_ambient_color_energy);
ClassDB::bind_method(D_METHOD("set_max_distance", "max_distance"), &ReflectionProbe::set_max_distance);
ClassDB::bind_method(D_METHOD("get_max_distance"), &ReflectionProbe::get_max_distance);
@@ -244,25 +226,28 @@ void ReflectionProbe::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "origin_offset"), "set_origin_offset", "get_origin_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "box_projection"), "set_enable_box_projection", "is_box_projection_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_as_interior", "is_set_as_interior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_shadows"), "set_enable_shadows", "are_shadows_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
- ADD_GROUP("Interior", "interior_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior_enable"), "set_as_interior", "is_set_as_interior");
- ADD_PROPERTY(PropertyInfo(Variant::COLOR, "interior_ambient_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_interior_ambient", "get_interior_ambient");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interior_ambient_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_interior_ambient_energy", "get_interior_ambient_energy");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interior_ambient_contrib", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_interior_ambient_probe_contribution", "get_interior_ambient_probe_contribution");
+ ADD_GROUP("Ambient", "ambient_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_mode", PROPERTY_HINT_ENUM, "Disabled,Environment,ConstantColor"), "set_ambient_mode", "get_ambient_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ambient_color", "get_ambient_color");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ambient_color_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_color_energy", "get_ambient_color_energy");
BIND_ENUM_CONSTANT(UPDATE_ONCE);
BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
+
+ BIND_ENUM_CONSTANT(AMBIENT_DISABLED);
+ BIND_ENUM_CONSTANT(AMBIENT_ENVIRONMENT);
+ BIND_ENUM_CONSTANT(AMBIENT_COLOR);
}
ReflectionProbe::ReflectionProbe() {
-
intensity = 1.0;
- interior_ambient = Color(0, 0, 0);
- interior_ambient_probe_contribution = 0;
- interior_ambient_energy = 1.0;
+ ambient_mode = AMBIENT_ENVIRONMENT;
+ ambient_color = Color(0, 0, 0);
+ ambient_color_energy = 1.0;
max_distance = 0;
extents = Vector3(1, 1, 1);
origin_offset = Vector3(0, 0, 0);
@@ -278,6 +263,5 @@ ReflectionProbe::ReflectionProbe() {
}
ReflectionProbe::~ReflectionProbe() {
-
RS::get_singleton()->free(probe);
}
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
index 3867d13435..56177d0f95 100644
--- a/scene/3d/reflection_probe.h
+++ b/scene/3d/reflection_probe.h
@@ -45,6 +45,12 @@ public:
UPDATE_ALWAYS,
};
+ enum AmbientMode {
+ AMBIENT_DISABLED,
+ AMBIENT_ENVIRONMENT,
+ AMBIENT_COLOR
+ };
+
private:
RID probe;
float intensity;
@@ -54,26 +60,29 @@ private:
bool box_projection;
bool enable_shadows;
bool interior;
- Color interior_ambient;
- float interior_ambient_energy;
- float interior_ambient_probe_contribution;
+ AmbientMode ambient_mode;
+ Color ambient_color;
+ float ambient_color_energy;
uint32_t cull_mask;
UpdateMode update_mode;
protected:
static void _bind_methods();
- void _validate_property(PropertyInfo &property) const;
+ void _validate_property(PropertyInfo &property) const override;
public:
void set_intensity(float p_intensity);
float get_intensity() const;
- void set_interior_ambient(Color p_ambient);
- Color get_interior_ambient() const;
+ void set_ambient_mode(AmbientMode p_mode);
+ AmbientMode get_ambient_mode() const;
+
+ void set_ambient_color(Color p_ambient);
+ Color get_ambient_color() const;
- void set_interior_ambient_energy(float p_energy);
- float get_interior_ambient_energy() const;
+ void set_ambient_color_energy(float p_energy);
+ float get_ambient_color_energy() const;
void set_interior_ambient_probe_contribution(float p_contribution);
float get_interior_ambient_probe_contribution() const;
@@ -102,13 +111,14 @@ public:
void set_update_mode(UpdateMode p_mode);
UpdateMode get_update_mode() const;
- virtual AABB get_aabb() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual AABB get_aabb() const override;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
ReflectionProbe();
~ReflectionProbe();
};
+VARIANT_ENUM_CAST(ReflectionProbe::AmbientMode);
VARIANT_ENUM_CAST(ReflectionProbe::UpdateMode);
#endif // REFLECTIONPROBE_H
diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp
index 38792bbb58..358f9346f8 100644
--- a/scene/3d/remote_transform_3d.cpp
+++ b/scene/3d/remote_transform_3d.cpp
@@ -43,33 +43,37 @@ void RemoteTransform3D::_update_cache() {
}
void RemoteTransform3D::_update_remote() {
-
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
- if (cache.is_null())
+ if (cache.is_null()) {
return;
+ }
Node3D *n = Object::cast_to<Node3D>(ObjectDB::get_instance(cache));
- if (!n)
+ if (!n) {
return;
+ }
- if (!n->is_inside_tree())
+ if (!n->is_inside_tree()) {
return;
+ }
//todo make faster
if (use_global_coordinates) {
-
if (update_remote_position && update_remote_rotation && update_remote_scale) {
n->set_global_transform(get_global_transform());
} else {
Transform our_trans = get_global_transform();
- if (update_remote_rotation)
+ if (update_remote_rotation) {
n->set_rotation(our_trans.basis.get_rotation());
+ }
- if (update_remote_scale)
+ if (update_remote_scale) {
n->set_scale(our_trans.basis.get_scale());
+ }
if (update_remote_position) {
Transform n_trans = n->get_global_transform();
@@ -85,11 +89,13 @@ void RemoteTransform3D::_update_remote() {
} else {
Transform our_trans = get_transform();
- if (update_remote_rotation)
+ if (update_remote_rotation) {
n->set_rotation(our_trans.basis.get_rotation());
+ }
- if (update_remote_scale)
+ if (update_remote_scale) {
n->set_scale(our_trans.basis.get_scale());
+ }
if (update_remote_position) {
Transform n_trans = n->get_transform();
@@ -102,20 +108,17 @@ void RemoteTransform3D::_update_remote() {
}
void RemoteTransform3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_ENTER_TREE: {
-
_update_cache();
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
break;
+ }
if (cache.is_valid()) {
-
_update_remote();
}
@@ -124,7 +127,6 @@ void RemoteTransform3D::_notification(int p_what) {
}
void RemoteTransform3D::set_remote_node(const NodePath &p_remote_node) {
-
remote_node = p_remote_node;
if (is_inside_tree()) {
_update_cache();
@@ -135,7 +137,6 @@ void RemoteTransform3D::set_remote_node(const NodePath &p_remote_node) {
}
NodePath RemoteTransform3D::get_remote_node() const {
-
return remote_node;
}
@@ -179,16 +180,19 @@ void RemoteTransform3D::force_update_cache() {
}
String RemoteTransform3D::get_configuration_warning() const {
+ String warning = Node3D::get_configuration_warning();
if (!has_node(remote_node) || !Object::cast_to<Node3D>(get_node(remote_node))) {
- return TTR("The \"Remote Path\" property must point to a valid Node3D or Node3D-derived node to work.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("The \"Remote Path\" property must point to a valid Node3D or Node3D-derived node to work.");
}
- return String();
+ return warning;
}
void RemoteTransform3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform3D::set_remote_node);
ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform3D::get_remote_node);
ClassDB::bind_method(D_METHOD("force_update_cache"), &RemoteTransform3D::force_update_cache);
@@ -213,7 +217,6 @@ void RemoteTransform3D::_bind_methods() {
}
RemoteTransform3D::RemoteTransform3D() {
-
use_global_coordinates = true;
update_remote_position = true;
update_remote_rotation = true;
diff --git a/scene/3d/remote_transform_3d.h b/scene/3d/remote_transform_3d.h
index 50d7c5a9b2..0ce30f7fce 100644
--- a/scene/3d/remote_transform_3d.h
+++ b/scene/3d/remote_transform_3d.h
@@ -70,7 +70,7 @@ public:
void force_update_cache();
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
RemoteTransform3D();
};
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index 973822653a..0ae1c0e3b6 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -30,12 +30,13 @@
#include "skeleton_3d.h"
-#include "core/engine.h"
-#include "core/message_queue.h"
-#include "core/project_settings.h"
-#include "core/type_info.h"
+#include "core/config/engine.h"
+#include "core/config/project_settings.h"
+#include "core/object/message_queue.h"
+#include "core/variant/type_info.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/resources/surface_tool.h"
+#include "scene/scene_string_names.h"
void SkinReference::_skin_changed() {
if (skeleton_node) {
@@ -66,40 +67,40 @@ SkinReference::~SkinReference() {
RS::get_singleton()->free(skeleton);
}
-bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) {
+///////////////////////////////////////
+bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) {
String path = p_path;
- if (!path.begins_with("bones/"))
+ if (!path.begins_with("bones/")) {
return false;
+ }
int which = path.get_slicec('/', 1).to_int();
String what = path.get_slicec('/', 2);
if (which == bones.size() && what == "name") {
-
add_bone(p_value);
return true;
}
ERR_FAIL_INDEX_V(which, bones.size(), false);
- if (what == "parent")
+ if (what == "parent") {
set_bone_parent(which, p_value);
- else if (what == "rest")
+ } else if (what == "rest") {
set_bone_rest(which, p_value);
- else if (what == "enabled")
+ } else if (what == "enabled") {
set_bone_enabled(which, p_value);
- else if (what == "pose")
+ } else if (what == "pose") {
set_bone_pose(which, p_value);
- else if (what == "bound_children") {
+ } else if (what == "bound_children") {
Array children = p_value;
if (is_inside_tree()) {
bones.write[which].nodes_bound.clear();
for (int i = 0; i < children.size(); i++) {
-
NodePath npath = children[i];
ERR_CONTINUE(npath.operator String() == "");
Node *node = get_node(npath);
@@ -115,32 +116,31 @@ bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) {
}
bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const {
-
String path = p_path;
- if (!path.begins_with("bones/"))
+ if (!path.begins_with("bones/")) {
return false;
+ }
int which = path.get_slicec('/', 1).to_int();
String what = path.get_slicec('/', 2);
ERR_FAIL_INDEX_V(which, bones.size(), false);
- if (what == "name")
+ if (what == "name") {
r_ret = get_bone_name(which);
- else if (what == "parent")
+ } else if (what == "parent") {
r_ret = get_bone_parent(which);
- else if (what == "rest")
+ } else if (what == "rest") {
r_ret = get_bone_rest(which);
- else if (what == "enabled")
+ } else if (what == "enabled") {
r_ret = is_bone_enabled(which);
- else if (what == "pose")
+ } else if (what == "pose") {
r_ret = get_bone_pose(which);
- else if (what == "bound_children") {
+ } else if (what == "bound_children") {
Array children;
for (const List<ObjectID>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) {
-
Object *obj = ObjectDB::get_instance(E->get());
ERR_CONTINUE(!obj);
Node *node = Object::cast_to<Node>(obj);
@@ -150,29 +150,29 @@ bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const {
}
r_ret = children;
- } else
+ } else {
return false;
+ }
return true;
}
-void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const {
+void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const {
for (int i = 0; i < bones.size(); i++) {
-
String prep = "bones/" + itos(i) + "/";
- p_list->push_back(PropertyInfo(Variant::STRING, prep + "name"));
- p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1"));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "rest"));
- p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled"));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "pose", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
- p_list->push_back(PropertyInfo(Variant::ARRAY, prep + "bound_children"));
+ p_list->push_back(PropertyInfo(Variant::STRING, prep + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "rest", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "pose", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, prep + "bound_children", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
}
}
void Skeleton3D::_update_process_order() {
-
- if (!process_order_dirty)
+ if (!process_order_dirty) {
return;
+ }
Bone *bonesptr = bones.ptrw();
int len = bones.size();
@@ -180,7 +180,6 @@ void Skeleton3D::_update_process_order() {
process_order.resize(len);
int *order = process_order.ptrw();
for (int i = 0; i < len; i++) {
-
if (bonesptr[i].parent >= len) {
//validate this just in case
ERR_PRINT("Bone " + itos(i) + " has invalid parent: " + itos(bonesptr[i].parent));
@@ -197,8 +196,9 @@ void Skeleton3D::_update_process_order() {
bool swapped = false;
for (int i = 0; i < len; i++) {
int parent_idx = bonesptr[order[i]].parent;
- if (parent_idx < 0)
+ if (parent_idx < 0) {
continue; //do nothing because it has no parent
+ }
//swap indices
int parent_order = bonesptr[parent_idx].sort_index;
if (parent_order > i) {
@@ -210,25 +210,23 @@ void Skeleton3D::_update_process_order() {
}
}
- if (!swapped)
+ if (!swapped) {
break;
+ }
pass_count++;
}
if (pass_count == len * len) {
- ERR_PRINT("Skeleton parenthood graph is cyclic");
+ ERR_PRINT("Skeleton3D parenthood graph is cyclic");
}
process_order_dirty = false;
}
void Skeleton3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_UPDATE_SKELETON: {
-
- RenderingServer *vs = RenderingServer::get_singleton();
+ RenderingServer *rs = RenderingServer::get_singleton();
Bone *bonesptr = bones.ptrw();
int len = bones.size();
@@ -237,7 +235,6 @@ void Skeleton3D::_notification(int p_what) {
const int *order = process_order.ptr();
for (int i = 0; i < len; i++) {
-
Bone &b = bonesptr[order[i]];
if (b.global_pose_override_amount >= 0.999) {
@@ -245,50 +242,38 @@ void Skeleton3D::_notification(int p_what) {
} else {
if (b.disable_rest) {
if (b.enabled) {
-
Transform pose = b.pose;
if (b.custom_pose_enable) {
pose = b.custom_pose * pose;
}
if (b.parent >= 0) {
-
b.pose_global = bonesptr[b.parent].pose_global * pose;
} else {
-
b.pose_global = pose;
}
} else {
-
if (b.parent >= 0) {
-
b.pose_global = bonesptr[b.parent].pose_global;
} else {
-
b.pose_global = Transform();
}
}
} else {
if (b.enabled) {
-
Transform pose = b.pose;
if (b.custom_pose_enable) {
pose = b.custom_pose * pose;
}
if (b.parent >= 0) {
-
b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose);
} else {
-
b.pose_global = b.rest * pose;
}
} else {
-
if (b.parent >= 0) {
-
b.pose_global = bonesptr[b.parent].pose_global * b.rest;
} else {
-
b.pose_global = b.rest;
}
}
@@ -304,18 +289,16 @@ void Skeleton3D::_notification(int p_what) {
}
for (List<ObjectID>::Element *E = b.nodes_bound.front(); E; E = E->next()) {
-
Object *obj = ObjectDB::get_instance(E->get());
ERR_CONTINUE(!obj);
- Node3D *sp = Object::cast_to<Node3D>(obj);
- ERR_CONTINUE(!sp);
- sp->set_transform(b.pose_global);
+ Node3D *node_3d = Object::cast_to<Node3D>(obj);
+ ERR_CONTINUE(!node_3d);
+ node_3d->set_transform(b.pose_global);
}
}
//update skins
for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) {
-
const Skin *skin = E->get()->skin.operator->();
RID skeleton = E->get()->skeleton;
uint32_t bind_count = skin->get_bind_count();
@@ -328,7 +311,6 @@ void Skeleton3D::_notification(int p_what) {
}
if (E->get()->skeleton_version != version) {
-
for (uint32_t i = 0; i < bind_count; i++) {
StringName bind_name = skin->get_bind_name(i);
@@ -344,7 +326,7 @@ void Skeleton3D::_notification(int p_what) {
}
if (!found) {
- ERR_PRINT("Skin bind #" + itos(i) + " contains named bind '" + String(bind_name) + "' but Skeleton has no bone by that name.");
+ ERR_PRINT("Skin bind #" + itos(i) + " contains named bind '" + String(bind_name) + "' but Skeleton3D has no bone by that name.");
E->get()->skin_bone_indices_ptrs[i] = 0;
}
} else if (skin->get_bind_bone(i) >= 0) {
@@ -367,11 +349,16 @@ void Skeleton3D::_notification(int p_what) {
for (uint32_t i = 0; i < bind_count; i++) {
uint32_t bone_index = E->get()->skin_bone_indices_ptrs[i];
ERR_CONTINUE(bone_index >= (uint32_t)len);
- vs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i));
+ rs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i));
}
}
dirty = false;
+
+#ifdef TOOLS_ENABLED
+ emit_signal(SceneStringNames::get_singleton()->pose_updated);
+#endif // TOOLS_ENABLED
+
} break;
#ifndef _3D_DISABLED
@@ -405,7 +392,6 @@ void Skeleton3D::clear_bones_global_pose_override() {
}
void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent) {
-
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].global_pose_override_amount = p_amount;
bones.write[p_bone].global_pose_override = p_pose;
@@ -414,20 +400,18 @@ void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform &p_po
}
Transform Skeleton3D::get_bone_global_pose(int p_bone) const {
-
ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
- if (dirty)
+ if (dirty) {
const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON);
+ }
return bones[p_bone].pose_global;
}
// skeleton creation api
void Skeleton3D::add_bone(const String &p_name) {
-
ERR_FAIL_COND(p_name == "" || p_name.find(":") != -1 || p_name.find("/") != -1);
for (int i = 0; i < bones.size(); i++) {
-
ERR_FAIL_COND(bones[i].name == p_name);
}
@@ -439,43 +423,42 @@ void Skeleton3D::add_bone(const String &p_name) {
_make_dirty();
update_gizmo();
}
-int Skeleton3D::find_bone(const String &p_name) const {
+int Skeleton3D::find_bone(const String &p_name) const {
for (int i = 0; i < bones.size(); i++) {
-
- if (bones[i].name == p_name)
+ if (bones[i].name == p_name) {
return i;
+ }
}
return -1;
}
-String Skeleton3D::get_bone_name(int p_bone) const {
+String Skeleton3D::get_bone_name(int p_bone) const {
ERR_FAIL_INDEX_V(p_bone, bones.size(), "");
return bones[p_bone].name;
}
bool Skeleton3D::is_bone_parent_of(int p_bone, int p_parent_bone_id) const {
-
int parent_of_bone = get_bone_parent(p_bone);
- if (-1 == parent_of_bone)
+ if (-1 == parent_of_bone) {
return false;
+ }
- if (parent_of_bone == p_parent_bone_id)
+ if (parent_of_bone == p_parent_bone_id) {
return true;
+ }
return is_bone_parent_of(parent_of_bone, p_parent_bone_id);
}
int Skeleton3D::get_bone_count() const {
-
return bones.size();
}
void Skeleton3D::set_bone_parent(int p_bone, int p_parent) {
-
ERR_FAIL_INDEX(p_bone, bones.size());
ERR_FAIL_COND(p_parent != -1 && (p_parent < 0));
@@ -485,7 +468,6 @@ void Skeleton3D::set_bone_parent(int p_bone, int p_parent) {
}
void Skeleton3D::unparent_bone_and_rest(int p_bone) {
-
ERR_FAIL_INDEX(p_bone, bones.size());
_update_process_order();
@@ -503,80 +485,73 @@ void Skeleton3D::unparent_bone_and_rest(int p_bone) {
}
void Skeleton3D::set_bone_disable_rest(int p_bone, bool p_disable) {
-
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].disable_rest = p_disable;
}
bool Skeleton3D::is_bone_rest_disabled(int p_bone) const {
-
ERR_FAIL_INDEX_V(p_bone, bones.size(), false);
return bones[p_bone].disable_rest;
}
int Skeleton3D::get_bone_parent(int p_bone) const {
-
ERR_FAIL_INDEX_V(p_bone, bones.size(), -1);
return bones[p_bone].parent;
}
void Skeleton3D::set_bone_rest(int p_bone, const Transform &p_rest) {
-
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].rest = p_rest;
_make_dirty();
}
-Transform Skeleton3D::get_bone_rest(int p_bone) const {
+Transform Skeleton3D::get_bone_rest(int p_bone) const {
ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
return bones[p_bone].rest;
}
void Skeleton3D::set_bone_enabled(int p_bone, bool p_enabled) {
-
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].enabled = p_enabled;
_make_dirty();
}
-bool Skeleton3D::is_bone_enabled(int p_bone) const {
+bool Skeleton3D::is_bone_enabled(int p_bone) const {
ERR_FAIL_INDEX_V(p_bone, bones.size(), false);
return bones[p_bone].enabled;
}
void Skeleton3D::bind_child_node_to_bone(int p_bone, Node *p_node) {
-
ERR_FAIL_NULL(p_node);
ERR_FAIL_INDEX(p_bone, bones.size());
ObjectID id = p_node->get_instance_id();
for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
-
- if (E->get() == id)
+ if (E->get() == id) {
return; // already here
+ }
}
bones.write[p_bone].nodes_bound.push_back(id);
}
-void Skeleton3D::unbind_child_node_from_bone(int p_bone, Node *p_node) {
+void Skeleton3D::unbind_child_node_from_bone(int p_bone, Node *p_node) {
ERR_FAIL_NULL(p_node);
ERR_FAIL_INDEX(p_bone, bones.size());
ObjectID id = p_node->get_instance_id();
bones.write[p_bone].nodes_bound.erase(id);
}
-void Skeleton3D::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) const {
+void Skeleton3D::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) const {
ERR_FAIL_INDEX(p_bone, bones.size());
for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
-
Object *obj = ObjectDB::get_instance(E->get());
ERR_CONTINUE(!obj);
p_bound->push_back(Object::cast_to<Node>(obj));
@@ -584,7 +559,6 @@ void Skeleton3D::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound
}
void Skeleton3D::clear_bones() {
-
bones.clear();
process_order_dirty = true;
version++;
@@ -594,7 +568,6 @@ void Skeleton3D::clear_bones() {
// posing api
void Skeleton3D::set_bone_pose(int p_bone, const Transform &p_pose) {
-
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].pose = p_pose;
@@ -602,14 +575,13 @@ void Skeleton3D::set_bone_pose(int p_bone, const Transform &p_pose) {
_make_dirty();
}
}
-Transform Skeleton3D::get_bone_pose(int p_bone) const {
+Transform Skeleton3D::get_bone_pose(int p_bone) const {
ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
return bones[p_bone].pose;
}
void Skeleton3D::set_bone_custom_pose(int p_bone, const Transform &p_custom_pose) {
-
ERR_FAIL_INDEX(p_bone, bones.size());
//ERR_FAIL_COND( !is_inside_scene() );
@@ -620,15 +592,14 @@ void Skeleton3D::set_bone_custom_pose(int p_bone, const Transform &p_custom_pose
}
Transform Skeleton3D::get_bone_custom_pose(int p_bone) const {
-
ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
return bones[p_bone].custom_pose;
}
void Skeleton3D::_make_dirty() {
-
- if (dirty)
+ if (dirty) {
return;
+ }
MessageQueue::get_singleton()->push_notification(this, NOTIFICATION_UPDATE_SKELETON);
dirty = true;
@@ -640,8 +611,12 @@ int Skeleton3D::get_process_order(int p_idx) {
return process_order[p_idx];
}
-void Skeleton3D::localize_rests() {
+Vector<int> Skeleton3D::get_bone_process_orders() {
+ _update_process_order();
+ return process_order;
+}
+void Skeleton3D::localize_rests() {
_update_process_order();
for (int i = bones.size() - 1; i >= 0; i--) {
@@ -729,14 +704,14 @@ void Skeleton3D::_rebuild_physical_bones_cache() {
PhysicalBone3D *parent_pb = _get_physical_bone_parent(i);
if (parent_pb != bones[i].physical_bone) {
bones.write[i].cache_parent_physical_bone = parent_pb;
- if (bones[i].physical_bone)
+ if (bones[i].physical_bone) {
bones[i].physical_bone->_on_bone_parent_changed();
+ }
}
}
}
void _pb_stop_simulation(Node *p_node) {
-
for (int i = p_node->get_child_count() - 1; 0 <= i; --i) {
_pb_stop_simulation(p_node->get_child(i));
}
@@ -755,7 +730,6 @@ void Skeleton3D::physical_bones_stop_simulation() {
}
void _pb_start_simulation(const Skeleton3D *p_skeleton, Node *p_node, const Vector<int> &p_sim_bones) {
-
for (int i = p_node->get_child_count() - 1; 0 <= i; --i) {
_pb_start_simulation(p_skeleton, p_node->get_child(i), p_sim_bones);
}
@@ -782,8 +756,9 @@ void Skeleton3D::physical_bones_start_simulation_on(const TypedArray<StringName>
int c = 0;
for (int i = sim_bones.size() - 1; 0 <= i; --i) {
int bone_id = find_bone(p_bones[i]);
- if (bone_id != -1)
+ if (bone_id != -1) {
sim_bones.write[c++] = bone_id;
+ }
}
sim_bones.resize(c);
}
@@ -792,7 +767,6 @@ void Skeleton3D::physical_bones_start_simulation_on(const TypedArray<StringName>
}
void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) {
-
for (int i = p_node->get_child_count() - 1; 0 <= i; --i) {
_physical_bones_add_remove_collision_exception(p_add, p_node->get_child(i), p_exception);
}
@@ -822,7 +796,6 @@ void Skeleton3D::_skin_changed() {
}
Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) {
-
for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) {
if (E->get()->skin == p_skin) {
return Ref<SkinReference>(E->get());
@@ -882,8 +855,17 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) {
return skin_ref;
}
-void Skeleton3D::_bind_methods() {
+// helper functions
+Transform Skeleton3D::bone_transform_to_world_transform(Transform p_bone_transform) {
+ return get_global_transform() * p_bone_transform;
+}
+
+Transform Skeleton3D::world_transform_to_bone_transform(Transform p_world_transform) {
+ return get_global_transform().affine_inverse() * p_world_transform;
+}
+void Skeleton3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_bone_process_orders"), &Skeleton3D::get_bone_process_orders);
ClassDB::bind_method(D_METHOD("add_bone", "name"), &Skeleton3D::add_bone);
ClassDB::bind_method(D_METHOD("find_bone", "name"), &Skeleton3D::find_bone);
ClassDB::bind_method(D_METHOD("get_bone_name", "bone_idx"), &Skeleton3D::get_bone_name);
@@ -921,6 +903,9 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton3D::get_bone_custom_pose);
ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton3D::set_bone_custom_pose);
+ ClassDB::bind_method(D_METHOD("bone_transform_to_world_transform", "bone_transform"), &Skeleton3D::bone_transform_to_world_transform);
+ ClassDB::bind_method(D_METHOD("world_transform_to_bone_transform", "world_transform"), &Skeleton3D::world_transform_to_bone_transform);
+
#ifndef _3D_DISABLED
ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton3D::set_animate_physical_bones);
@@ -934,11 +919,14 @@ void Skeleton3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones");
#endif // _3D_DISABLED
+#ifdef TOOLS_ENABLED
+ ADD_SIGNAL(MethodInfo("pose_updated"));
+#endif // TOOLS_ENABLED
+
BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON);
}
Skeleton3D::Skeleton3D() {
-
animate_physical_bones = true;
dirty = false;
version = 1;
@@ -946,7 +934,6 @@ Skeleton3D::Skeleton3D() {
}
Skeleton3D::~Skeleton3D() {
-
//some skins may remain bound
for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) {
E->get()->skeleton_node = nullptr;
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index 0bccd3f8fc..c54f89d3ce 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -31,7 +31,7 @@
#ifndef SKELETON_3D_H
#define SKELETON_3D_H
-#include "core/rid.h"
+#include "core/templates/rid.h"
#include "scene/3d/node_3d.h"
#include "scene/resources/skin.h"
@@ -66,18 +66,12 @@ public:
};
class Skeleton3D : public Node3D {
-
GDCLASS(Skeleton3D, Node3D);
private:
friend class SkinReference;
- Set<SkinReference *> skin_bindings;
-
- void _skin_changed();
-
struct Bone {
-
String name;
bool enabled;
@@ -118,6 +112,10 @@ private:
}
};
+ Set<SkinReference *> skin_bindings;
+
+ void _skin_changed();
+
bool animate_physical_bones;
Vector<Bone> bones;
Vector<int> process_order;
@@ -130,13 +128,11 @@ private:
// bind helpers
Array _get_bound_child_nodes_to_bone(int p_bone) const {
-
Array bound;
List<Node *> children;
get_bound_child_nodes_to_bone(p_bone, &children);
for (int i = 0; i < children.size(); i++) {
-
bound.push_back(children[i]);
}
return bound;
@@ -153,7 +149,6 @@ protected:
public:
enum {
-
NOTIFICATION_UPDATE_SKELETON = 50
};
@@ -200,9 +195,14 @@ public:
void localize_rests(); // used for loaders and tools
int get_process_order(int p_idx);
+ Vector<int> get_bone_process_orders();
Ref<SkinReference> register_skin(const Ref<Skin> &p_skin);
+ // Helper functions
+ Transform bone_transform_to_world_transform(Transform p_transform);
+ Transform world_transform_to_bone_transform(Transform p_transform);
+
#ifndef _3D_DISABLED
// Physical bone API
@@ -216,7 +216,7 @@ public:
PhysicalBone3D *get_physical_bone_parent(int p_bone);
private:
- /// This is a slow API os it's cached
+ /// This is a slow API, so it's cached
PhysicalBone3D *_get_physical_bone_parent(int p_bone);
void _rebuild_physical_bones_cache();
diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp
index 7366290ed3..32d7afd5df 100644
--- a/scene/3d/skeleton_ik_3d.cpp
+++ b/scene/3d/skeleton_ik_3d.cpp
@@ -55,7 +55,6 @@ FabrikInverseKinematic::ChainItem *FabrikInverseKinematic::ChainItem::add_child(
/// Build a chain that starts from the root to tip
bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain) {
-
ERR_FAIL_COND_V(-1 == p_task->root_bone, false);
Chain &chain(p_task->chain);
@@ -75,7 +74,6 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
chain_ids.resize(p_task->skeleton->get_bone_count());
for (int x = p_task->end_effectors.size() - 1; 0 <= x; --x) {
-
const EndEffector *ee(&p_task->end_effectors[x]);
ERR_FAIL_COND_V(p_task->root_bone >= ee->tip_bone, false);
ERR_FAIL_INDEX_V(ee->tip_bone, p_task->skeleton->get_bone_count(), false);
@@ -84,7 +82,6 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
// Picks all IDs that composing a single chain in reverse order (except the root)
BoneId chain_sub_tip(ee->tip_bone);
while (chain_sub_tip > p_task->root_bone) {
-
chain_ids.write[sub_chain_size++] = chain_sub_tip;
chain_sub_tip = p_task->skeleton->get_bone_parent(chain_sub_tip);
}
@@ -95,10 +92,8 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
// For each chain item id will be created a ChainItem if doesn't exists
ChainItem *sub_chain(&chain.chain_root);
for (int i = sub_chain_size - 1; 0 <= i; --i) {
-
ChainItem *child_ci(sub_chain->find_child(chain_ids[i]));
if (!child_ci) {
-
child_ci = sub_chain->add_child(chain_ids[i]);
child_ci->pb = p_task->skeleton->get_physical_bone(child_ci->bone);
@@ -118,8 +113,9 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
}
}
- if (!middle_chain_item_id)
+ if (!middle_chain_item_id) {
chain.middle_chain_item = nullptr;
+ }
// Initialize current tip
chain.tips.write[x].chain_item = sub_chain;
@@ -137,9 +133,9 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
}
void FabrikInverseKinematic::update_chain(const Skeleton3D *p_sk, ChainItem *p_chain_item) {
-
- if (!p_chain_item)
+ if (!p_chain_item) {
return;
+ }
p_chain_item->initial_transform = p_sk->get_bone_global_pose(p_chain_item->bone);
p_chain_item->current_pos = p_chain_item->initial_transform.origin;
@@ -151,7 +147,6 @@ void FabrikInverseKinematic::update_chain(const Skeleton3D *p_sk, ChainItem *p_c
}
void FabrikInverseKinematic::solve_simple(Task *p_task, bool p_solve_magnet) {
-
real_t distance_to_goal(1e4);
real_t previous_distance_to_goal(0);
int can_solve(p_task->max_iterations);
@@ -167,7 +162,6 @@ void FabrikInverseKinematic::solve_simple(Task *p_task, bool p_solve_magnet) {
}
void FabrikInverseKinematic::solve_simple_backwards(Chain &r_chain, bool p_solve_magnet) {
-
if (p_solve_magnet && !r_chain.middle_chain_item) {
return;
}
@@ -200,7 +194,6 @@ void FabrikInverseKinematic::solve_simple_backwards(Chain &r_chain, bool p_solve
}
void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_magnet) {
-
if (p_solve_magnet && !r_chain.middle_chain_item) {
return;
}
@@ -212,7 +205,6 @@ void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_
sub_chain_root->current_pos = origin;
if (!sub_chain_root->children.empty()) {
-
ChainItem &child(sub_chain_root->children.write[0]);
// Is not tip
@@ -231,7 +223,6 @@ void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_
sub_chain_root = &child;
}
} else {
-
// Is tip
sub_chain_root = nullptr;
}
@@ -239,7 +230,6 @@ void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_
}
FabrikInverseKinematic::Task *FabrikInverseKinematic::create_simple_task(Skeleton3D *p_sk, BoneId root_bone, BoneId tip_bone, const Transform &goal_transform) {
-
FabrikInverseKinematic::EndEffector ee;
ee.tip_bone = tip_bone;
@@ -258,8 +248,9 @@ FabrikInverseKinematic::Task *FabrikInverseKinematic::create_simple_task(Skeleto
}
void FabrikInverseKinematic::free_task(Task *p_task) {
- if (p_task)
+ if (p_task) {
memdelete(p_task);
+ }
}
void FabrikInverseKinematic::set_goal(Task *p_task, const Transform &p_goal) {
@@ -267,12 +258,10 @@ void FabrikInverseKinematic::set_goal(Task *p_task, const Transform &p_goal) {
}
void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_transf, real_t blending_delta) {
-
if (blending_delta >= 0.99f) {
// Update the end_effector (local transform) without blending
p_task->end_effectors.write[0].goal_transform = p_inverse_transf * p_task->goal_global_transform;
} else {
-
// End effector in local transform
const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose(p_task->end_effectors.write[0].tip_bone));
@@ -282,19 +271,26 @@ void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_
}
void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position) {
-
if (blending_delta <= 0.01f) {
return; // Skip solving
}
- p_task->skeleton->clear_bones_global_pose_override();
+ p_task->skeleton->set_bone_global_pose_override(p_task->chain.chain_root.bone, Transform(), 0.0, true);
+
+ if (p_task->chain.middle_chain_item) {
+ p_task->skeleton->set_bone_global_pose_override(p_task->chain.middle_chain_item->bone, Transform(), 0.0, true);
+ }
+
+ for (int i = 0; i < p_task->chain.tips.size(); i += 1) {
+ p_task->skeleton->set_bone_global_pose_override(p_task->chain.tips[i].chain_item->bone, Transform(), 0.0, true);
+ }
make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse().scaled(p_task->skeleton->get_global_transform().get_basis().get_scale()), blending_delta);
update_chain(p_task->skeleton, &p_task->chain.chain_root);
if (p_use_magnet && p_task->chain.middle_chain_item) {
- p_task->chain.magnet_position = p_task->chain.middle_chain_item->initial_transform.origin.linear_interpolate(p_magnet_position, blending_delta);
+ p_task->chain.magnet_position = p_task->chain.middle_chain_item->initial_transform.origin.lerp(p_magnet_position, blending_delta);
solve_simple(p_task, true);
}
solve_simple(p_task, false);
@@ -306,7 +302,6 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
new_bone_pose.origin = ci->current_pos;
if (!ci->children.empty()) {
-
/// Rotate basis
const Vector3 initial_ori((ci->children[0].initial_transform.origin - ci->initial_transform.origin).normalized());
const Vector3 rot_axis(initial_ori.cross(ci->current_ori).normalized());
@@ -317,38 +312,37 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
}
} else {
// Set target orientation to tip
- if (override_tip_basis)
+ if (override_tip_basis) {
new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
- else
+ } else {
new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis;
+ }
}
p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1.0, true);
- if (!ci->children.empty())
+ if (!ci->children.empty()) {
ci = &ci->children.write[0];
- else
+ } else {
ci = nullptr;
+ }
}
}
void SkeletonIK3D::_validate_property(PropertyInfo &property) const {
-
if (property.name == "root_bone" || property.name == "tip_bone") {
-
if (skeleton) {
-
String names("--,");
for (int i = 0; i < skeleton->get_bone_count(); i++) {
- if (i > 0)
+ if (i > 0) {
names += ",";
+ }
names += skeleton->get_bone_name(i);
}
property.hint = PROPERTY_HINT_ENUM;
property.hint_string = names;
} else {
-
property.hint = PROPERTY_HINT_NONE;
property.hint_string = "";
}
@@ -356,7 +350,6 @@ void SkeletonIK3D::_validate_property(PropertyInfo &property) const {
}
void SkeletonIK3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_root_bone", "root_bone"), &SkeletonIK3D::set_root_bone);
ClassDB::bind_method(D_METHOD("get_root_bone"), &SkeletonIK3D::get_root_bone);
@@ -413,9 +406,9 @@ void SkeletonIK3D::_notification(int p_what) {
reload_chain();
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
-
- if (target_node_override)
+ if (target_node_override) {
reload_goal();
+ }
_solve_chain();
@@ -426,15 +419,7 @@ void SkeletonIK3D::_notification(int p_what) {
}
}
-SkeletonIK3D::SkeletonIK3D() :
- interpolation(1),
- override_tip_basis(true),
- use_magnet(false),
- min_distance(0.01),
- max_iterations(10),
- skeleton(nullptr),
- target_node_override(nullptr),
- task(nullptr) {
+SkeletonIK3D::SkeletonIK3D() {
}
SkeletonIK3D::~SkeletonIK3D() {
@@ -526,6 +511,11 @@ bool SkeletonIK3D::is_running() {
void SkeletonIK3D::start(bool p_one_time) {
if (p_one_time) {
set_process_internal(false);
+
+ if (target_node_override) {
+ reload_goal();
+ }
+
_solve_chain();
} else {
set_process_internal(true);
@@ -537,23 +527,24 @@ void SkeletonIK3D::stop() {
}
Transform SkeletonIK3D::_get_target_transform() {
-
- if (!target_node_override && !target_node_path_override.is_empty())
+ if (!target_node_override && !target_node_path_override.is_empty()) {
target_node_override = Object::cast_to<Node3D>(get_node(target_node_path_override));
+ }
- if (target_node_override)
+ if (target_node_override) {
return target_node_override->get_global_transform();
- else
+ } else {
return target;
+ }
}
void SkeletonIK3D::reload_chain() {
-
FabrikInverseKinematic::free_task(task);
task = nullptr;
- if (!skeleton)
+ if (!skeleton) {
return;
+ }
task = FabrikInverseKinematic::create_simple_task(skeleton, skeleton->find_bone(root_bone), skeleton->find_bone(tip_bone), _get_target_transform());
if (task) {
@@ -563,15 +554,17 @@ void SkeletonIK3D::reload_chain() {
}
void SkeletonIK3D::reload_goal() {
- if (!task)
+ if (!task) {
return;
+ }
FabrikInverseKinematic::set_goal(task, _get_target_transform());
}
void SkeletonIK3D::_solve_chain() {
- if (!task)
+ if (!task) {
return;
+ }
FabrikInverseKinematic::solve(task, interpolation, override_tip_basis, use_magnet, magnet_position);
}
diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h
index 5fbbe6e9e7..80acc3e937 100644
--- a/scene/3d/skeleton_ik_3d.h
+++ b/scene/3d/skeleton_ik_3d.h
@@ -41,45 +41,37 @@
#include "scene/3d/skeleton_3d.h"
class FabrikInverseKinematic {
-
struct EndEffector {
BoneId tip_bone;
Transform goal_transform;
};
struct ChainItem {
-
Vector<ChainItem> children;
- ChainItem *parent_item;
+ ChainItem *parent_item = nullptr;
// Bone info
- BoneId bone;
- PhysicalBone3D *pb;
+ BoneId bone = -1;
+ PhysicalBone3D *pb = nullptr;
- real_t length;
+ real_t length = 0;
/// Positions relative to root bone
Transform initial_transform;
Vector3 current_pos;
// Direction from this bone to child
Vector3 current_ori;
- ChainItem() :
- parent_item(nullptr),
- bone(-1),
- pb(nullptr),
- length(0) {}
+ ChainItem() {}
ChainItem *find_child(const BoneId p_bone_id);
ChainItem *add_child(const BoneId p_bone_id);
};
struct ChainTip {
- ChainItem *chain_item;
- const EndEffector *end_effector;
+ ChainItem *chain_item = nullptr;
+ const EndEffector *end_effector = nullptr;
- ChainTip() :
- chain_item(nullptr),
- end_effector(nullptr) {}
+ ChainTip() {}
ChainTip(ChainItem *p_chain_item, const EndEffector *p_end_effector) :
chain_item(p_chain_item),
@@ -100,25 +92,21 @@ class FabrikInverseKinematic {
public:
struct Task {
RID self;
- Skeleton3D *skeleton;
+ Skeleton3D *skeleton = nullptr;
Chain chain;
// Settings
- real_t min_distance;
- int max_iterations;
+ real_t min_distance = 0.01;
+ int max_iterations = 10;
// Bone data
- BoneId root_bone;
+ BoneId root_bone = -1;
Vector<EndEffector> end_effectors;
Transform goal_global_transform;
- Task() :
- skeleton(nullptr),
- min_distance(0.01),
- max_iterations(10),
- root_bone(-1) {}
+ Task() {}
};
private:
@@ -146,23 +134,23 @@ class SkeletonIK3D : public Node {
StringName root_bone;
StringName tip_bone;
- real_t interpolation;
+ real_t interpolation = 1;
Transform target;
NodePath target_node_path_override;
- bool override_tip_basis;
- bool use_magnet;
+ bool override_tip_basis = true;
+ bool use_magnet = false;
Vector3 magnet_position;
- real_t min_distance;
- int max_iterations;
+ real_t min_distance = 0.01;
+ int max_iterations = 10;
- Skeleton3D *skeleton;
- Node3D *target_node_override;
- FabrikInverseKinematic::Task *task;
+ Skeleton3D *skeleton = nullptr;
+ Node3D *target_node_override = nullptr;
+ FabrikInverseKinematic::Task *task = nullptr;
protected:
virtual void
- _validate_property(PropertyInfo &property) const;
+ _validate_property(PropertyInfo &property) const override;
static void _bind_methods();
virtual void _notification(int p_what);
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index 6092818252..132c35771b 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -30,10 +30,10 @@
#include "soft_body_3d.h"
-#include "core/list.h"
-#include "core/object.h"
+#include "core/object/class_db.h"
#include "core/os/os.h"
-#include "core/rid.h"
+#include "core/templates/list.h"
+#include "core/templates/rid.h"
#include "scene/3d/collision_object_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/3d/skeleton_3d.h"
@@ -65,7 +65,6 @@ void SoftBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) {
}
void SoftBodyRenderingServerHandler::clear() {
-
if (mesh.is_valid()) {
buffer.resize(0);
}
@@ -97,9 +96,7 @@ void SoftBodyRenderingServerHandler::set_aabb(const AABB &p_aabb) {
RS::get_singleton()->mesh_set_custom_aabb(mesh, p_aabb);
}
-SoftBody3D::PinnedPoint::PinnedPoint() :
- point_index(-1),
- spatial_attachment(nullptr) {
+SoftBody3D::PinnedPoint::PinnedPoint() {
}
SoftBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) {
@@ -109,7 +106,7 @@ SoftBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) {
offset = obj_tocopy.offset;
}
-SoftBody3D::PinnedPoint SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) {
+SoftBody3D::PinnedPoint &SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) {
point_index = obj.point_index;
spatial_attachment_path = obj.spatial_attachment_path;
spatial_attachment = obj.spatial_attachment;
@@ -118,8 +115,9 @@ SoftBody3D::PinnedPoint SoftBody3D::PinnedPoint::operator=(const PinnedPoint &ob
}
void SoftBody3D::_update_pickable() {
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
bool pickable = ray_pickable && is_visible_in_tree();
PhysicsServer3D::get_singleton()->soft_body_set_ray_pickable(physics_rid, pickable);
}
@@ -129,11 +127,9 @@ bool SoftBody3D::_set(const StringName &p_name, const Variant &p_value) {
String which = name.get_slicec('/', 0);
if ("pinned_points" == which) {
-
return _set_property_pinned_points_indices(p_value);
} else if ("attachments" == which) {
-
int idx = name.get_slicec('/', 1).to_int();
String what = name.get_slicec('/', 2);
@@ -161,7 +157,6 @@ bool SoftBody3D::_get(const StringName &p_name, Variant &r_ret) const {
return true;
} else if ("attachments" == which) {
-
int idx = name.get_slicec('/', 1).to_int();
String what = name.get_slicec('/', 2);
@@ -172,7 +167,6 @@ bool SoftBody3D::_get(const StringName &p_name, Variant &r_ret) const {
}
void SoftBody3D::_get_property_list(List<PropertyInfo> *p_list) const {
-
const int pinned_points_indices_size = pinned_points.size();
p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "pinned_points"));
@@ -185,7 +179,6 @@ void SoftBody3D::_get_property_list(List<PropertyInfo> *p_list) const {
}
bool SoftBody3D::_set_property_pinned_points_indices(const Array &p_indices) {
-
const int p_indices_size = p_indices.size();
{ // Remove the pined points on physics server that will be removed by resize
@@ -204,8 +197,9 @@ bool SoftBody3D::_set_property_pinned_points_indices(const Array &p_indices) {
for (int i = 0; i < p_indices_size; ++i) {
point_index = p_indices.get(i);
if (w[i].point_index != point_index) {
- if (-1 != w[i].point_index)
+ if (-1 != w[i].point_index) {
pin_point(w[i].point_index, false);
+ }
w[i].point_index = point_index;
pin_point(w[i].point_index, true);
}
@@ -264,23 +258,21 @@ void SoftBody3D::_changed_callback(Object *p_changed, const char *p_prop) {
void SoftBody3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
-
if (Engine::get_singleton()->is_editor_hint()) {
-
add_change_receptor(this);
}
- RID space = get_world()->get_space();
+ RID space = get_world_3d()->get_space();
PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, space);
prepare_physics_server();
} break;
case NOTIFICATION_READY: {
- if (!parent_collision_ignore.is_empty())
+ if (!parent_collision_ignore.is_empty()) {
add_collision_exception_with(get_node(parent_collision_ignore));
+ }
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
-
if (Engine::get_singleton()->is_editor_hint()) {
_reset_points_offsets();
return;
@@ -290,18 +282,16 @@ void SoftBody3D::_notification(int p_what) {
set_notify_transform(false);
// Required to be top level with Transform at center of world in order to modify RenderingServer only to support custom Transform
- set_as_toplevel(true);
+ set_as_top_level(true);
set_transform(Transform());
set_notify_transform(true);
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
-
_update_pickable();
} break;
case NOTIFICATION_EXIT_WORLD: {
-
PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, RID());
} break;
@@ -319,7 +309,6 @@ void SoftBody3D::_notification(int p_what) {
}
void SoftBody3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody3D::set_collision_mask);
ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody3D::get_collision_mask);
@@ -388,20 +377,21 @@ void SoftBody3D::_bind_methods() {
}
String SoftBody3D::get_configuration_warning() const {
-
String warning = MeshInstance3D::get_configuration_warning();
if (get_mesh().is_null()) {
- if (!warning.empty())
+ if (!warning.empty()) {
warning += "\n\n";
+ }
warning += TTR("This body will be ignored until you set a mesh.");
}
Transform t = get_transform();
if ((ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) {
- if (!warning.empty())
+ if (!warning.empty()) {
warning += "\n\n";
+ }
warning += TTR("Size changes to SoftBody3D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.");
}
@@ -410,8 +400,9 @@ String SoftBody3D::get_configuration_warning() const {
}
void SoftBody3D::_update_physics_server() {
- if (!simulation_started)
+ if (!simulation_started) {
return;
+ }
_update_cache_pin_points_datas();
// Submit bone attachment
@@ -425,16 +416,16 @@ void SoftBody3D::_update_physics_server() {
}
void SoftBody3D::_draw_soft_mesh() {
- if (get_mesh().is_null())
+ if (get_mesh().is_null()) {
return;
+ }
if (!rendering_server_handler.is_ready()) {
-
rendering_server_handler.prepare(get_mesh()->get_rid(), 0);
/// Necessary in order to render the mesh correctly (Soft body nodes are in global space)
simulation_started = true;
- call_deferred("set_as_toplevel", true);
+ call_deferred("set_as_top_level", true);
call_deferred("set_transform", Transform());
}
@@ -448,24 +439,21 @@ void SoftBody3D::_draw_soft_mesh() {
}
void SoftBody3D::prepare_physics_server() {
-
if (Engine::get_singleton()->is_editor_hint()) {
-
- if (get_mesh().is_valid())
+ if (get_mesh().is_valid()) {
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh());
- else
+ } else {
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, nullptr);
+ }
return;
}
if (get_mesh().is_valid()) {
-
become_mesh_owner();
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh());
RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh));
} else {
-
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, nullptr);
if (RS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh))) {
RS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh));
@@ -474,8 +462,9 @@ void SoftBody3D::prepare_physics_server() {
}
void SoftBody3D::become_mesh_owner() {
- if (mesh.is_null())
+ if (mesh.is_null()) {
return;
+ }
if (!mesh_owner) {
mesh_owner = true;
@@ -515,6 +504,7 @@ void SoftBody3D::set_collision_mask(uint32_t p_mask) {
uint32_t SoftBody3D::get_collision_mask() const {
return collision_mask;
}
+
void SoftBody3D::set_collision_layer(uint32_t p_layer) {
collision_layer = p_layer;
PhysicsServer3D::get_singleton()->soft_body_set_collision_layer(physics_rid, p_layer);
@@ -526,10 +516,11 @@ uint32_t SoftBody3D::get_collision_layer() const {
void SoftBody3D::set_collision_mask_bit(int p_bit, bool p_value) {
uint32_t mask = get_collision_mask();
- if (p_value)
+ if (p_value) {
mask |= 1 << p_bit;
- else
+ } else {
mask &= ~(1 << p_bit);
+ }
set_collision_mask(mask);
}
@@ -539,10 +530,11 @@ bool SoftBody3D::get_collision_mask_bit(int p_bit) const {
void SoftBody3D::set_collision_layer_bit(int p_bit, bool p_value) {
uint32_t layer = get_collision_layer();
- if (p_value)
+ if (p_value) {
layer |= 1 << p_bit;
- else
+ } else {
layer &= ~(1 << p_bit);
+ }
set_collision_layer(layer);
}
@@ -691,25 +683,16 @@ bool SoftBody3D::is_point_pinned(int p_point_index) const {
}
void SoftBody3D::set_ray_pickable(bool p_ray_pickable) {
-
ray_pickable = p_ray_pickable;
_update_pickable();
}
bool SoftBody3D::is_ray_pickable() const {
-
return ray_pickable;
}
SoftBody3D::SoftBody3D() :
- physics_rid(PhysicsServer3D::get_singleton()->soft_body_create()),
- mesh_owner(false),
- collision_mask(1),
- collision_layer(1),
- simulation_started(false),
- pinned_points_cache_dirty(true),
- ray_pickable(true) {
-
+ physics_rid(PhysicsServer3D::get_singleton()->soft_body_create()) {
PhysicsServer3D::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id());
}
@@ -730,14 +713,14 @@ void SoftBody3D::_make_cache_dirty() {
}
void SoftBody3D::_update_cache_pin_points_datas() {
- if (!pinned_points_cache_dirty)
+ if (!pinned_points_cache_dirty) {
return;
+ }
pinned_points_cache_dirty = false;
PinnedPoint *w = pinned_points.ptrw();
for (int i = pinned_points.size() - 1; 0 <= i; --i) {
-
if (!w[i].spatial_attachment_path.is_empty()) {
w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(w[i].spatial_attachment_path));
}
@@ -754,7 +737,6 @@ void SoftBody3D::_pin_point_on_physics_server(int p_point_index, bool pin) {
void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) {
SoftBody3D::PinnedPoint *pinned_point;
if (-1 == _get_pinned_point(p_point_index, pinned_point)) {
-
// Create new
PinnedPoint pp;
pp.point_index = p_point_index;
@@ -768,7 +750,6 @@ void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_
pinned_points.push_back(pp);
} else {
-
pinned_point->point_index = p_point_index;
pinned_point->spatial_attachment_path = p_spatial_attachment_path;
@@ -780,19 +761,20 @@ void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_
}
void SoftBody3D::_reset_points_offsets() {
-
- if (!Engine::get_singleton()->is_editor_hint())
+ if (!Engine::get_singleton()->is_editor_hint()) {
return;
+ }
const PinnedPoint *r = pinned_points.ptr();
PinnedPoint *w = pinned_points.ptrw();
for (int i = pinned_points.size() - 1; 0 <= i; --i) {
-
- if (!r[i].spatial_attachment)
+ if (!r[i].spatial_attachment) {
w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(r[i].spatial_attachment_path));
+ }
- if (!r[i].spatial_attachment)
+ if (!r[i].spatial_attachment) {
continue;
+ }
w[i].offset = (r[i].spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, r[i].point_index));
}
diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h
index 7dd5880985..c59a0b3aa3 100644
--- a/scene/3d/soft_body_3d.h
+++ b/scene/3d/soft_body_3d.h
@@ -36,7 +36,6 @@
class SoftBody3D;
class SoftBodyRenderingServerHandler {
-
friend class SoftBody3D;
RID mesh;
@@ -68,14 +67,14 @@ class SoftBody3D : public MeshInstance3D {
public:
struct PinnedPoint {
- int point_index;
+ int point_index = -1;
NodePath spatial_attachment_path;
- Node3D *spatial_attachment; // Cache
+ Node3D *spatial_attachment = nullptr; // Cache
Vector3 offset;
PinnedPoint();
PinnedPoint(const PinnedPoint &obj_tocopy);
- PinnedPoint operator=(const PinnedPoint &obj);
+ PinnedPoint &operator=(const PinnedPoint &obj);
};
private:
@@ -83,19 +82,19 @@ private:
RID physics_rid;
- bool mesh_owner;
- uint32_t collision_mask;
- uint32_t collision_layer;
+ bool mesh_owner = false;
+ uint32_t collision_mask = 1;
+ uint32_t collision_layer = 1;
NodePath parent_collision_ignore;
Vector<PinnedPoint> pinned_points;
- bool simulation_started;
- bool pinned_points_cache_dirty;
+ bool simulation_started = false;
+ bool pinned_points_cache_dirty = true;
Ref<ArrayMesh> debug_mesh_cache;
class MeshInstance3D *debug_mesh;
bool capture_input_on_drag;
- bool ray_pickable;
+ bool ray_pickable = true;
void _update_pickable();
@@ -108,12 +107,12 @@ protected:
bool _set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value);
bool _get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const;
- virtual void _changed_callback(Object *p_changed, const char *p_prop);
+ virtual void _changed_callback(Object *p_changed, const char *p_prop) override;
void _notification(int p_what);
static void _bind_methods();
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
protected:
void _update_physics_server();
diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp
index 0ffde7aa8f..287d760db0 100644
--- a/scene/3d/spring_arm_3d.cpp
+++ b/scene/3d/spring_arm_3d.cpp
@@ -29,18 +29,12 @@
/*************************************************************************/
#include "spring_arm_3d.h"
-#include "core/engine.h"
+
+#include "core/config/engine.h"
#include "scene/3d/collision_object_3d.h"
#include "scene/resources/sphere_shape_3d.h"
#include "servers/physics_server_3d.h"
-SpringArm3D::SpringArm3D() :
- spring_length(1),
- current_spring_length(0),
- keep_child_basis(false),
- mask(1),
- margin(0.01) {}
-
void SpringArm3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
@@ -60,7 +54,6 @@ void SpringArm3D::_notification(int p_what) {
}
void SpringArm3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("get_hit_length"), &SpringArm3D::get_hit_length);
ClassDB::bind_method(D_METHOD("set_length", "length"), &SpringArm3D::set_length);
@@ -90,8 +83,9 @@ float SpringArm3D::get_length() const {
}
void SpringArm3D::set_length(float p_length) {
- if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint()))
+ if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) {
update_gizmo();
+ }
spring_length = p_length;
}
@@ -147,7 +141,7 @@ void SpringArm3D::process_spring() {
if (shape.is_null()) {
motion = Vector3(cast_direction * (spring_length));
PhysicsDirectSpaceState3D::RayResult r;
- bool intersected = get_world()->get_direct_space_state()->intersect_ray(get_global_transform().origin, get_global_transform().origin + motion, r, excluded_objects, mask);
+ bool intersected = get_world_3d()->get_direct_space_state()->intersect_ray(get_global_transform().origin, get_global_transform().origin + motion, r, excluded_objects, mask);
if (intersected) {
float dist = get_global_transform().origin.distance_to(r.position);
dist -= margin;
@@ -155,7 +149,7 @@ void SpringArm3D::process_spring() {
}
} else {
motion = Vector3(cast_direction * spring_length);
- get_world()->get_direct_space_state()->cast_motion(shape->get_rid(), get_global_transform(), motion, 0, motion_delta, motion_delta_unsafe, excluded_objects, mask);
+ get_world_3d()->get_direct_space_state()->cast_motion(shape->get_rid(), get_global_transform(), motion, 0, motion_delta, motion_delta_unsafe, excluded_objects, mask);
}
current_spring_length = spring_length * motion_delta;
@@ -163,7 +157,6 @@ void SpringArm3D::process_spring() {
childs_transform.origin = get_global_transform().origin + cast_direction * (spring_length * motion_delta);
for (int i = get_child_count() - 1; 0 <= i; --i) {
-
Node3D *child = Object::cast_to<Node3D>(get_child(i));
if (child) {
childs_transform.basis = child->get_global_transform().basis;
diff --git a/scene/3d/spring_arm_3d.h b/scene/3d/spring_arm_3d.h
index cb8a00ecf9..7f6fe2f1a2 100644
--- a/scene/3d/spring_arm_3d.h
+++ b/scene/3d/spring_arm_3d.h
@@ -38,11 +38,11 @@ class SpringArm3D : public Node3D {
Ref<Shape3D> shape;
Set<RID> excluded_objects;
- float spring_length;
- float current_spring_length;
- bool keep_child_basis;
- uint32_t mask;
- float margin;
+ float spring_length = 1;
+ float current_spring_length = 0;
+ bool keep_child_basis = false;
+ uint32_t mask = 1;
+ float margin = 0.01;
protected:
void _notification(int p_what);
@@ -62,7 +62,7 @@ public:
void set_margin(float p_margin);
float get_margin();
- SpringArm3D();
+ SpringArm3D() {}
private:
void process_spring();
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 85e5ebc475..b6999beff4 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -34,14 +34,15 @@
#include "scene/scene_string_names.h"
Color SpriteBase3D::_get_color_accum() {
-
- if (!color_dirty)
+ if (!color_dirty) {
return color_accum;
+ }
- if (parent_sprite)
+ if (parent_sprite) {
color_accum = parent_sprite->_get_color_accum();
- else
+ } else {
color_accum = Color(1, 1, 1, 1);
+ }
color_accum.r *= modulate.r;
color_accum.g *= modulate.g;
@@ -52,25 +53,23 @@ Color SpriteBase3D::_get_color_accum() {
}
void SpriteBase3D::_propagate_color_changed() {
-
- if (color_dirty)
+ if (color_dirty) {
return;
+ }
color_dirty = true;
_queue_update();
for (List<SpriteBase3D *>::Element *E = children.front(); E; E = E->next()) {
-
E->get()->_propagate_color_changed();
}
}
void SpriteBase3D::_notification(int p_what) {
-
if (p_what == NOTIFICATION_ENTER_TREE) {
-
- if (!pending_update)
+ if (!pending_update) {
_im_update();
+ }
parent_sprite = Object::cast_to<SpriteBase3D>(get_parent());
if (parent_sprite) {
@@ -79,9 +78,7 @@ void SpriteBase3D::_notification(int p_what) {
}
if (p_what == NOTIFICATION_EXIT_TREE) {
-
if (parent_sprite) {
-
parent_sprite->children.erase(pI);
pI = nullptr;
parent_sprite = nullptr;
@@ -90,100 +87,89 @@ void SpriteBase3D::_notification(int p_what) {
}
void SpriteBase3D::set_centered(bool p_center) {
-
centered = p_center;
_queue_update();
}
bool SpriteBase3D::is_centered() const {
-
return centered;
}
void SpriteBase3D::set_offset(const Point2 &p_offset) {
-
offset = p_offset;
_queue_update();
}
-Point2 SpriteBase3D::get_offset() const {
+Point2 SpriteBase3D::get_offset() const {
return offset;
}
void SpriteBase3D::set_flip_h(bool p_flip) {
-
hflip = p_flip;
_queue_update();
}
-bool SpriteBase3D::is_flipped_h() const {
+bool SpriteBase3D::is_flipped_h() const {
return hflip;
}
void SpriteBase3D::set_flip_v(bool p_flip) {
-
vflip = p_flip;
_queue_update();
}
-bool SpriteBase3D::is_flipped_v() const {
+bool SpriteBase3D::is_flipped_v() const {
return vflip;
}
void SpriteBase3D::set_modulate(const Color &p_color) {
-
modulate = p_color;
_propagate_color_changed();
_queue_update();
}
Color SpriteBase3D::get_modulate() const {
-
return modulate;
}
void SpriteBase3D::set_pixel_size(float p_amount) {
-
pixel_size = p_amount;
_queue_update();
}
-float SpriteBase3D::get_pixel_size() const {
+float SpriteBase3D::get_pixel_size() const {
return pixel_size;
}
void SpriteBase3D::set_opacity(float p_amount) {
-
opacity = p_amount;
_queue_update();
}
-float SpriteBase3D::get_opacity() const {
+float SpriteBase3D::get_opacity() const {
return opacity;
}
void SpriteBase3D::set_axis(Vector3::Axis p_axis) {
-
ERR_FAIL_INDEX(p_axis, 3);
axis = p_axis;
_queue_update();
}
-Vector3::Axis SpriteBase3D::get_axis() const {
+Vector3::Axis SpriteBase3D::get_axis() const {
return axis;
}
void SpriteBase3D::_im_update() {
-
_draw();
pending_update = false;
}
void SpriteBase3D::_queue_update() {
-
- if (pending_update)
+ if (pending_update) {
return;
+ }
triangle_mesh.unref();
update_gizmo();
@@ -193,17 +179,17 @@ void SpriteBase3D::_queue_update() {
}
AABB SpriteBase3D::get_aabb() const {
-
return aabb;
}
-Vector<Face3> SpriteBase3D::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> SpriteBase3D::get_faces(uint32_t p_usage_flags) const {
return Vector<Face3>();
}
Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
- if (triangle_mesh.is_valid())
+ if (triangle_mesh.is_valid()) {
return triangle_mesh;
+ }
Vector<Vector3> faces;
faces.resize(6);
@@ -211,13 +197,13 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
Rect2 final_rect = get_item_rect();
- if (final_rect.size.x == 0 || final_rect.size.y == 0)
+ if (final_rect.size.x == 0 || final_rect.size.y == 0) {
return Ref<TriangleMesh>();
+ }
float pixel_size = get_pixel_size();
Vector2 vertices[4] = {
-
(final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size,
(final_rect.position + final_rect.size) * pixel_size,
(final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size,
@@ -260,7 +246,6 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
}
void SpriteBase3D::set_draw_flag(DrawFlags p_flag, bool p_enable) {
-
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
flags[p_flag] = p_enable;
_queue_update();
@@ -272,31 +257,26 @@ bool SpriteBase3D::get_draw_flag(DrawFlags p_flag) const {
}
void SpriteBase3D::set_alpha_cut_mode(AlphaCutMode p_mode) {
-
ERR_FAIL_INDEX(p_mode, 3);
alpha_cut = p_mode;
_queue_update();
}
SpriteBase3D::AlphaCutMode SpriteBase3D::get_alpha_cut_mode() const {
-
return alpha_cut;
}
void SpriteBase3D::set_billboard_mode(StandardMaterial3D::BillboardMode p_mode) {
-
ERR_FAIL_INDEX(p_mode, 3);
billboard_mode = p_mode;
_queue_update();
}
StandardMaterial3D::BillboardMode SpriteBase3D::get_billboard_mode() const {
-
return billboard_mode;
}
void SpriteBase3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_centered", "centered"), &SpriteBase3D::set_centered);
ClassDB::bind_method(D_METHOD("is_centered"), &SpriteBase3D::is_centered);
@@ -359,7 +339,6 @@ void SpriteBase3D::_bind_methods() {
}
SpriteBase3D::SpriteBase3D() {
-
color_dirty = true;
centered = true;
hflip = false;
@@ -367,8 +346,9 @@ SpriteBase3D::SpriteBase3D() {
parent_sprite = nullptr;
pI = nullptr;
- for (int i = 0; i < FLAG_MAX; i++)
+ for (int i = 0; i < FLAG_MAX; i++) {
flags[i] = i == FLAG_TRANSPARENT || i == FLAG_DOUBLE_SIDED;
+ }
alpha_cut = ALPHA_CUT_DISABLED;
billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED;
@@ -382,46 +362,50 @@ SpriteBase3D::SpriteBase3D() {
}
SpriteBase3D::~SpriteBase3D() {
-
RenderingServer::get_singleton()->free(immediate);
}
///////////////////////////////////////////
void Sprite3D::_draw() {
-
RID immediate = get_immediate();
RS::get_singleton()->immediate_clear(immediate);
- if (!texture.is_valid())
+ if (!texture.is_valid()) {
return;
+ }
Vector2 tsize = texture->get_size();
- if (tsize.x == 0 || tsize.y == 0)
+ if (tsize.x == 0 || tsize.y == 0) {
return;
+ }
Rect2 base_rect;
- if (region)
+ if (region) {
base_rect = region_rect;
- else
+ } else {
base_rect = Rect2(0, 0, texture->get_width(), texture->get_height());
+ }
Size2 frame_size = base_rect.size / Size2(hframes, vframes);
Point2 frame_offset = Point2(frame % hframes, frame / hframes);
frame_offset *= frame_size;
Point2 dest_offset = get_offset();
- if (is_centered())
+ if (is_centered()) {
dest_offset -= frame_size / 2;
+ }
Rect2 src_rect(base_rect.position + frame_offset, frame_size);
Rect2 final_dst_rect(dest_offset, frame_size);
Rect2 final_rect;
Rect2 final_src_rect;
- if (!texture->get_rect_region(final_dst_rect, src_rect, final_rect, final_src_rect))
+ if (!texture->get_rect_region(final_dst_rect, src_rect, final_rect, final_src_rect)) {
return;
+ }
- if (final_rect.size.x == 0 || final_rect.size.y == 0)
+ if (final_rect.size.x == 0 || final_rect.size.y == 0) {
return;
+ }
Color color = _get_color_accum();
color.a *= get_opacity();
@@ -429,7 +413,6 @@ void Sprite3D::_draw() {
float pixel_size = get_pixel_size();
Vector2 vertices[4] = {
-
(final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size,
(final_rect.position + final_rect.size) * pixel_size,
(final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size,
@@ -458,7 +441,6 @@ void Sprite3D::_draw() {
SWAP(uvs[2], uvs[3]);
}
if (is_flipped_v()) {
-
SWAP(uvs[0], uvs[3]);
SWAP(uvs[1], uvs[2]);
}
@@ -499,7 +481,6 @@ void Sprite3D::_draw() {
AABB aabb;
for (int i = 0; i < 6; i++) {
-
static const int index[6] = { 0, 1, 2, 0, 2, 3 };
RS::get_singleton()->immediate_normal(immediate, normal);
@@ -527,9 +508,9 @@ void Sprite3D::_texture_changed() {
}
void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) {
-
- if (p_texture == texture)
+ if (p_texture == texture) {
return;
+ }
if (texture.is_valid()) {
texture->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed));
}
@@ -541,26 +522,23 @@ void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) {
}
Ref<Texture2D> Sprite3D::get_texture() const {
-
return texture;
}
void Sprite3D::set_region(bool p_region) {
-
- if (p_region == region)
+ if (p_region == region) {
return;
+ }
region = p_region;
_queue_update();
}
bool Sprite3D::is_region() const {
-
return region;
}
void Sprite3D::set_region_rect(const Rect2 &p_region_rect) {
-
bool changed = region_rect != p_region_rect;
region_rect = p_region_rect;
if (region && changed) {
@@ -569,12 +547,10 @@ void Sprite3D::set_region_rect(const Rect2 &p_region_rect) {
}
Rect2 Sprite3D::get_region_rect() const {
-
return region_rect;
}
void Sprite3D::set_frame(int p_frame) {
-
ERR_FAIL_INDEX(p_frame, int64_t(vframes) * hframes);
frame = p_frame;
@@ -587,7 +563,6 @@ void Sprite3D::set_frame(int p_frame) {
}
int Sprite3D::get_frame() const {
-
return frame;
}
@@ -603,33 +578,31 @@ Vector2 Sprite3D::get_frame_coords() const {
}
void Sprite3D::set_vframes(int p_amount) {
-
ERR_FAIL_COND(p_amount < 1);
vframes = p_amount;
_queue_update();
_change_notify();
}
-int Sprite3D::get_vframes() const {
+int Sprite3D::get_vframes() const {
return vframes;
}
void Sprite3D::set_hframes(int p_amount) {
-
ERR_FAIL_COND(p_amount < 1);
hframes = p_amount;
_queue_update();
_change_notify();
}
-int Sprite3D::get_hframes() const {
+int Sprite3D::get_hframes() const {
return hframes;
}
Rect2 Sprite3D::get_item_rect() const {
-
- if (texture.is_null())
+ if (texture.is_null()) {
return Rect2(0, 0, 1, 1);
+ }
/*
if (texture.is_null())
return CanvasItem::get_item_rect();
@@ -638,7 +611,6 @@ Rect2 Sprite3D::get_item_rect() const {
Size2i s;
if (region) {
-
s = region_rect.size;
} else {
s = texture->get_size();
@@ -646,17 +618,18 @@ Rect2 Sprite3D::get_item_rect() const {
}
Point2 ofs = get_offset();
- if (is_centered())
+ if (is_centered()) {
ofs -= s / 2;
+ }
- if (s == Size2(0, 0))
+ if (s == Size2(0, 0)) {
s = Size2(1, 1);
+ }
return Rect2(ofs, s);
}
void Sprite3D::_validate_property(PropertyInfo &property) const {
-
if (property.name == "frame") {
property.hint = PROPERTY_HINT_RANGE;
property.hint_string = "0," + itos(vframes * hframes - 1) + ",1";
@@ -669,7 +642,6 @@ void Sprite3D::_validate_property(PropertyInfo &property) const {
}
void Sprite3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite3D::set_texture);
ClassDB::bind_method(D_METHOD("get_texture"), &Sprite3D::get_texture);
@@ -693,8 +665,8 @@ void Sprite3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
ADD_GROUP("Animation", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_GROUP("Region", "region_");
@@ -705,7 +677,6 @@ void Sprite3D::_bind_methods() {
}
Sprite3D::Sprite3D() {
-
region = false;
frame = 0;
vframes = 1;
@@ -715,7 +686,6 @@ Sprite3D::Sprite3D() {
////////////////////////////////////////
void AnimatedSprite3D::_draw() {
-
RID immediate = get_immediate();
RS::get_singleton()->immediate_clear(immediate);
@@ -732,11 +702,13 @@ void AnimatedSprite3D::_draw() {
}
Ref<Texture2D> texture = frames->get_frame(animation, frame);
- if (!texture.is_valid())
+ if (!texture.is_valid()) {
return; //no texuture no life
+ }
Vector2 tsize = texture->get_size();
- if (tsize.x == 0 || tsize.y == 0)
+ if (tsize.x == 0 || tsize.y == 0) {
return;
+ }
Size2i s = tsize;
Rect2 src_rect;
@@ -744,18 +716,21 @@ void AnimatedSprite3D::_draw() {
src_rect.size = s;
Point2 ofs = get_offset();
- if (is_centered())
+ if (is_centered()) {
ofs -= s / 2;
+ }
Rect2 dst_rect(ofs, s);
Rect2 final_rect;
Rect2 final_src_rect;
- if (!texture->get_rect_region(dst_rect, src_rect, final_rect, final_src_rect))
+ if (!texture->get_rect_region(dst_rect, src_rect, final_rect, final_src_rect)) {
return;
+ }
- if (final_rect.size.x == 0 || final_rect.size.y == 0)
+ if (final_rect.size.x == 0 || final_rect.size.y == 0) {
return;
+ }
Color color = _get_color_accum();
color.a *= get_opacity();
@@ -763,7 +738,6 @@ void AnimatedSprite3D::_draw() {
float pixel_size = get_pixel_size();
Vector2 vertices[4] = {
-
(final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size,
(final_rect.position + final_rect.size) * pixel_size,
(final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size,
@@ -792,7 +766,6 @@ void AnimatedSprite3D::_draw() {
SWAP(uvs[2], uvs[3]);
}
if (is_flipped_v()) {
-
SWAP(uvs[0], uvs[3]);
SWAP(uvs[1], uvs[2]);
}
@@ -834,7 +807,6 @@ void AnimatedSprite3D::_draw() {
AABB aabb;
for (int i = 0; i < 6; i++) {
-
static const int indices[6] = {
0, 1, 2,
0, 2, 3
@@ -861,11 +833,10 @@ void AnimatedSprite3D::_draw() {
}
void AnimatedSprite3D::_validate_property(PropertyInfo &property) const {
-
- if (!frames.is_valid())
+ if (!frames.is_valid()) {
return;
+ }
if (property.name == "animation") {
-
property.hint = PROPERTY_HINT_ENUM;
List<StringName> names;
frames->get_animation_list(&names);
@@ -903,27 +874,27 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &property) const {
}
void AnimatedSprite3D::_notification(int p_what) {
-
switch (p_what) {
case NOTIFICATION_INTERNAL_PROCESS: {
-
- if (frames.is_null())
+ if (frames.is_null()) {
return;
- if (!frames->has_animation(animation))
+ }
+ if (!frames->has_animation(animation)) {
return;
- if (frame < 0)
+ }
+ if (frame < 0) {
return;
+ }
float speed = frames->get_animation_speed(animation);
- if (speed == 0)
+ if (speed == 0) {
return; //do nothing
+ }
float remaining = get_process_delta_time();
while (remaining) {
-
if (timeout <= 0) {
-
timeout = 1.0 / speed;
int fc = frames->get_frame_count(animation);
@@ -950,12 +921,13 @@ void AnimatedSprite3D::_notification(int p_what) {
}
void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
-
- if (frames.is_valid())
+ if (frames.is_valid()) {
frames->disconnect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed));
+ }
frames = p_frames;
- if (frames.is_valid())
+ if (frames.is_valid()) {
frames->connect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed));
+ }
if (!frames.is_valid()) {
frame = 0;
@@ -970,27 +942,28 @@ void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
}
Ref<SpriteFrames> AnimatedSprite3D::get_sprite_frames() const {
-
return frames;
}
void AnimatedSprite3D::set_frame(int p_frame) {
-
if (!frames.is_valid()) {
return;
}
if (frames->has_animation(animation)) {
int limit = frames->get_frame_count(animation);
- if (p_frame >= limit)
+ if (p_frame >= limit) {
p_frame = limit - 1;
+ }
}
- if (p_frame < 0)
+ if (p_frame < 0) {
p_frame = 0;
+ }
- if (frame == p_frame)
+ if (frame == p_frame) {
return;
+ }
frame = p_frame;
_reset_timeout();
@@ -998,36 +971,38 @@ void AnimatedSprite3D::set_frame(int p_frame) {
_change_notify("frame");
emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
-int AnimatedSprite3D::get_frame() const {
+int AnimatedSprite3D::get_frame() const {
return frame;
}
Rect2 AnimatedSprite3D::get_item_rect() const {
-
if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) {
return Rect2(0, 0, 1, 1);
}
Ref<Texture2D> t;
- if (animation)
+ if (animation) {
t = frames->get_frame(animation, frame);
- if (t.is_null())
+ }
+ if (t.is_null()) {
return Rect2(0, 0, 1, 1);
+ }
Size2i s = t->get_size();
Point2 ofs = get_offset();
- if (centered)
+ if (centered) {
ofs -= s / 2;
+ }
- if (s == Size2(0, 0))
+ if (s == Size2(0, 0)) {
s = Size2(1, 1);
+ }
return Rect2(ofs, s);
}
void AnimatedSprite3D::_res_changed() {
-
set_frame(frame);
_change_notify("frame");
_change_notify("animation");
@@ -1035,40 +1010,37 @@ void AnimatedSprite3D::_res_changed() {
}
void AnimatedSprite3D::_set_playing(bool p_playing) {
-
- if (playing == p_playing)
+ if (playing == p_playing) {
return;
+ }
playing = p_playing;
_reset_timeout();
set_process_internal(playing);
}
bool AnimatedSprite3D::_is_playing() const {
-
return playing;
}
void AnimatedSprite3D::play(const StringName &p_animation) {
-
- if (p_animation)
+ if (p_animation) {
set_animation(p_animation);
+ }
_set_playing(true);
}
void AnimatedSprite3D::stop() {
-
_set_playing(false);
}
bool AnimatedSprite3D::is_playing() const {
-
return is_processing();
}
void AnimatedSprite3D::_reset_timeout() {
-
- if (!playing)
+ if (!playing) {
return;
+ }
if (frames.is_valid() && frames->has_animation(animation)) {
float speed = frames->get_animation_speed(animation);
@@ -1083,9 +1055,9 @@ void AnimatedSprite3D::_reset_timeout() {
}
void AnimatedSprite3D::set_animation(const StringName &p_animation) {
-
- if (animation == p_animation)
+ if (animation == p_animation) {
return;
+ }
animation = p_animation;
_reset_timeout();
@@ -1093,22 +1065,25 @@ void AnimatedSprite3D::set_animation(const StringName &p_animation) {
_change_notify();
_queue_update();
}
-StringName AnimatedSprite3D::get_animation() const {
+StringName AnimatedSprite3D::get_animation() const {
return animation;
}
String AnimatedSprite3D::get_configuration_warning() const {
+ String warning = SpriteBase3D::get_configuration_warning();
if (frames.is_null()) {
- return TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames.");
}
- return String();
+ return warning;
}
void AnimatedSprite3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_sprite_frames", "sprite_frames"), &AnimatedSprite3D::set_sprite_frames);
ClassDB::bind_method(D_METHOD("get_sprite_frames"), &AnimatedSprite3D::get_sprite_frames);
@@ -1134,7 +1109,6 @@ void AnimatedSprite3D::_bind_methods() {
}
AnimatedSprite3D::AnimatedSprite3D() {
-
frame = 0;
playing = false;
animation = "default";
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index 64bef41fd8..cb8467aac6 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -35,7 +35,6 @@
#include "scene/3d/visual_instance_3d.h"
class SpriteBase3D : public GeometryInstance3D {
-
GDCLASS(SpriteBase3D, GeometryInstance3D);
mutable Ref<TriangleMesh> triangle_mesh; //cached
@@ -136,8 +135,8 @@ public:
virtual Rect2 get_item_rect() const = 0;
- virtual AABB get_aabb() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual AABB get_aabb() const override;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
Ref<TriangleMesh> generate_triangle_mesh() const;
SpriteBase3D();
@@ -145,7 +144,6 @@ public:
};
class Sprite3D : public SpriteBase3D {
-
GDCLASS(Sprite3D, SpriteBase3D);
Ref<Texture2D> texture;
@@ -160,10 +158,10 @@ class Sprite3D : public SpriteBase3D {
void _texture_changed();
protected:
- virtual void _draw();
+ virtual void _draw() override;
static void _bind_methods();
- virtual void _validate_property(PropertyInfo &property) const;
+ virtual void _validate_property(PropertyInfo &property) const override;
public:
void set_texture(const Ref<Texture2D> &p_texture);
@@ -187,14 +185,13 @@ public:
void set_hframes(int p_amount);
int get_hframes() const;
- virtual Rect2 get_item_rect() const;
+ virtual Rect2 get_item_rect() const override;
Sprite3D();
//~Sprite3D();
};
class AnimatedSprite3D : public SpriteBase3D {
-
GDCLASS(AnimatedSprite3D, SpriteBase3D);
Ref<SpriteFrames> frames;
@@ -218,10 +215,10 @@ class AnimatedSprite3D : public SpriteBase3D {
bool _is_playing() const;
protected:
- virtual void _draw();
+ virtual void _draw() override;
static void _bind_methods();
void _notification(int p_what);
- virtual void _validate_property(PropertyInfo &property) const;
+ virtual void _validate_property(PropertyInfo &property) const override;
public:
void set_sprite_frames(const Ref<SpriteFrames> &p_frames);
@@ -237,9 +234,9 @@ public:
void set_frame(int p_frame);
int get_frame() const;
- virtual Rect2 get_item_rect() const;
+ virtual Rect2 get_item_rect() const override;
- virtual String get_configuration_warning() const;
+ virtual String get_configuration_warning() const override;
AnimatedSprite3D();
};
diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp
index 5c2fa59a21..e27307e75f 100644
--- a/scene/3d/vehicle_body_3d.cpp
+++ b/scene/3d/vehicle_body_3d.cpp
@@ -44,7 +44,7 @@ public:
real_t getDiagonal() const { return m_Adiag; }
- btVehicleJacobianEntry(){};
+ btVehicleJacobianEntry() {}
//constraint between two different rigidbodies
btVehicleJacobianEntry(
const Basis &world2A,
@@ -79,12 +79,11 @@ public:
};
void VehicleWheel3D::_notification(int p_what) {
-
if (p_what == NOTIFICATION_ENTER_TREE) {
-
VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent());
- if (!cb)
+ if (!cb) {
return;
+ }
body = cb;
local_xform = get_transform();
cb->wheels.push_back(this);
@@ -94,25 +93,29 @@ void VehicleWheel3D::_notification(int p_what) {
m_wheelAxleCS = get_transform().basis.get_axis(Vector3::AXIS_X).normalized();
}
if (p_what == NOTIFICATION_EXIT_TREE) {
-
VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent());
- if (!cb)
+ if (!cb) {
return;
+ }
cb->wheels.erase(this);
body = nullptr;
}
}
String VehicleWheel3D::get_configuration_warning() const {
+ String warning = Node3D::get_configuration_warning();
+
if (!Object::cast_to<VehicleBody3D>(get_parent())) {
- return TTR("VehicleWheel3D serves to provide a wheel system to a VehicleBody3D. Please use it as a child of a VehicleBody3D.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("VehicleWheel3D serves to provide a wheel system to a VehicleBody3D. Please use it as a child of a VehicleBody3D.");
}
- return String();
+ return warning;
}
void VehicleWheel3D::_update(PhysicsDirectBodyState3D *s) {
-
if (m_raycastInfo.m_isInContact)
{
@@ -145,77 +148,68 @@ void VehicleWheel3D::_update(PhysicsDirectBodyState3D *s) {
}
void VehicleWheel3D::set_radius(float p_radius) {
-
m_wheelRadius = p_radius;
update_gizmo();
}
float VehicleWheel3D::get_radius() const {
-
return m_wheelRadius;
}
void VehicleWheel3D::set_suspension_rest_length(float p_length) {
-
m_suspensionRestLength = p_length;
update_gizmo();
}
-float VehicleWheel3D::get_suspension_rest_length() const {
+float VehicleWheel3D::get_suspension_rest_length() const {
return m_suspensionRestLength;
}
void VehicleWheel3D::set_suspension_travel(float p_length) {
-
m_maxSuspensionTravelCm = p_length / 0.01;
}
-float VehicleWheel3D::get_suspension_travel() const {
+float VehicleWheel3D::get_suspension_travel() const {
return m_maxSuspensionTravelCm * 0.01;
}
void VehicleWheel3D::set_suspension_stiffness(float p_value) {
-
m_suspensionStiffness = p_value;
}
-float VehicleWheel3D::get_suspension_stiffness() const {
+float VehicleWheel3D::get_suspension_stiffness() const {
return m_suspensionStiffness;
}
void VehicleWheel3D::set_suspension_max_force(float p_value) {
-
m_maxSuspensionForce = p_value;
}
-float VehicleWheel3D::get_suspension_max_force() const {
+float VehicleWheel3D::get_suspension_max_force() const {
return m_maxSuspensionForce;
}
void VehicleWheel3D::set_damping_compression(float p_value) {
-
m_wheelsDampingCompression = p_value;
}
-float VehicleWheel3D::get_damping_compression() const {
+float VehicleWheel3D::get_damping_compression() const {
return m_wheelsDampingCompression;
}
void VehicleWheel3D::set_damping_relaxation(float p_value) {
-
m_wheelsDampingRelaxation = p_value;
}
-float VehicleWheel3D::get_damping_relaxation() const {
+float VehicleWheel3D::get_damping_relaxation() const {
return m_wheelsDampingRelaxation;
}
void VehicleWheel3D::set_friction_slip(float p_value) {
-
m_frictionSlip = p_value;
}
-float VehicleWheel3D::get_friction_slip() const {
+float VehicleWheel3D::get_friction_slip() const {
return m_frictionSlip;
}
@@ -232,7 +226,6 @@ bool VehicleWheel3D::is_in_contact() const {
}
void VehicleWheel3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_radius", "length"), &VehicleWheel3D::set_radius);
ClassDB::bind_method(D_METHOD("get_radius"), &VehicleWheel3D::get_radius);
@@ -303,65 +296,54 @@ void VehicleWheel3D::_bind_methods() {
}
void VehicleWheel3D::set_engine_force(float p_engine_force) {
-
m_engineForce = p_engine_force;
}
float VehicleWheel3D::get_engine_force() const {
-
return m_engineForce;
}
void VehicleWheel3D::set_brake(float p_brake) {
-
m_brake = p_brake;
}
-float VehicleWheel3D::get_brake() const {
+float VehicleWheel3D::get_brake() const {
return m_brake;
}
void VehicleWheel3D::set_steering(float p_steering) {
-
m_steering = p_steering;
}
-float VehicleWheel3D::get_steering() const {
+float VehicleWheel3D::get_steering() const {
return m_steering;
}
void VehicleWheel3D::set_use_as_traction(bool p_enable) {
-
engine_traction = p_enable;
}
bool VehicleWheel3D::is_used_as_traction() const {
-
return engine_traction;
}
void VehicleWheel3D::set_use_as_steering(bool p_enabled) {
-
steers = p_enabled;
}
bool VehicleWheel3D::is_used_as_steering() const {
-
return steers;
}
float VehicleWheel3D::get_skidinfo() const {
-
return m_skidInfo;
}
float VehicleWheel3D::get_rpm() const {
-
return m_rpm;
}
VehicleWheel3D::VehicleWheel3D() {
-
steers = false;
engine_traction = false;
m_steering = real_t(0.);
@@ -389,7 +371,6 @@ VehicleWheel3D::VehicleWheel3D() {
}
void VehicleBody3D::_update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirectBodyState3D *s) {
-
wheel.m_raycastInfo.m_isInContact = false;
Transform chassisTrans = s->get_transform();
@@ -406,7 +387,6 @@ void VehicleBody3D::_update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirect
}
void VehicleBody3D::_update_wheel(int p_idx, PhysicsDirectBodyState3D *s) {
-
VehicleWheel3D &wheel = *wheels[p_idx];
_update_wheel_transform(wheel, s);
@@ -431,7 +411,6 @@ void VehicleBody3D::_update_wheel(int p_idx, PhysicsDirectBodyState3D *s) {
}
real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState3D *s) {
-
VehicleWheel3D &wheel = *wheels[p_idx];
_update_wheel_transform(wheel, s);
@@ -462,8 +441,9 @@ real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState3D *s) {
wheel.m_raycastInfo.m_contactNormalWS = rr.normal;
wheel.m_raycastInfo.m_isInContact = true;
- if (rr.collider)
+ if (rr.collider) {
wheel.m_raycastInfo.m_groundObject = Object::cast_to<PhysicsBody3D>(rr.collider);
+ }
real_t hitDistance = param * raylen;
wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelRadius;
@@ -514,7 +494,6 @@ real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState3D *s) {
}
void VehicleBody3D::_update_suspension(PhysicsDirectBodyState3D *s) {
-
real_t chassisMass = mass;
for (int w_it = 0; w_it < wheels.size(); w_it++) {
@@ -560,7 +539,6 @@ void VehicleBody3D::_update_suspension(PhysicsDirectBodyState3D *s) {
//bilateral constraint between two dynamic objects
void VehicleBody3D::_resolve_single_bilateral(PhysicsDirectBodyState3D *s, const Vector3 &pos1,
PhysicsBody3D *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence) {
-
real_t normalLenSqr = normal.length_squared();
//ERR_FAIL_COND( normalLenSqr < real_t(1.1));
@@ -571,15 +549,17 @@ void VehicleBody3D::_resolve_single_bilateral(PhysicsDirectBodyState3D *s, const
Vector3 rel_pos1 = pos1 - s->get_transform().origin;
Vector3 rel_pos2;
- if (body2)
+ if (body2) {
rel_pos2 = pos2 - body2->get_global_transform().origin;
+ }
//this jacobian entry could be re-used for all iterations
Vector3 vel1 = s->get_linear_velocity() + (s->get_angular_velocity()).cross(rel_pos1); // * mPos);
Vector3 vel2;
- if (body2)
+ if (body2) {
vel2 = body2->get_linear_velocity() + body2->get_angular_velocity().cross(rel_pos2);
+ }
Vector3 vel = vel1 - vel2;
@@ -654,7 +634,6 @@ VehicleBody3D::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDir
/* TODO: Why is this code unused?
if (body1) {
-
Vector3 r0 = frictionPosWorld - body1->get_global_transform().origin;
Vector3 c0 = (r0).cross(frictionDirectionWorld);
Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0);
@@ -668,15 +647,15 @@ VehicleBody3D::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDir
}
real_t VehicleBody3D::_calc_rolling_friction(btVehicleWheelContactPoint &contactPoint) {
-
real_t j1 = 0.f;
const Vector3 &contactPosWorld = contactPoint.m_frictionPositionWorld;
Vector3 rel_pos1 = contactPosWorld - contactPoint.m_s->get_transform().origin;
Vector3 rel_pos2;
- if (contactPoint.m_body1)
+ if (contactPoint.m_body1) {
rel_pos2 = contactPosWorld - contactPoint.m_body1->get_global_transform().origin;
+ }
real_t maxImpulse = contactPoint.m_maxImpulse;
@@ -699,11 +678,11 @@ real_t VehicleBody3D::_calc_rolling_friction(btVehicleWheelContactPoint &contact
static const real_t sideFrictionStiffness2 = real_t(1.0);
void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) {
-
//calculate the impulse, so that the wheels don't move sidewards
int numWheel = wheels.size();
- if (!numWheel)
+ if (!numWheel) {
return;
+ }
m_forwardWS.resize(numWheel);
m_axle.resize(numWheel);
@@ -717,13 +696,10 @@ void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) {
}
{
-
for (int i = 0; i < wheels.size(); i++) {
-
VehicleWheel3D &wheelInfo = *wheels[i];
if (wheelInfo.m_raycastInfo.m_isInContact) {
-
//const btTransform& wheelTrans = getWheelTransformWS( i );
Basis wheelBasis0 = wheelInfo.m_worldTransform.basis; //get_global_transform().basis;
@@ -822,7 +798,7 @@ void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) {
s->get_transform().origin;
if (m_forwardImpulse[wheel] != real_t(0.)) {
- s->apply_impulse(rel_pos, m_forwardWS[wheel] * (m_forwardImpulse[wheel]));
+ s->apply_impulse(m_forwardWS[wheel] * (m_forwardImpulse[wheel]), rel_pos);
}
if (m_sideImpulse[wheel] != real_t(0.)) {
PhysicsBody3D *groundObject = wheelInfo.m_raycastInfo.m_groundObject;
@@ -840,7 +816,7 @@ void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) {
#else
rel_pos[1] *= wheelInfo.m_rollInfluence; //?
#endif
- s->apply_impulse(rel_pos, sideImp);
+ s->apply_impulse(sideImp, rel_pos);
//apply friction impulse on the ground
//todo
@@ -851,7 +827,6 @@ void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) {
}
void VehicleBody3D::_direct_state_changed(Object *p_state) {
-
RigidBody3D::_direct_state_changed(p_state);
state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
@@ -859,12 +834,10 @@ void VehicleBody3D::_direct_state_changed(Object *p_state) {
float step = state->get_step();
for (int i = 0; i < wheels.size(); i++) {
-
_update_wheel(i, state);
}
for (int i = 0; i < wheels.size(); i++) {
-
_ray_cast(i, state);
wheels[i]->set_transform(state->get_transform().inverse() * wheels[i]->m_worldTransform);
}
@@ -872,7 +845,6 @@ void VehicleBody3D::_direct_state_changed(Object *p_state) {
_update_suspension(state);
for (int i = 0; i < wheels.size(); i++) {
-
//apply suspension force
VehicleWheel3D &wheel = *wheels[i];
@@ -882,10 +854,9 @@ void VehicleBody3D::_direct_state_changed(Object *p_state) {
suspensionForce = wheel.m_maxSuspensionForce;
}
Vector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
- Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS - state->get_transform().origin;
+ Vector3 relative_position = wheel.m_raycastInfo.m_contactPointWS - state->get_transform().origin;
- state->apply_impulse(relpos, impulse);
- //getRigidBody()->applyImpulse(impulse, relpos);
+ state->apply_impulse(impulse, relative_position);
}
_update_friction(state);
@@ -921,49 +892,46 @@ void VehicleBody3D::_direct_state_changed(Object *p_state) {
}
void VehicleBody3D::set_engine_force(float p_engine_force) {
-
engine_force = p_engine_force;
for (int i = 0; i < wheels.size(); i++) {
VehicleWheel3D &wheelInfo = *wheels[i];
- if (wheelInfo.engine_traction)
+ if (wheelInfo.engine_traction) {
wheelInfo.m_engineForce = p_engine_force;
+ }
}
}
float VehicleBody3D::get_engine_force() const {
-
return engine_force;
}
void VehicleBody3D::set_brake(float p_brake) {
-
brake = p_brake;
for (int i = 0; i < wheels.size(); i++) {
VehicleWheel3D &wheelInfo = *wheels[i];
wheelInfo.m_brake = p_brake;
}
}
-float VehicleBody3D::get_brake() const {
+float VehicleBody3D::get_brake() const {
return brake;
}
void VehicleBody3D::set_steering(float p_steering) {
-
m_steeringValue = p_steering;
for (int i = 0; i < wheels.size(); i++) {
VehicleWheel3D &wheelInfo = *wheels[i];
- if (wheelInfo.steers)
+ if (wheelInfo.steers) {
wheelInfo.m_steering = p_steering;
+ }
}
}
-float VehicleBody3D::get_steering() const {
+float VehicleBody3D::get_steering() const {
return m_steeringValue;
}
void VehicleBody3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_engine_force", "engine_force"), &VehicleBody3D::set_engine_force);
ClassDB::bind_method(D_METHOD("get_engine_force"), &VehicleBody3D::get_engine_force);
@@ -980,7 +948,6 @@ void VehicleBody3D::_bind_methods() {
}
VehicleBody3D::VehicleBody3D() {
-
m_pitchControl = 0;
m_currentVehicleSpeedKmHour = real_t(0.);
m_steeringValue = real_t(0.);
diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h
index d5e896263d..0b4b3a4440 100644
--- a/scene/3d/vehicle_body_3d.h
+++ b/scene/3d/vehicle_body_3d.h
@@ -36,7 +36,6 @@
class VehicleBody3D;
class VehicleWheel3D : public Node3D {
-
GDCLASS(VehicleWheel3D, Node3D);
friend class VehicleBody3D;
@@ -146,13 +145,12 @@ public:
void set_steering(float p_steering);
float get_steering() const;
- String get_configuration_warning() const;
+ String get_configuration_warning() const override;
VehicleWheel3D();
};
class VehicleBody3D : public RigidBody3D {
-
GDCLASS(VehicleBody3D, RigidBody3D);
float engine_force;
@@ -194,7 +192,7 @@ class VehicleBody3D : public RigidBody3D {
static void _bind_methods();
- void _direct_state_changed(Object *p_state);
+ void _direct_state_changed(Object *p_state) override;
public:
void set_engine_force(float p_engine_force);
diff --git a/scene/3d/velocity_tracker_3d.cpp b/scene/3d/velocity_tracker_3d.cpp
index c9b95e6397..eba7d44c16 100644
--- a/scene/3d/velocity_tracker_3d.cpp
+++ b/scene/3d/velocity_tracker_3d.cpp
@@ -29,19 +29,17 @@
/*************************************************************************/
#include "velocity_tracker_3d.h"
-#include "core/engine.h"
+#include "core/config/engine.h"
void VelocityTracker3D::set_track_physics_step(bool p_track_physics_step) {
-
physics_step = p_track_physics_step;
}
bool VelocityTracker3D::is_tracking_physics_step() const {
-
return physics_step;
}
-void VelocityTracker3D::update_position(const Vector3 &p_position) {
+void VelocityTracker3D::update_position(const Vector3 &p_position) {
PositionHistory ph;
ph.position = p_position;
if (physics_step) {
@@ -59,8 +57,8 @@ void VelocityTracker3D::update_position(const Vector3 &p_position) {
position_history.write[0] = ph;
}
-Vector3 VelocityTracker3D::get_tracked_linear_velocity() const {
+Vector3 VelocityTracker3D::get_tracked_linear_velocity() const {
Vector3 linear_velocity;
float max_time = 1 / 5.0; //maximum time to interpolate a velocity
@@ -90,8 +88,9 @@ Vector3 VelocityTracker3D::get_tracked_linear_velocity() const {
delta = double(diff) / 1000000.0;
}
- if (base_time + time_accum + delta > max_time)
+ if (base_time + time_accum + delta > max_time) {
break;
+ }
distance_accum += distance;
time_accum += delta;
@@ -105,7 +104,6 @@ Vector3 VelocityTracker3D::get_tracked_linear_velocity() const {
}
void VelocityTracker3D::reset(const Vector3 &p_new_pos) {
-
PositionHistory ph;
ph.position = p_new_pos;
if (physics_step) {
@@ -119,7 +117,6 @@ void VelocityTracker3D::reset(const Vector3 &p_new_pos) {
}
void VelocityTracker3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_track_physics_step", "enable"), &VelocityTracker3D::set_track_physics_step);
ClassDB::bind_method(D_METHOD("is_tracking_physics_step"), &VelocityTracker3D::is_tracking_physics_step);
ClassDB::bind_method(D_METHOD("update_position", "position"), &VelocityTracker3D::update_position);
diff --git a/scene/3d/visibility_notifier_3d.cpp b/scene/3d/visibility_notifier_3d.cpp
index 2f657fe7b1..9f5c40caf4 100644
--- a/scene/3d/visibility_notifier_3d.cpp
+++ b/scene/3d/visibility_notifier_3d.cpp
@@ -30,14 +30,13 @@
#include "visibility_notifier_3d.h"
-#include "core/engine.h"
+#include "core/config/engine.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/scene_string_names.h"
void VisibilityNotifier3D::_enter_camera(Camera3D *p_camera) {
-
ERR_FAIL_COND(cameras.has(p_camera));
cameras.insert(p_camera);
if (cameras.size() == 1) {
@@ -49,7 +48,6 @@ void VisibilityNotifier3D::_enter_camera(Camera3D *p_camera) {
}
void VisibilityNotifier3D::_exit_camera(Camera3D *p_camera) {
-
ERR_FAIL_COND(!cameras.has(p_camera));
cameras.erase(p_camera);
@@ -62,13 +60,13 @@ void VisibilityNotifier3D::_exit_camera(Camera3D *p_camera) {
}
void VisibilityNotifier3D::set_aabb(const AABB &p_aabb) {
-
- if (aabb == p_aabb)
+ if (aabb == p_aabb) {
return;
+ }
aabb = p_aabb;
if (is_inside_world()) {
- get_world()->_update_notifier(this, get_global_transform().xform(aabb));
+ get_world_3d()->_update_notifier(this, get_global_transform().xform(aabb));
}
_change_notify("aabb");
@@ -76,35 +74,28 @@ void VisibilityNotifier3D::set_aabb(const AABB &p_aabb) {
}
AABB VisibilityNotifier3D::get_aabb() const {
-
return aabb;
}
void VisibilityNotifier3D::_notification(int p_what) {
-
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
-
- get_world()->_register_notifier(this, get_global_transform().xform(aabb));
+ get_world_3d()->_register_notifier(this, get_global_transform().xform(aabb));
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
-
- get_world()->_update_notifier(this, get_global_transform().xform(aabb));
+ get_world_3d()->_update_notifier(this, get_global_transform().xform(aabb));
} break;
case NOTIFICATION_EXIT_WORLD: {
-
- get_world()->_remove_notifier(this);
+ get_world_3d()->_remove_notifier(this);
} break;
}
}
bool VisibilityNotifier3D::is_on_screen() const {
-
return cameras.size() != 0;
}
void VisibilityNotifier3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_aabb", "rect"), &VisibilityNotifier3D::set_aabb);
ClassDB::bind_method(D_METHOD("get_aabb"), &VisibilityNotifier3D::get_aabb);
ClassDB::bind_method(D_METHOD("is_on_screen"), &VisibilityNotifier3D::is_on_screen);
@@ -118,7 +109,6 @@ void VisibilityNotifier3D::_bind_methods() {
}
VisibilityNotifier3D::VisibilityNotifier3D() {
-
aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
set_notify_transform(true);
}
@@ -126,9 +116,7 @@ VisibilityNotifier3D::VisibilityNotifier3D() {
//////////////////////////////////////
void VisibilityEnabler3D::_screen_enter() {
-
for (Map<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
-
_change_node_state(E->key(), true);
}
@@ -136,9 +124,7 @@ void VisibilityEnabler3D::_screen_enter() {
}
void VisibilityEnabler3D::_screen_exit() {
-
for (Map<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
-
_change_node_state(E->key(), false);
}
@@ -146,14 +132,12 @@ void VisibilityEnabler3D::_screen_exit() {
}
void VisibilityEnabler3D::_find_nodes(Node *p_node) {
-
bool add = false;
Variant meta;
{
RigidBody3D *rb = Object::cast_to<RigidBody3D>(p_node);
if (rb && ((rb->get_mode() == RigidBody3D::MODE_CHARACTER || rb->get_mode() == RigidBody3D::MODE_RIGID))) {
-
add = true;
meta = rb->get_mode();
}
@@ -167,7 +151,6 @@ void VisibilityEnabler3D::_find_nodes(Node *p_node) {
}
if (add) {
-
p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler3D::_node_removed), varray(p_node), CONNECT_ONESHOT);
nodes[p_node] = meta;
_change_node_state(p_node, false);
@@ -175,37 +158,38 @@ void VisibilityEnabler3D::_find_nodes(Node *p_node) {
for (int i = 0; i < p_node->get_child_count(); i++) {
Node *c = p_node->get_child(i);
- if (c->get_filename() != String())
+ if (c->get_filename() != String()) {
continue; //skip, instance
+ }
_find_nodes(c);
}
}
void VisibilityEnabler3D::_notification(int p_what) {
-
if (p_what == NOTIFICATION_ENTER_TREE) {
-
- if (Engine::get_singleton()->is_editor_hint())
+ if (Engine::get_singleton()->is_editor_hint()) {
return;
+ }
Node *from = this;
//find where current scene starts
- while (from->get_parent() && from->get_filename() == String())
+ while (from->get_parent() && from->get_filename() == String()) {
from = from->get_parent();
+ }
_find_nodes(from);
}
if (p_what == NOTIFICATION_EXIT_TREE) {
-
- if (Engine::get_singleton()->is_editor_hint())
+ if (Engine::get_singleton()->is_editor_hint()) {
return;
+ }
for (Map<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
-
- if (!visible)
+ if (!visible) {
_change_node_state(E->key(), true);
+ }
E->key()->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler3D::_node_removed));
}
@@ -214,35 +198,32 @@ void VisibilityEnabler3D::_notification(int p_what) {
}
void VisibilityEnabler3D::_change_node_state(Node *p_node, bool p_enabled) {
-
ERR_FAIL_COND(!nodes.has(p_node));
if (enabler[ENABLER_FREEZE_BODIES]) {
RigidBody3D *rb = Object::cast_to<RigidBody3D>(p_node);
- if (rb)
-
+ if (rb) {
rb->set_sleeping(!p_enabled);
+ }
}
if (enabler[ENABLER_PAUSE_ANIMATIONS]) {
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
if (ap) {
-
ap->set_active(p_enabled);
}
}
}
void VisibilityEnabler3D::_node_removed(Node *p_node) {
-
- if (!visible)
+ if (!visible) {
_change_node_state(p_node, true);
+ }
nodes.erase(p_node);
}
void VisibilityEnabler3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_enabler", "enabler", "enabled"), &VisibilityEnabler3D::set_enabler);
ClassDB::bind_method(D_METHOD("is_enabler_enabled", "enabler"), &VisibilityEnabler3D::is_enabler_enabled);
@@ -255,20 +236,19 @@ void VisibilityEnabler3D::_bind_methods() {
}
void VisibilityEnabler3D::set_enabler(Enabler p_enabler, bool p_enable) {
-
ERR_FAIL_INDEX(p_enabler, ENABLER_MAX);
enabler[p_enabler] = p_enable;
}
-bool VisibilityEnabler3D::is_enabler_enabled(Enabler p_enabler) const {
+bool VisibilityEnabler3D::is_enabler_enabled(Enabler p_enabler) const {
ERR_FAIL_INDEX_V(p_enabler, ENABLER_MAX, false);
return enabler[p_enabler];
}
VisibilityEnabler3D::VisibilityEnabler3D() {
-
- for (int i = 0; i < ENABLER_MAX; i++)
+ for (int i = 0; i < ENABLER_MAX; i++) {
enabler[i] = true;
+ }
visible = false;
}
diff --git a/scene/3d/visibility_notifier_3d.h b/scene/3d/visibility_notifier_3d.h
index 19204a6a4e..35f6c02e83 100644
--- a/scene/3d/visibility_notifier_3d.h
+++ b/scene/3d/visibility_notifier_3d.h
@@ -35,7 +35,6 @@
class Camera3D;
class VisibilityNotifier3D : public Node3D {
-
GDCLASS(VisibilityNotifier3D, Node3D);
Set<Camera3D *> cameras;
@@ -62,7 +61,6 @@ public:
};
class VisibilityEnabler3D : public VisibilityNotifier3D {
-
GDCLASS(VisibilityEnabler3D, VisibilityNotifier3D);
public:
@@ -73,8 +71,8 @@ public:
};
protected:
- virtual void _screen_enter();
- virtual void _screen_exit();
+ virtual void _screen_enter() override;
+ virtual void _screen_exit() override;
bool visible;
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index 604bc53422..a1c498e8ab 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -35,73 +35,62 @@
#include "skeleton_3d.h"
AABB VisualInstance3D::get_transformed_aabb() const {
-
return get_global_transform().xform(get_aabb());
}
void VisualInstance3D::_update_visibility() {
-
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
_change_notify("visible");
RS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree());
}
void VisualInstance3D::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_ENTER_WORLD: {
-
// CHECK SKELETON => moving skeleton attaching logic to MeshInstance
/*
Skeleton *skeleton=Object::cast_to<Skeleton>(get_parent());
if (skeleton)
RenderingServer::get_singleton()->instance_attach_skeleton( instance, skeleton->get_skeleton() );
*/
- ERR_FAIL_COND(get_world().is_null());
- RenderingServer::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario());
+ ERR_FAIL_COND(get_world_3d().is_null());
+ RenderingServer::get_singleton()->instance_set_scenario(instance, get_world_3d()->get_scenario());
_update_visibility();
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
-
Transform gt = get_global_transform();
RenderingServer::get_singleton()->instance_set_transform(instance, gt);
} break;
case NOTIFICATION_EXIT_WORLD: {
-
RenderingServer::get_singleton()->instance_set_scenario(instance, RID());
RenderingServer::get_singleton()->instance_attach_skeleton(instance, RID());
//RS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID() );
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
-
_update_visibility();
} break;
}
}
RID VisualInstance3D::get_instance() const {
-
return instance;
}
RID VisualInstance3D::_get_visual_instance_rid() const {
-
return instance;
}
void VisualInstance3D::set_layer_mask(uint32_t p_mask) {
-
layers = p_mask;
RenderingServer::get_singleton()->instance_set_layer_mask(instance, p_mask);
}
uint32_t VisualInstance3D::get_layer_mask() const {
-
return layers;
}
@@ -120,7 +109,6 @@ bool VisualInstance3D::get_layer_mask_bit(int p_layer) const {
}
void VisualInstance3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("_get_visual_instance_rid"), &VisualInstance3D::_get_visual_instance_rid);
ClassDB::bind_method(D_METHOD("set_base", "base"), &VisualInstance3D::set_base);
ClassDB::bind_method(D_METHOD("get_base"), &VisualInstance3D::get_base);
@@ -136,18 +124,15 @@ void VisualInstance3D::_bind_methods() {
}
void VisualInstance3D::set_base(const RID &p_base) {
-
RenderingServer::get_singleton()->instance_set_base(instance, p_base);
base = p_base;
}
RID VisualInstance3D::get_base() const {
-
return base;
}
VisualInstance3D::VisualInstance3D() {
-
instance = RenderingServer::get_singleton()->instance_create();
RenderingServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id());
layers = 1;
@@ -155,62 +140,51 @@ VisualInstance3D::VisualInstance3D() {
}
VisualInstance3D::~VisualInstance3D() {
-
RenderingServer::get_singleton()->free(instance);
}
void GeometryInstance3D::set_material_override(const Ref<Material> &p_material) {
-
material_override = p_material;
RS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID());
}
Ref<Material> GeometryInstance3D::get_material_override() const {
-
return material_override;
}
void GeometryInstance3D::set_lod_min_distance(float p_dist) {
-
lod_min_distance = p_dist;
RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
}
float GeometryInstance3D::get_lod_min_distance() const {
-
return lod_min_distance;
}
void GeometryInstance3D::set_lod_max_distance(float p_dist) {
-
lod_max_distance = p_dist;
RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
}
float GeometryInstance3D::get_lod_max_distance() const {
-
return lod_max_distance;
}
void GeometryInstance3D::set_lod_min_hysteresis(float p_dist) {
-
lod_min_hysteresis = p_dist;
RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
}
float GeometryInstance3D::get_lod_min_hysteresis() const {
-
return lod_min_hysteresis;
}
void GeometryInstance3D::set_lod_max_hysteresis(float p_dist) {
-
lod_max_hysteresis = p_dist;
RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
}
float GeometryInstance3D::get_lod_max_hysteresis() const {
-
return lod_max_hysteresis;
}
@@ -239,7 +213,17 @@ bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value)
set_shader_instance_uniform(*r, p_value);
return true;
}
+#ifndef DISABLE_DEPRECATED
+ if (p_name == SceneStringNames::get_singleton()->use_in_baked_light && bool(p_value)) {
+ set_gi_mode(GI_MODE_BAKED);
+ return true;
+ }
+ if (p_name == SceneStringNames::get_singleton()->use_dynamic_gi && bool(p_value)) {
+ set_gi_mode(GI_MODE_DYNAMIC);
+ return true;
+ }
+#endif
return false;
}
@@ -252,6 +236,7 @@ bool GeometryInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
return false;
}
+
void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
List<PropertyInfo> pinfo;
RS::get_singleton()->instance_geometry_get_shader_parameter_list(get_instance(), &pinfo);
@@ -273,49 +258,27 @@ void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
-void GeometryInstance3D::set_flag(Flags p_flag, bool p_value) {
-
- ERR_FAIL_INDEX(p_flag, FLAG_MAX);
- if (flags[p_flag] == p_value)
- return;
-
- flags[p_flag] = p_value;
- RS::get_singleton()->instance_geometry_set_flag(get_instance(), (RS::InstanceFlags)p_flag, p_value);
-}
-
-bool GeometryInstance3D::get_flag(Flags p_flag) const {
-
- ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
-
- return flags[p_flag];
-}
-
void GeometryInstance3D::set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting) {
-
shadow_casting_setting = p_shadow_casting_setting;
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(get_instance(), (RS::ShadowCastingSetting)p_shadow_casting_setting);
}
GeometryInstance3D::ShadowCastingSetting GeometryInstance3D::get_cast_shadows_setting() const {
-
return shadow_casting_setting;
}
void GeometryInstance3D::set_extra_cull_margin(float p_margin) {
-
ERR_FAIL_COND(p_margin < 0);
extra_cull_margin = p_margin;
RS::get_singleton()->instance_set_extra_visibility_margin(get_instance(), extra_cull_margin);
}
float GeometryInstance3D::get_extra_cull_margin() const {
-
return extra_cull_margin;
}
void GeometryInstance3D::set_shader_instance_uniform(const StringName &p_uniform, const Variant &p_value) {
-
if (p_value.get_type() == Variant::NIL) {
Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), p_uniform);
RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, def_value);
@@ -327,22 +290,50 @@ void GeometryInstance3D::set_shader_instance_uniform(const StringName &p_uniform
}
Variant GeometryInstance3D::get_shader_instance_uniform(const StringName &p_uniform) const {
-
return RS::get_singleton()->instance_geometry_get_shader_parameter(get_instance(), p_uniform);
}
-void GeometryInstance3D::set_custom_aabb(AABB aabb) {
+void GeometryInstance3D::set_custom_aabb(AABB aabb) {
RS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb);
}
-void GeometryInstance3D::_bind_methods() {
+void GeometryInstance3D::set_lightmap_scale(LightmapScale p_scale) {
+ ERR_FAIL_INDEX(p_scale, LIGHTMAP_SCALE_MAX);
+ lightmap_scale = p_scale;
+}
+GeometryInstance3D::LightmapScale GeometryInstance3D::get_lightmap_scale() const {
+ return lightmap_scale;
+}
+
+void GeometryInstance3D::set_gi_mode(GIMode p_mode) {
+ switch (p_mode) {
+ case GI_MODE_DISABLED: {
+ RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
+ RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_DYNAMIC_GI, false);
+ } break;
+ case GI_MODE_BAKED: {
+ RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_BAKED_LIGHT, true);
+ RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_DYNAMIC_GI, false);
+
+ } break;
+ case GI_MODE_DYNAMIC: {
+ RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
+ RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_DYNAMIC_GI, true);
+ } break;
+ }
+
+ gi_mode = p_mode;
+}
+
+GeometryInstance3D::GIMode GeometryInstance3D::get_gi_mode() const {
+ return gi_mode;
+}
+
+void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_material_override", "material"), &GeometryInstance3D::set_material_override);
ClassDB::bind_method(D_METHOD("get_material_override"), &GeometryInstance3D::get_material_override);
- ClassDB::bind_method(D_METHOD("set_flag", "flag", "value"), &GeometryInstance3D::set_flag);
- ClassDB::bind_method(D_METHOD("get_flag", "flag"), &GeometryInstance3D::get_flag);
-
ClassDB::bind_method(D_METHOD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance3D::set_cast_shadows_setting);
ClassDB::bind_method(D_METHOD("get_cast_shadows_setting"), &GeometryInstance3D::get_cast_shadows_setting);
@@ -364,6 +355,12 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance3D::set_extra_cull_margin);
ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance3D::get_extra_cull_margin);
+ ClassDB::bind_method(D_METHOD("set_lightmap_scale", "scale"), &GeometryInstance3D::set_lightmap_scale);
+ ClassDB::bind_method(D_METHOD("get_lightmap_scale"), &GeometryInstance3D::get_lightmap_scale);
+
+ ClassDB::bind_method(D_METHOD("set_gi_mode", "mode"), &GeometryInstance3D::set_gi_mode);
+ ClassDB::bind_method(D_METHOD("get_gi_mode"), &GeometryInstance3D::get_gi_mode);
+
ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &GeometryInstance3D::set_custom_aabb);
ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance3D::get_aabb);
@@ -372,8 +369,9 @@ void GeometryInstance3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_in_baked_light"), "set_flag", "get_flag", FLAG_USE_BAKED_LIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_dynamic_gi"), "set_flag", "get_flag", FLAG_USE_DYNAMIC_GI);
+ ADD_GROUP("Global Illumination", "gi_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Baked,Dynamic"), "set_gi_mode", "get_gi_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, "1x,2x,4x,8x"), "set_lightmap_scale", "get_lightmap_scale");
ADD_GROUP("LOD", "lod_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_distance", "get_lod_min_distance");
@@ -388,10 +386,15 @@ void GeometryInstance3D::_bind_methods() {
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED);
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY);
- BIND_ENUM_CONSTANT(FLAG_USE_BAKED_LIGHT);
- BIND_ENUM_CONSTANT(FLAG_USE_DYNAMIC_GI);
- BIND_ENUM_CONSTANT(FLAG_DRAW_NEXT_FRAME_IF_VISIBLE);
- BIND_ENUM_CONSTANT(FLAG_MAX);
+ BIND_ENUM_CONSTANT(GI_MODE_DISABLED);
+ BIND_ENUM_CONSTANT(GI_MODE_BAKED);
+ BIND_ENUM_CONSTANT(GI_MODE_DYNAMIC);
+
+ BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_1X);
+ BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_2X);
+ BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_4X);
+ BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_8X);
+ BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_MAX);
}
GeometryInstance3D::GeometryInstance3D() {
@@ -400,9 +403,8 @@ GeometryInstance3D::GeometryInstance3D() {
lod_min_hysteresis = 0;
lod_max_hysteresis = 0;
- for (int i = 0; i < FLAG_MAX; i++) {
- flags[i] = false;
- }
+ gi_mode = GI_MODE_DISABLED;
+ lightmap_scale = LIGHTMAP_SCALE_1X;
shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
extra_cull_margin = 0;
diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h
index cc5f92066f..51bcb411da 100644
--- a/scene/3d/visual_instance_3d.h
+++ b/scene/3d/visual_instance_3d.h
@@ -32,12 +32,11 @@
#define VISUAL_INSTANCE_H
#include "core/math/face3.h"
-#include "core/rid.h"
+#include "core/templates/rid.h"
#include "scene/3d/node_3d.h"
#include "scene/resources/material.h"
class VisualInstance3D : public Node3D {
-
GDCLASS(VisualInstance3D, Node3D);
OBJ_CATEGORY("3D Visual Nodes");
@@ -81,17 +80,9 @@ public:
};
class GeometryInstance3D : public VisualInstance3D {
-
GDCLASS(GeometryInstance3D, VisualInstance3D);
public:
- enum Flags {
- FLAG_USE_BAKED_LIGHT = RS::INSTANCE_FLAG_USE_BAKED_LIGHT,
- FLAG_USE_DYNAMIC_GI = RS::INSTANCE_FLAG_USE_DYNAMIC_GI,
- FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE,
- FLAG_MAX = RS::INSTANCE_FLAG_MAX,
- };
-
enum ShadowCastingSetting {
SHADOW_CASTING_SETTING_OFF = RS::SHADOW_CASTING_SETTING_OFF,
SHADOW_CASTING_SETTING_ON = RS::SHADOW_CASTING_SETTING_ON,
@@ -99,8 +90,21 @@ public:
SHADOW_CASTING_SETTING_SHADOWS_ONLY = RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY
};
+ enum GIMode {
+ GI_MODE_DISABLED,
+ GI_MODE_BAKED,
+ GI_MODE_DYNAMIC
+ };
+
+ enum LightmapScale {
+ LIGHTMAP_SCALE_1X,
+ LIGHTMAP_SCALE_2X,
+ LIGHTMAP_SCALE_4X,
+ LIGHTMAP_SCALE_8X,
+ LIGHTMAP_SCALE_MAX,
+ };
+
private:
- bool flags[FLAG_MAX];
ShadowCastingSetting shadow_casting_setting;
Ref<Material> material_override;
float lod_min_distance;
@@ -112,6 +116,8 @@ private:
mutable HashMap<StringName, StringName> instance_uniform_property_remap;
float extra_cull_margin;
+ LightmapScale lightmap_scale;
+ GIMode gi_mode;
const StringName *_instance_uniform_get_remap(const StringName p_name) const;
@@ -124,9 +130,6 @@ protected:
static void _bind_methods();
public:
- void set_flag(Flags p_flag, bool p_value);
- bool get_flag(Flags p_flag) const;
-
void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting);
ShadowCastingSetting get_cast_shadows_setting() const;
@@ -148,6 +151,12 @@ public:
void set_extra_cull_margin(float p_margin);
float get_extra_cull_margin() const;
+ void set_gi_mode(GIMode p_mode);
+ GIMode get_gi_mode() const;
+
+ void set_lightmap_scale(LightmapScale p_scale);
+ LightmapScale get_lightmap_scale() const;
+
void set_shader_instance_uniform(const StringName &p_uniform, const Variant &p_value);
Variant get_shader_instance_uniform(const StringName &p_uniform) const;
@@ -156,7 +165,8 @@ public:
GeometryInstance3D();
};
-VARIANT_ENUM_CAST(GeometryInstance3D::Flags);
VARIANT_ENUM_CAST(GeometryInstance3D::ShadowCastingSetting);
+VARIANT_ENUM_CAST(GeometryInstance3D::LightmapScale);
+VARIANT_ENUM_CAST(GeometryInstance3D::GIMode);
#endif
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
index f30c58be55..c570fc7b7c 100644
--- a/scene/3d/voxelizer.cpp
+++ b/scene/3d/voxelizer.cpp
@@ -29,194 +29,13 @@
/*************************************************************************/
#include "voxelizer.h"
+#include "core/math/geometry_3d.h"
#include "core/os/os.h"
#include "core/os/threaded_array_processor.h"
#include <stdlib.h>
-#define FINDMINMAX(x0, x1, x2, min, max) \
- min = max = x0; \
- if (x1 < min) min = x1; \
- if (x1 > max) max = x1; \
- if (x2 < min) min = x2; \
- if (x2 > max) max = x2;
-
-static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) {
- int q;
- Vector3 vmin, vmax;
- for (q = 0; q <= 2; q++) {
- if (normal[q] > 0.0f) {
- vmin[q] = -maxbox[q];
- vmax[q] = maxbox[q];
- } else {
- vmin[q] = maxbox[q];
- vmax[q] = -maxbox[q];
- }
- }
- if (normal.dot(vmin) + d > 0.0f) return false;
- if (normal.dot(vmax) + d >= 0.0f) return true;
-
- return false;
-}
-
-/*======================== X-tests ========================*/
-#define AXISTEST_X01(a, b, fa, fb) \
- p0 = a * v0.y - b * v0.z; \
- p2 = a * v2.y - b * v2.z; \
- if (p0 < p2) { \
- min = p0; \
- max = p2; \
- } else { \
- min = p2; \
- max = p0; \
- } \
- rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \
- if (min > rad || max < -rad) return false;
-
-#define AXISTEST_X2(a, b, fa, fb) \
- p0 = a * v0.y - b * v0.z; \
- p1 = a * v1.y - b * v1.z; \
- if (p0 < p1) { \
- min = p0; \
- max = p1; \
- } else { \
- min = p1; \
- max = p0; \
- } \
- rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \
- if (min > rad || max < -rad) return false;
-
-/*======================== Y-tests ========================*/
-#define AXISTEST_Y02(a, b, fa, fb) \
- p0 = -a * v0.x + b * v0.z; \
- p2 = -a * v2.x + b * v2.z; \
- if (p0 < p2) { \
- min = p0; \
- max = p2; \
- } else { \
- min = p2; \
- max = p0; \
- } \
- rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
- if (min > rad || max < -rad) return false;
-
-#define AXISTEST_Y1(a, b, fa, fb) \
- p0 = -a * v0.x + b * v0.z; \
- p1 = -a * v1.x + b * v1.z; \
- if (p0 < p1) { \
- min = p0; \
- max = p1; \
- } else { \
- min = p1; \
- max = p0; \
- } \
- rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
- if (min > rad || max < -rad) return false;
-
-/*======================== Z-tests ========================*/
-
-#define AXISTEST_Z12(a, b, fa, fb) \
- p1 = a * v1.x - b * v1.y; \
- p2 = a * v2.x - b * v2.y; \
- if (p2 < p1) { \
- min = p2; \
- max = p1; \
- } else { \
- min = p1; \
- max = p2; \
- } \
- rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
- if (min > rad || max < -rad) return false;
-
-#define AXISTEST_Z0(a, b, fa, fb) \
- p0 = a * v0.x - b * v0.y; \
- p1 = a * v1.x - b * v1.y; \
- if (p0 < p1) { \
- min = p0; \
- max = p1; \
- } else { \
- min = p1; \
- max = p0; \
- } \
- rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
- if (min > rad || max < -rad) return false;
-
-static bool fast_tri_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalfsize, const Vector3 *triverts) {
-
- /* use separating axis theorem to test overlap between triangle and box */
- /* need to test for overlap in these directions: */
- /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
- /* we do not even need to test these) */
- /* 2) normal of the triangle */
- /* 3) crossproduct(edge from tri, {x,y,z}-directin) */
- /* this gives 3x3=9 more tests */
- Vector3 v0, v1, v2;
- float min, max, d, p0, p1, p2, rad, fex, fey, fez;
- Vector3 normal, e0, e1, e2;
-
- /* This is the fastest branch on Sun */
- /* move everything so that the boxcenter is in (0,0,0) */
-
- v0 = triverts[0] - boxcenter;
- v1 = triverts[1] - boxcenter;
- v2 = triverts[2] - boxcenter;
-
- /* compute triangle edges */
- e0 = v1 - v0; /* tri edge 0 */
- e1 = v2 - v1; /* tri edge 1 */
- e2 = v0 - v2; /* tri edge 2 */
-
- /* Bullet 3: */
- /* test the 9 tests first (this was faster) */
- fex = Math::abs(e0.x);
- fey = Math::abs(e0.y);
- fez = Math::abs(e0.z);
- AXISTEST_X01(e0.z, e0.y, fez, fey);
- AXISTEST_Y02(e0.z, e0.x, fez, fex);
- AXISTEST_Z12(e0.y, e0.x, fey, fex);
-
- fex = Math::abs(e1.x);
- fey = Math::abs(e1.y);
- fez = Math::abs(e1.z);
- AXISTEST_X01(e1.z, e1.y, fez, fey);
- AXISTEST_Y02(e1.z, e1.x, fez, fex);
- AXISTEST_Z0(e1.y, e1.x, fey, fex);
-
- fex = Math::abs(e2.x);
- fey = Math::abs(e2.y);
- fez = Math::abs(e2.z);
- AXISTEST_X2(e2.z, e2.y, fez, fey);
- AXISTEST_Y1(e2.z, e2.x, fez, fex);
- AXISTEST_Z12(e2.y, e2.x, fey, fex);
-
- /* Bullet 1: */
- /* first test overlap in the {x,y,z}-directions */
- /* find min, max of the triangle each direction, and test for overlap in */
- /* that direction -- this is equivalent to testing a minimal AABB around */
- /* the triangle against the AABB */
-
- /* test in X-direction */
- FINDMINMAX(v0.x, v1.x, v2.x, min, max);
- if (min > boxhalfsize.x || max < -boxhalfsize.x) return false;
-
- /* test in Y-direction */
- FINDMINMAX(v0.y, v1.y, v2.y, min, max);
- if (min > boxhalfsize.y || max < -boxhalfsize.y) return false;
-
- /* test in Z-direction */
- FINDMINMAX(v0.z, v1.z, v2.z, min, max);
- if (min > boxhalfsize.z || max < -boxhalfsize.z) return false;
-
- /* Bullet 2: */
- /* test if the box intersects the plane of the triangle */
- /* compute plane equation of triangle: normal*x+d=0 */
- normal = e0.cross(e1);
- d = -normal.dot(v0); /* plane eq: normal.x+d=0 */
- return planeBoxOverlap(normal, d, boxhalfsize); /* if true, box and triangle overlaps */
-}
-
static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) {
-
if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) {
r_uv = p_uv[0];
r_normal = p_normal[0];
@@ -257,7 +76,6 @@ static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3
}
void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector3 *p_normal, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb) {
-
if (p_level == cell_subdiv) {
//plot the face by guessing its albedo and emission value
@@ -269,7 +87,6 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
Vector3 normal = plane.normal;
for (int i = 0; i < 3; i++) {
-
Vector3 axis;
axis[i] = 1.0;
float dot = ABS(normal.dot(axis));
@@ -297,11 +114,9 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
//map to a grid average in the best axis for this face
for (int i = 0; i < color_scan_cell_width; i++) {
-
Vector3 ofs_i = float(i) * t1;
for (int j = 0; j < color_scan_cell_width; j++) {
-
Vector3 ofs_j = float(j) * t2;
Vector3 from = p_aabb.position + ofs_i + ofs_j;
@@ -309,7 +124,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
Vector3 half = (to - from) * 0.5;
//is in this cell?
- if (!fast_tri_box_overlap(from + half, half, p_vtx)) {
+ if (!Geometry3D::triangle_box_overlap(from + half, half, p_vtx)) {
continue; //face does not span this cell
}
@@ -327,7 +142,6 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
if (ABS(plane.distance_to(ray_from)) < ABS(plane.distance_to(ray_to))) {
intersection = plane.project(ray_from);
} else {
-
intersection = plane.project(ray_to);
}
}
@@ -337,8 +151,9 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
Vector2 uv;
Vector3 lnormal;
get_uv_and_normal(intersection, p_vtx, p_uv, p_normal, uv, lnormal);
- if (lnormal == Vector3()) //just in case normal as nor provided
+ if (lnormal == Vector3()) { //just in case normal as nor provided
lnormal = normal;
+ }
int uv_x = CLAMP(int(Math::fposmod(uv.x, 1.0f) * bake_texture_size), 0, bake_texture_size - 1);
int uv_y = CLAMP(int(Math::fposmod(uv.y, 1.0f) * bake_texture_size), 0, bake_texture_size - 1);
@@ -368,8 +183,9 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
Vector3 lnormal;
Vector2 uv;
get_uv_and_normal(inters, p_vtx, p_uv, p_normal, uv, normal);
- if (lnormal == Vector3()) //just in case normal as nor provided
+ if (lnormal == Vector3()) { //just in case normal as nor provided
lnormal = normal;
+ }
int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
@@ -390,7 +206,6 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
normal_accum = lnormal * alpha;
} else {
-
float accdiv = 1.0 / (color_scan_cell_width * color_scan_cell_width);
alpha *= accdiv;
@@ -423,7 +238,6 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
int half = (1 << cell_subdiv) >> (p_level + 1);
for (int i = 0; i < 8; i++) {
-
AABB aabb = p_aabb;
aabb.size *= 0.5;
@@ -444,15 +258,16 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
nz += half;
}
//make sure to not plot beyond limits
- if (nx < 0 || nx >= axis_cell_size[0] || ny < 0 || ny >= axis_cell_size[1] || nz < 0 || nz >= axis_cell_size[2])
+ if (nx < 0 || nx >= axis_cell_size[0] || ny < 0 || ny >= axis_cell_size[1] || nz < 0 || nz >= axis_cell_size[2]) {
continue;
+ }
{
AABB test_aabb = aabb;
//test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time
Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test
- if (!fast_tri_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) {
+ if (!Geometry3D::triangle_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) {
//if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) {
//does not fit in child, go on
continue;
@@ -477,11 +292,9 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
}
Vector<Color> Voxelizer::_get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add) {
-
Vector<Color> ret;
if (p_image.is_null() || p_image->empty()) {
-
ret.resize(bake_texture_size * bake_texture_size);
for (int i = 0; i < bake_texture_size * bake_texture_size; i++) {
ret.write[i] = p_color_add;
@@ -515,7 +328,6 @@ Vector<Color> Voxelizer::_get_bake_texture(Ref<Image> p_image, const Color &p_co
}
Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material) {
-
//this way of obtaining materials is inaccurate and also does not support some compressed formats very well
Ref<StandardMaterial3D> mat = p_material;
@@ -528,12 +340,10 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material
MaterialCache mc;
if (mat.is_valid()) {
-
Ref<Texture2D> albedo_tex = mat->get_texture(StandardMaterial3D::TEXTURE_ALBEDO);
Ref<Image> img_albedo;
if (albedo_tex.is_valid()) {
-
img_albedo = albedo_tex->get_data();
mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo(), Color(0, 0, 0)); // albedo texture, color is multiplicative
} else {
@@ -548,7 +358,6 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material
Ref<Image> img_emission;
if (emission_tex.is_valid()) {
-
img_emission = emission_tex->get_data();
}
@@ -570,11 +379,10 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material
}
void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material) {
-
for (int i = 0; i < p_mesh->get_surface_count(); i++) {
-
- if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES)
+ if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
continue; //only triangles
+ }
Ref<Material> src_material;
@@ -606,12 +414,10 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec
}
if (index.size()) {
-
int facecount = index.size() / 3;
const int *ir = index.ptr();
for (int j = 0; j < facecount; j++) {
-
Vector3 vtxs[3];
Vector2 uvs[3];
Vector3 normal[3];
@@ -633,18 +439,17 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec
}
//test against original bounds
- if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
+ if (!Geometry3D::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) {
continue;
+ }
//plot
_plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds);
}
} else {
-
int facecount = vertices.size() / 3;
for (int j = 0; j < facecount; j++) {
-
Vector3 vtxs[3];
Vector2 uvs[3];
Vector3 normal[3];
@@ -666,8 +471,9 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec
}
//test against original bounds
- if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
+ if (!Geometry3D::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) {
continue;
+ }
//plot face
_plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds);
}
@@ -678,7 +484,6 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec
}
void Voxelizer::_sort() {
-
// cells need to be sorted by level and coordinates
// it is important that level has more priority (for compute), and that Z has the least,
// given it may aid older implementations plot using GPU
@@ -687,7 +492,6 @@ void Voxelizer::_sort() {
uint32_t cell_count = bake_cells.size();
sorted_cells.resize(cell_count);
{
-
CellSort *sort_cellsp = sorted_cells.ptrw();
const Cell *bake_cellsp = bake_cells.ptr();
@@ -720,7 +524,6 @@ void Voxelizer::_sort() {
}
{
-
const CellSort *sort_cellsp = sorted_cells.ptr();
const Cell *bake_cellsp = bake_cells.ptr();
const uint32_t *reverse_mapp = reverse_map.ptr();
@@ -743,9 +546,7 @@ void Voxelizer::_sort() {
}
void Voxelizer::_fixup_plot(int p_idx, int p_level) {
-
if (p_level == cell_subdiv) {
-
leaf_voxel_count++;
float alpha = bake_cells[p_idx].alpha;
@@ -779,12 +580,10 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) {
/*if (bake_light.size()) {
for(int i=0;i<6;i++) {
-
}
}*/
} else {
-
//go down
bake_cells.write[p_idx].emission[0] = 0;
@@ -801,11 +600,11 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) {
int children_found = 0;
for (int i = 0; i < 8; i++) {
-
uint32_t child = bake_cells[p_idx].children[i];
- if (child == CHILD_EMPTY)
+ if (child == CHILD_EMPTY) {
continue;
+ }
_fixup_plot(child, p_level + 1);
alpha_average += bake_cells[child].alpha;
@@ -818,7 +617,6 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) {
}
void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds) {
-
sorted = false;
original_bounds = p_bounds;
cell_subdiv = p_subdiv;
@@ -833,9 +631,9 @@ void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds) {
leaf_voxel_count = 0;
for (int i = 0; i < 3; i++) {
-
- if (i == longest_axis)
+ if (i == longest_axis) {
continue;
+ }
axis_cell_size[i] = axis_cell_size[longest_axis];
float axis_size = po2_bounds.size[longest_axis];
@@ -873,9 +671,11 @@ void Voxelizer::end_bake() {
int Voxelizer::get_gi_probe_octree_depth() const {
return cell_subdiv;
}
+
Vector3i Voxelizer::get_giprobe_octree_size() const {
return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]);
}
+
int Voxelizer::get_giprobe_cell_count() const {
return bake_cells.size();
}
@@ -891,7 +691,6 @@ Vector<uint8_t> Voxelizer::get_giprobe_octree_cells() const {
uint32_t cell_count = bake_cells.size();
for (uint32_t i = 0; i < cell_count; i++) {
-
for (uint32_t j = 0; j < 8; j++) {
children_cells[i * 8 + j] = cells[i].children[j];
}
@@ -900,6 +699,7 @@ Vector<uint8_t> Voxelizer::get_giprobe_octree_cells() const {
return data;
}
+
Vector<uint8_t> Voxelizer::get_giprobe_data_cells() const {
Vector<uint8_t> data;
data.resize((4 * 4) * bake_cells.size()); //8 uint32t values
@@ -911,7 +711,6 @@ Vector<uint8_t> Voxelizer::get_giprobe_data_cells() const {
uint32_t cell_count = bake_cells.size();
for (uint32_t i = 0; i < cell_count; i++) {
-
{ //position
uint32_t x = cells[i].x;
@@ -983,7 +782,6 @@ Vector<int> Voxelizer::get_giprobe_level_cell_count() const {
/* dt of 1d function using squared distance */
static void edt(float *f, int stride, int n) {
-
float *d = (float *)alloca(sizeof(float) * n + sizeof(int) * n + sizeof(float) * (n + 1));
int *v = (int *)&(d[n]);
float *z = (float *)&v[n];
@@ -1007,8 +805,9 @@ static void edt(float *f, int stride, int n) {
k = 0;
for (int q = 0; q <= n - 1; q++) {
- while (z[k + 1] < q)
+ while (z[k + 1] < q) {
k++;
+ }
d[q] = square(q - v[k]) + f[v[k] * stride];
}
@@ -1020,7 +819,6 @@ static void edt(float *f, int stride, int n) {
#undef square
Vector<uint8_t> Voxelizer::get_sdf_3d_image() const {
-
Vector3i octree_size = get_giprobe_octree_size();
uint32_t float_count = octree_size.x * octree_size.y * octree_size.z;
@@ -1038,7 +836,6 @@ Vector<uint8_t> Voxelizer::get_sdf_3d_image() const {
uint32_t cell_count = bake_cells.size();
for (uint32_t i = 0; i < cell_count; i++) {
-
if (cells[i].level < (cell_subdiv - 1)) {
continue; //do not care about this level
}
@@ -1092,9 +889,7 @@ Vector<uint8_t> Voxelizer::get_sdf_3d_image() const {
#undef INF
void Voxelizer::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx) {
-
if (p_level == cell_subdiv - 1) {
-
Vector3 center = p_aabb.position + p_aabb.size * 0.5;
Transform xform;
xform.origin = center;
@@ -1108,23 +903,25 @@ void Voxelizer::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<Mult
idx++;
} else {
-
for (int i = 0; i < 8; i++) {
-
uint32_t child = bake_cells[p_idx].children[i];
- if (child == CHILD_EMPTY || child >= (uint32_t)max_original_cells)
+ if (child == CHILD_EMPTY || child >= (uint32_t)max_original_cells) {
continue;
+ }
AABB aabb = p_aabb;
aabb.size *= 0.5;
- if (i & 1)
+ if (i & 1) {
aabb.position.x += aabb.size.x;
- if (i & 2)
+ }
+ if (i & 2) {
aabb.position.y += aabb.size.y;
- if (i & 4)
+ }
+ if (i & 4) {
aabb.position.z += aabb.size.z;
+ }
_debug_mesh(bake_cells[p_idx].children[i], p_level + 1, aabb, p_multimesh, idx);
}
@@ -1132,7 +929,6 @@ void Voxelizer::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<Mult
}
Ref<MultiMesh> Voxelizer::create_debug_multimesh() {
-
Ref<MultiMesh> mm;
mm.instance();
@@ -1155,22 +951,20 @@ Ref<MultiMesh> Voxelizer::create_debug_multimesh() {
colors.push_back(Color(1, 1, 1, 1));
for (int i = 0; i < 6; i++) {
-
Vector3 face_points[4];
for (int j = 0; j < 4; j++) {
-
float v[3];
v[0] = 1.0;
v[1] = 1 - 2 * ((j >> 1) & 1);
v[2] = v[1] * (1 - 2 * (j & 1));
for (int k = 0; k < 3; k++) {
-
- if (i < 3)
+ if (i < 3) {
face_points[j][(i + k) % 3] = v[k];
- else
+ } else {
face_points[3 - j][(i + k) % 3] = -v[k];
+ }
}
}
@@ -1211,6 +1005,7 @@ Ref<MultiMesh> Voxelizer::create_debug_multimesh() {
Transform Voxelizer::get_to_cell_space_xform() const {
return to_cell_space;
}
+
Voxelizer::Voxelizer() {
sorted = false;
color_scan_cell_width = 4;
diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h
index 1fde6237a2..3546fd7729 100644
--- a/scene/3d/voxelizer.h
+++ b/scene/3d/voxelizer.h
@@ -43,7 +43,6 @@ private:
};
struct Cell {
-
uint32_t children[8];
float albedo[3]; //albedo in RGB24
float emission[3]; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast)
diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp
index 8cf4554653..3c12d4991e 100644
--- a/scene/3d/world_environment.cpp
+++ b/scene/3d/world_environment.cpp
@@ -29,113 +29,114 @@
/*************************************************************************/
#include "world_environment.h"
+
#include "scene/main/window.h"
void WorldEnvironment::_notification(int p_what) {
-
if (p_what == Node3D::NOTIFICATION_ENTER_WORLD || p_what == Node3D::NOTIFICATION_ENTER_TREE) {
-
if (environment.is_valid()) {
- if (get_viewport()->find_world()->get_environment().is_valid()) {
+ if (get_viewport()->find_world_3d()->get_environment().is_valid()) {
WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding.");
}
- get_viewport()->find_world()->set_environment(environment);
- add_to_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ get_viewport()->find_world_3d()->set_environment(environment);
+ add_to_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
if (camera_effects.is_valid()) {
- if (get_viewport()->find_world()->get_camera_effects().is_valid()) {
+ if (get_viewport()->find_world_3d()->get_camera_effects().is_valid()) {
WARN_PRINT("World already has a camera effects (Another WorldEnvironment?), overriding.");
}
- get_viewport()->find_world()->set_camera_effects(camera_effects);
- add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ get_viewport()->find_world_3d()->set_camera_effects(camera_effects);
+ add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
} else if (p_what == Node3D::NOTIFICATION_EXIT_WORLD || p_what == Node3D::NOTIFICATION_EXIT_TREE) {
-
- if (environment.is_valid() && get_viewport()->find_world()->get_environment() == environment) {
- get_viewport()->find_world()->set_environment(Ref<Environment>());
- remove_from_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ if (environment.is_valid() && get_viewport()->find_world_3d()->get_environment() == environment) {
+ get_viewport()->find_world_3d()->set_environment(Ref<Environment>());
+ remove_from_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
- if (camera_effects.is_valid() && get_viewport()->find_world()->get_camera_effects() == camera_effects) {
- get_viewport()->find_world()->set_camera_effects(Ref<CameraEffects>());
- remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ if (camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) {
+ get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>());
+ remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
}
}
void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) {
-
- if (is_inside_tree() && environment.is_valid() && get_viewport()->find_world()->get_environment() == environment) {
- get_viewport()->find_world()->set_environment(Ref<Environment>());
- remove_from_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ if (is_inside_tree() && environment.is_valid() && get_viewport()->find_world_3d()->get_environment() == environment) {
+ get_viewport()->find_world_3d()->set_environment(Ref<Environment>());
+ remove_from_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
//clean up
}
environment = p_environment;
if (is_inside_tree() && environment.is_valid()) {
- if (get_viewport()->find_world()->get_environment().is_valid()) {
+ if (get_viewport()->find_world_3d()->get_environment().is_valid()) {
WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding.");
}
- get_viewport()->find_world()->set_environment(environment);
- add_to_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ get_viewport()->find_world_3d()->set_environment(environment);
+ add_to_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
update_configuration_warning();
}
Ref<Environment> WorldEnvironment::get_environment() const {
-
return environment;
}
void WorldEnvironment::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) {
-
- if (is_inside_tree() && camera_effects.is_valid() && get_viewport()->find_world()->get_camera_effects() == camera_effects) {
- get_viewport()->find_world()->set_camera_effects(Ref<CameraEffects>());
- remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ if (is_inside_tree() && camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) {
+ get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>());
+ remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
//clean up
}
camera_effects = p_camera_effects;
if (is_inside_tree() && camera_effects.is_valid()) {
- if (get_viewport()->find_world()->get_camera_effects().is_valid()) {
+ if (get_viewport()->find_world_3d()->get_camera_effects().is_valid()) {
WARN_PRINT("World already has an camera_effects (Another WorldEnvironment?), overriding.");
}
- get_viewport()->find_world()->set_camera_effects(camera_effects);
- add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ get_viewport()->find_world_3d()->set_camera_effects(camera_effects);
+ add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
update_configuration_warning();
}
Ref<CameraEffects> WorldEnvironment::get_camera_effects() const {
-
return camera_effects;
}
String WorldEnvironment::get_configuration_warning() const {
+ String warning = Node::get_configuration_warning();
if (!environment.is_valid()) {
- return TTR("WorldEnvironment requires its \"Environment\" property to contain an Environment to have a visible effect.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("WorldEnvironment requires its \"Environment\" property to contain an Environment to have a visible effect.");
}
- if (!is_inside_tree())
- return String();
+ if (!is_inside_tree()) {
+ return warning;
+ }
List<Node *> nodes;
- get_tree()->get_nodes_in_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id()), &nodes);
+ get_tree()->get_nodes_in_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), &nodes);
if (nodes.size() > 1) {
- return TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes).");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes).");
}
- return String();
+ return warning;
}
void WorldEnvironment::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_environment", "env"), &WorldEnvironment::set_environment);
ClassDB::bind_method(D_METHOD("get_environment"), &WorldEnvironment::get_environment);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h
index e4c9fc071d..3fd3dc0b50 100644
--- a/scene/3d/world_environment.h
+++ b/scene/3d/world_environment.h
@@ -32,9 +32,10 @@
#define SCENARIO_FX_H
#include "scene/3d/node_3d.h"
+#include "scene/resources/camera_effects.h"
+#include "scene/resources/environment.h"
class WorldEnvironment : public Node {
-
GDCLASS(WorldEnvironment, Node);
Ref<Environment> environment;
@@ -51,7 +52,7 @@ public:
void set_camera_effects(const Ref<CameraEffects> &p_camera_effects);
Ref<CameraEffects> get_camera_effects() const;
- String get_configuration_warning() const;
+ String get_configuration_warning() const override;
WorldEnvironment();
};
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index 0373114e7d..c0015aa338 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -29,7 +29,8 @@
/*************************************************************************/
#include "xr_nodes.h"
-#include "core/input/input_filter.h"
+
+#include "core/input/input.h"
#include "servers/xr/xr_interface.h"
#include "servers/xr_server.h"
@@ -55,16 +56,22 @@ void XRCamera3D::_notification(int p_what) {
};
String XRCamera3D::get_configuration_warning() const {
- if (!is_visible() || !is_inside_tree())
+ if (!is_visible() || !is_inside_tree()) {
return String();
+ }
+
+ String warning = Camera3D::get_configuration_warning();
// must be child node of XROrigin3D!
XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent());
if (origin == nullptr) {
- return TTR("XRCamera3D must have an XROrigin3D node as its parent.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("XRCamera3D must have an XROrigin3D node as its parent.");
};
- return String();
+ return warning;
};
Vector3 XRCamera3D::project_local_ray_normal(const Point2 &p_pos) const {
@@ -167,14 +174,6 @@ Vector<Plane> XRCamera3D::get_frustum() const {
return cm.get_projection_planes(get_camera_transform());
};
-XRCamera3D::XRCamera3D(){
- // nothing to do here yet for now..
-};
-
-XRCamera3D::~XRCamera3D(){
- // nothing to do here yet for now..
-};
-
////////////////////////////////////////////////////////////////////////////////////////////////////
void XRController3D::_notification(int p_what) {
@@ -206,7 +205,7 @@ void XRController3D::_notification(int p_what) {
// check button states
for (int i = 0; i < 16; i++) {
bool was_pressed = (button_states & mask) == mask;
- bool is_pressed = InputFilter::get_singleton()->is_joy_button_pressed(joy_id, i);
+ bool is_pressed = Input::get_singleton()->is_joy_button_pressed(joy_id, i);
if (!was_pressed && is_pressed) {
emit_signal("button_pressed", i);
@@ -269,11 +268,11 @@ void XRController3D::set_controller_id(int p_controller_id) {
update_configuration_warning();
};
-int XRController3D::get_controller_id(void) const {
+int XRController3D::get_controller_id() const {
return controller_id;
};
-String XRController3D::get_controller_name(void) const {
+String XRController3D::get_controller_name() const {
// get our XRServer
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, String());
@@ -306,7 +305,7 @@ bool XRController3D::is_button_pressed(int p_button) const {
return false;
};
- return InputFilter::get_singleton()->is_joy_button_pressed(joy_id, p_button);
+ return Input::get_singleton()->is_joy_button_pressed(joy_id, p_button);
};
float XRController3D::get_joystick_axis(int p_axis) const {
@@ -315,7 +314,7 @@ float XRController3D::get_joystick_axis(int p_axis) const {
return 0.0;
};
- return InputFilter::get_singleton()->get_joy_axis(joy_id, p_axis);
+ return Input::get_singleton()->get_joy_axis(joy_id, p_axis);
};
real_t XRController3D::get_rumble() const {
@@ -364,30 +363,29 @@ XRPositionalTracker::TrackerHand XRController3D::get_hand() const {
};
String XRController3D::get_configuration_warning() const {
- if (!is_visible() || !is_inside_tree())
+ if (!is_visible() || !is_inside_tree()) {
return String();
+ }
+
+ String warning = Node3D::get_configuration_warning();
// must be child node of XROrigin!
XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent());
if (origin == nullptr) {
- return TTR("XRController3D must have an XROrigin3D node as its parent.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("XRController3D must have an XROrigin3D node as its parent.");
};
if (controller_id == 0) {
- return TTR("The controller ID must not be 0 or this controller won't be bound to an actual controller.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("The controller ID must not be 0 or this controller won't be bound to an actual controller.");
};
- return String();
-};
-
-XRController3D::XRController3D() {
- controller_id = 1;
- is_active = true;
- button_states = 0;
-};
-
-XRController3D::~XRController3D(){
- // nothing to do here yet for now..
+ return warning;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -443,7 +441,6 @@ void XRAnchor3D::_notification(int p_what) {
};
void XRAnchor3D::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("set_anchor_id", "anchor_id"), &XRAnchor3D::set_anchor_id);
ClassDB::bind_method(D_METHOD("get_anchor_id"), &XRAnchor3D::get_anchor_id);
ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_id", PROPERTY_HINT_RANGE, "0,32,1"), "set_anchor_id", "get_anchor_id");
@@ -465,7 +462,7 @@ void XRAnchor3D::set_anchor_id(int p_anchor_id) {
update_configuration_warning();
};
-int XRAnchor3D::get_anchor_id(void) const {
+int XRAnchor3D::get_anchor_id() const {
return anchor_id;
};
@@ -473,7 +470,7 @@ Vector3 XRAnchor3D::get_size() const {
return size;
};
-String XRAnchor3D::get_anchor_name(void) const {
+String XRAnchor3D::get_anchor_name() const {
// get our XRServer
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, String());
@@ -491,20 +488,29 @@ bool XRAnchor3D::get_is_active() const {
};
String XRAnchor3D::get_configuration_warning() const {
- if (!is_visible() || !is_inside_tree())
+ if (!is_visible() || !is_inside_tree()) {
return String();
+ }
+
+ String warning = Node3D::get_configuration_warning();
// must be child node of XROrigin3D!
XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent());
if (origin == nullptr) {
- return TTR("XRAnchor3D must have an XROrigin3D node as its parent.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("XRAnchor3D must have an XROrigin3D node as its parent.");
};
if (anchor_id == 0) {
- return TTR("The anchor ID must not be 0 or this anchor won't be bound to an actual anchor.");
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("The anchor ID must not be 0 or this anchor won't be bound to an actual anchor.");
};
- return String();
+ return warning;
};
Plane XRAnchor3D::get_plane() const {
@@ -520,25 +526,23 @@ Ref<Mesh> XRAnchor3D::get_mesh() const {
return mesh;
}
-XRAnchor3D::XRAnchor3D() {
- anchor_id = 1;
- is_active = true;
-};
-
-XRAnchor3D::~XRAnchor3D(){
- // nothing to do here yet for now..
-};
-
////////////////////////////////////////////////////////////////////////////////////////////////////
String XROrigin3D::get_configuration_warning() const {
- if (!is_visible() || !is_inside_tree())
+ if (!is_visible() || !is_inside_tree()) {
return String();
+ }
+
+ String warning = Node3D::get_configuration_warning();
- if (tracked_camera == nullptr)
- return TTR("XROrigin3D requires an XRCamera3D child node.");
+ if (tracked_camera == nullptr) {
+ if (!warning.empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("XROrigin3D requires an XRCamera3D child node.");
+ }
- return String();
+ return warning;
};
void XROrigin3D::_bind_methods() {
@@ -611,11 +615,3 @@ void XROrigin3D::_notification(int p_what) {
}
}
};
-
-XROrigin3D::XROrigin3D() {
- tracked_camera = nullptr;
-};
-
-XROrigin3D::~XROrigin3D(){
- // nothing to do here yet for now..
-};
diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h
index a2f16545d1..751b2b68cb 100644
--- a/scene/3d/xr_nodes.h
+++ b/scene/3d/xr_nodes.h
@@ -44,22 +44,21 @@
XRCamera is a subclass of camera which will register itself with its parent XROrigin and as a result is automatically positioned
*/
class XRCamera3D : public Camera3D {
-
GDCLASS(XRCamera3D, Camera3D);
protected:
void _notification(int p_what);
public:
- String get_configuration_warning() const;
+ String get_configuration_warning() const override;
- virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const;
- virtual Point2 unproject_position(const Vector3 &p_pos) const;
- virtual Vector3 project_position(const Point2 &p_point, float p_z_depth) const;
- virtual Vector<Plane> get_frustum() const;
+ virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const override;
+ virtual Point2 unproject_position(const Vector3 &p_pos) const override;
+ virtual Vector3 project_position(const Point2 &p_point, float p_z_depth) const override;
+ virtual Vector<Plane> get_frustum() const override;
- XRCamera3D();
- ~XRCamera3D();
+ XRCamera3D() {}
+ ~XRCamera3D() {}
};
/*
@@ -69,13 +68,12 @@ public:
*/
class XRController3D : public Node3D {
-
GDCLASS(XRController3D, Node3D);
private:
- int controller_id;
- bool is_active;
- int button_states;
+ int controller_id = 1;
+ bool is_active = true;
+ int button_states = 0;
Ref<Mesh> mesh;
protected:
@@ -84,8 +82,8 @@ protected:
public:
void set_controller_id(int p_controller_id);
- int get_controller_id(void) const;
- String get_controller_name(void) const;
+ int get_controller_id() const;
+ String get_controller_name() const;
int get_joystick_id() const;
bool is_button_pressed(int p_button) const;
@@ -97,12 +95,12 @@ public:
bool get_is_active() const;
XRPositionalTracker::TrackerHand get_hand() const;
- Ref<Mesh> get_mesh(void) const;
+ Ref<Mesh> get_mesh() const;
- String get_configuration_warning() const;
+ String get_configuration_warning() const override;
- XRController3D();
- ~XRController3D();
+ XRController3D() {}
+ ~XRController3D() {}
};
/*
@@ -114,8 +112,8 @@ class XRAnchor3D : public Node3D {
GDCLASS(XRAnchor3D, Node3D);
private:
- int anchor_id;
- bool is_active;
+ int anchor_id = 1;
+ bool is_active = true;
Vector3 size;
Ref<Mesh> mesh;
@@ -125,20 +123,20 @@ protected:
public:
void set_anchor_id(int p_anchor_id);
- int get_anchor_id(void) const;
- String get_anchor_name(void) const;
+ int get_anchor_id() const;
+ String get_anchor_name() const;
bool get_is_active() const;
Vector3 get_size() const;
Plane get_plane() const;
- Ref<Mesh> get_mesh(void) const;
+ Ref<Mesh> get_mesh() const;
- String get_configuration_warning() const;
+ String get_configuration_warning() const override;
- XRAnchor3D();
- ~XRAnchor3D();
+ XRAnchor3D() {}
+ ~XRAnchor3D() {}
};
/*
@@ -150,18 +148,17 @@ public:
This node will automatically locate any camera child nodes and update its position while our XRController3D node will handle tracked controllers.
*/
class XROrigin3D : public Node3D {
-
GDCLASS(XROrigin3D, Node3D);
private:
- XRCamera3D *tracked_camera;
+ XRCamera3D *tracked_camera = nullptr;
protected:
void _notification(int p_what);
static void _bind_methods();
public:
- String get_configuration_warning() const;
+ String get_configuration_warning() const override;
void set_tracked_camera(XRCamera3D *p_tracked_camera);
void clear_tracked_camera_if(XRCamera3D *p_tracked_camera);
@@ -169,8 +166,8 @@ public:
float get_world_scale() const;
void set_world_scale(float p_world_scale);
- XROrigin3D();
- ~XROrigin3D();
+ XROrigin3D() {}
+ ~XROrigin3D() {}
};
#endif /* XR_NODES_H */