diff options
Diffstat (limited to 'scene/3d')
82 files changed, 4006 insertions, 3502 deletions
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index 5b02a91793..a024757927 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,29 +165,30 @@ 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; if (E->get().rc == 0) { - 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 (E->get().in_tree) { emit_signal(SceneStringNames::get_singleton()->body_exited, obj); + } } eraseit = true; @@ -210,15 +197,15 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_area_shape); } - if (eraseit) + 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,19 +214,19 @@ 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) + 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); } @@ -251,25 +238,24 @@ void Area3D::_clear_monitoring() { } { - 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) + 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); } @@ -280,35 +266,33 @@ void Area3D::_clear_monitoring() { } } } -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 { - PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), NULL, StringName()); - PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), NULL, StringName()); + PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), nullptr, StringName()); + PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), nullptr, StringName()); _clear_monitoring(); } } 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 +304,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 +318,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 +339,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,24 +351,24 @@ 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; if (E->get().rc == 0) { - 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)); @@ -404,20 +383,19 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i emit_signal(SceneStringNames::get_singleton()->area_shape_exited, objid, obj, p_area_shape, p_self_shape); } - if (eraseit) + if (eraseit) { area_map.erase(E); + } } locked = false; } bool Area3D::is_monitoring() const { - return monitoring; } -Array Area3D::get_overlapping_bodies() const { - +TypedArray<Node3D> Area3D::get_overlapping_bodies() const { ERR_FAIL_COND_V(!monitoring, Array()); Array ret; ret.resize(body_map.size()); @@ -435,11 +413,11 @@ Array 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 +425,10 @@ void Area3D::set_monitorable(bool p_enable) { } bool Area3D::is_monitorable() const { - return monitorable; } -Array Area3D::get_overlapping_areas() const { - +TypedArray<Area3D> Area3D::get_overlapping_areas() const { ERR_FAIL_COND_V(!monitoring, Array()); Array ret; ret.resize(area_map.size()); @@ -470,89 +446,82 @@ Array 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 +531,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 +552,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 +693,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 ff6c0b6b08..98f337d3e4 100644 --- a/scene/3d/area_3d.h +++ b/scene/3d/area_3d.h @@ -35,7 +35,6 @@ #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; @@ -184,8 +181,8 @@ public: void set_collision_layer_bit(int p_bit, bool p_value); bool get_collision_layer_bit(int p_bit) const; - Array get_overlapping_bodies() const; - Array get_overlapping_areas() const; //function for script + TypedArray<Node3D> get_overlapping_bodies() const; + TypedArray<Area3D> get_overlapping_areas() const; //function for script bool overlaps_area(Node *p_area) const; bool overlaps_body(Node *p_body) const; diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 9f5170fa98..6e4db8f382 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -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,37 +382,40 @@ 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]; int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, false, true); - Area3D *area = NULL; + 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 1cce0c77d5..9f261c54b4 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]; @@ -82,7 +80,7 @@ private: Output() { filter_gain = 0; - viewport = NULL; + viewport = nullptr; reverb_bus_index = -1; bus_index = -1; } diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index 05e3f3fefa..a41eaf9da0 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/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 = NULL; -BakedLightmap::BakeStepFunc BakedLightmap::bake_step_function = NULL; -BakedLightmap::BakeEndFunc BakedLightmap::bake_end_function = NULL; +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_ALL, -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_ALL, 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_ALL, 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..08098c3d5d 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/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; 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; 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; - 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..fec59217d2 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; diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 7980c15f89..7ffca4bd9e 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -39,16 +39,13 @@ 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 +75,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 +87,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 +108,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(); @@ -138,25 +132,24 @@ void Camera3D::_notification(int p_what) { if (viewport) { viewport->_camera_remove(this); - viewport = NULL; + viewport = nullptr; } } 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 +157,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 +170,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 +188,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 +213,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,13 +229,13 @@ 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(NULL); + get_viewport()->_camera_set(nullptr); if (p_enable_next) { get_viewport()->_camera_make_next_current(this); @@ -258,27 +252,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 +276,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 +288,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 +295,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,7 +317,6 @@ 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); @@ -344,10 +329,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 +347,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 +372,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 +381,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(); @@ -413,50 +399,31 @@ Vector3 Camera3D::project_position(const Point2 &p_point, float p_z_depth) const return get_camera_transform().xform(p); } -/* -void Camera::_camera_make_current(Node *p_camera) { - - - if (p_camera==this) { - RenderingServer::get_singleton()->viewport_attach_camera(viewport_id,camera); - active=true; - } else { - if (active && p_camera==NULL) { - //detech camera because no one else will claim it - RenderingServer::get_singleton()->viewport_attach_camera(viewport_id,RID()); - } - active=false; - } -} -*/ - 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; } @@ -468,14 +435,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) { @@ -492,7 +458,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); @@ -569,17 +534,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; } @@ -588,12 +550,10 @@ Vector2 Camera3D::get_frustum_offset() const { } float Camera3D::get_zfar() const { - return far; } Camera3D::Projection Camera3D::get_projection() const { - return mode; } @@ -633,7 +593,6 @@ void Camera3D::set_cull_mask(uint32_t p_layers) { } uint32_t Camera3D::get_cull_mask() const { - return layers; } @@ -652,27 +611,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; } @@ -682,20 +639,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; @@ -703,10 +658,10 @@ Camera3D::Camera3D() { near = 0; far = 0; current = false; - viewport = NULL; + 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; @@ -720,7 +675,6 @@ Camera3D::Camera3D() { } Camera3D::~Camera3D() { - RenderingServer::get_singleton()->free(camera); } @@ -729,11 +683,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; } @@ -741,12 +696,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; @@ -754,13 +709,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(); @@ -800,9 +754,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(); @@ -814,90 +768,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); @@ -937,6 +879,7 @@ void ClippedCamera3D::_bind_methods() { BIND_ENUM_CONSTANT(CLIP_PROCESS_PHYSICS); BIND_ENUM_CONSTANT(CLIP_PROCESS_IDLE); } + ClippedCamera3D::ClippedCamera3D() { margin = 0; clip_offset = 0; @@ -949,6 +892,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..138b1b8a7a 100644 --- a/scene/3d/camera_3d.h +++ b/scene/3d/camera_3d.h @@ -37,7 +37,6 @@ #include "scene/resources/environment.h" class Camera3D : public Node3D { - GDCLASS(Camera3D, Node3D); public: @@ -184,7 +183,6 @@ VARIANT_ENUM_CAST(Camera3D::KeepAspect); VARIANT_ENUM_CAST(Camera3D::DopplerTracking); class ClippedCamera3D : public Camera3D { - GDCLASS(ClippedCamera3D, Camera3D); public: diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 6ee0512546..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), NULL); + 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 6a70f56caa..8bcbef0e98 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 { @@ -56,7 +54,7 @@ class CollisionObject3D : public Node3D { ShapeData() { disabled = false; - owner = NULL; + owner = nullptr; } }; diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp index 982205137b..e2d11c740a 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); } @@ -112,13 +110,12 @@ void CollisionPolygon3D::_notification(int p_what) { parent->remove_shape_owner(owner_id); } owner_id = 0; - parent = NULL; + parent = nullptr; } break; } } 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,7 +156,6 @@ bool CollisionPolygon3D::is_disabled() const { } String CollisionPolygon3D::get_configuration_warning() const { - 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."); } @@ -178,8 +170,8 @@ String CollisionPolygon3D::get_configuration_warning() const { 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,11 +189,10 @@ void CollisionPolygon3D::_bind_methods() { } CollisionPolygon3D::CollisionPolygon3D() { - aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); depth = 1.0; set_notify_local_transform(true); - parent = NULL; + parent = nullptr; owner_id = 0; disabled = false; } diff --git a/scene/3d/collision_polygon_3d.h b/scene/3d/collision_polygon_3d.h index 256aee3d7e..0cd9aee111 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: diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index 6aecfd08cc..56367e9bdd 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -45,20 +45,17 @@ //TODO: Implement CylinderShape and HeightMapShape? void CollisionShape3D::make_convex_from_brothers() { - Node *p = get_parent(); - if (!p) + if (!p) { return; + } 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); } @@ -68,15 +65,14 @@ void CollisionShape3D::make_convex_from_brothers() { 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) { @@ -105,18 +101,16 @@ void CollisionShape3D::_notification(int p_what) { parent->remove_shape_owner(owner_id); } owner_id = 0; - parent = NULL; + parent = nullptr; } break; } } void CollisionShape3D::resource_changed(RES res) { - update_gizmo(); } String CollisionShape3D::get_configuration_warning() const { - 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."); } @@ -137,7 +131,6 @@ String CollisionShape3D::get_configuration_warning() const { } 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); @@ -154,7 +147,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 +164,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,23 +183,22 @@ 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 = NULL; - parent = NULL; + debug_shape = nullptr; + parent = nullptr; owner_id = 0; set_notify_local_transform(true); } CollisionShape3D::~CollisionShape3D() { - if (!shape.is_null()) + if (!shape.is_null()) { shape->unregister_owner(this); + } //RenderingServer::get_singleton()->free(indicator); } @@ -217,12 +207,13 @@ void CollisionShape3D::_update_debug_shape() { if (debug_shape) { debug_shape->queue_delete(); - debug_shape = NULL; + debug_shape = nullptr; } 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..4ed2f4007b 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"); diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index 2226b0ed83..4244a11592 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,7 +189,6 @@ bool CPUParticles3D::get_fractional_delta() const { } String CPUParticles3D::get_configuration_warning() const { - String warnings; bool mesh_found = false; @@ -208,26 +197,28 @@ String CPUParticles3D::get_configuration_warning() const { if (get_mesh().is_valid()) { mesh_found = true; for (int j = 0; j < get_mesh()->get_surface_count(); j++) { - anim_material_found = Object::cast_to<ShaderMaterial>(get_mesh()->surface_get_material(j).ptr()) != NULL; + anim_material_found = Object::cast_to<ShaderMaterial>(get_mesh()->surface_get_material(j).ptr()) != nullptr; StandardMaterial3D *spat = Object::cast_to<StandardMaterial3D>(get_mesh()->surface_get_material(j).ptr()); anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); } } - anim_material_found = anim_material_found || Object::cast_to<ShaderMaterial>(get_material_override().ptr()) != NULL; + anim_material_found = anim_material_found || Object::cast_to<ShaderMaterial>(get_material_override().ptr()) != nullptr; StandardMaterial3D *spat = Object::cast_to<StandardMaterial3D>(get_material_override().ptr()); 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; @@ -804,7 +770,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 +839,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 +866,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 +922,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 +965,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); @@ -1022,7 +986,7 @@ void CPUParticles3D::_update_particle_data_buffer() { int pc = particles.size(); int *ow; - int *order = NULL; + int *order = nullptr; float *w = particle_data.ptrw(); const Particle *r = particles.ptr(); @@ -1045,7 +1009,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 +1025,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 +1069,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 +1092,6 @@ void CPUParticles3D::_set_redraw(bool p_redraw) { } void CPUParticles3D::_update_render_thread() { - MutexLock lock(update_mutex); if (can_update) { @@ -1139,13 +1101,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 +1116,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 +1126,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 +1136,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 +1164,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 +1182,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 +1212,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 +1234,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); @@ -1478,7 +1438,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..2afb6846c0 100644 --- a/scene/3d/cpu_particles_3d.h +++ b/scene/3d/cpu_particles_3d.h @@ -122,7 +122,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); } }; diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp new file mode 100644 index 0000000000..fb72e10171 --- /dev/null +++ b/scene/3d/decal.cpp @@ -0,0 +1,241 @@ +/*************************************************************************/ +/* decal.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 "decal.h" + +void Decal::set_extents(const Vector3 &p_extents) { + extents = p_extents; + RS::get_singleton()->decal_set_extents(decal, p_extents); + update_gizmo(); + _change_notify("extents"); +} + +Vector3 Decal::get_extents() const { + return extents; +} + +void Decal::set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture) { + ERR_FAIL_INDEX(p_type, TEXTURE_MAX); + textures[p_type] = 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]; +} + +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; +} + +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; +} + +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; +} + +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; +} + +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; +} + +void Decal::set_modulate(Color p_modulate) { + modulate = p_modulate; + RS::get_singleton()->decal_set_modulate(decal, p_modulate); +} + +Color Decal::get_modulate() const { + return modulate; +} + +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; +} + +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; +} + +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; +} + +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 { + 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); + + ClassDB::bind_method(D_METHOD("set_texture", "type", "texture"), &Decal::set_texture); + ClassDB::bind_method(D_METHOD("get_texture", "type"), &Decal::get_texture); + + ClassDB::bind_method(D_METHOD("set_emission_energy", "energy"), &Decal::set_emission_energy); + ClassDB::bind_method(D_METHOD("get_emission_energy"), &Decal::get_emission_energy); + + ClassDB::bind_method(D_METHOD("set_albedo_mix", "energy"), &Decal::set_albedo_mix); + ClassDB::bind_method(D_METHOD("get_albedo_mix"), &Decal::get_albedo_mix); + + ClassDB::bind_method(D_METHOD("set_modulate", "color"), &Decal::set_modulate); + ClassDB::bind_method(D_METHOD("get_modulate"), &Decal::get_modulate); + + ClassDB::bind_method(D_METHOD("set_upper_fade", "fade"), &Decal::set_upper_fade); + ClassDB::bind_method(D_METHOD("get_upper_fade"), &Decal::get_upper_fade); + + ClassDB::bind_method(D_METHOD("set_lower_fade", "fade"), &Decal::set_lower_fade); + ClassDB::bind_method(D_METHOD("get_lower_fade"), &Decal::get_lower_fade); + + ClassDB::bind_method(D_METHOD("set_normal_fade", "fade"), &Decal::set_normal_fade); + ClassDB::bind_method(D_METHOD("get_normal_fade"), &Decal::get_normal_fade); + + ClassDB::bind_method(D_METHOD("set_enable_distance_fade", "enable"), &Decal::set_enable_distance_fade); + ClassDB::bind_method(D_METHOD("is_distance_fade_enabled"), &Decal::is_distance_fade_enabled); + + ClassDB::bind_method(D_METHOD("set_distance_fade_begin", "distance"), &Decal::set_distance_fade_begin); + ClassDB::bind_method(D_METHOD("get_distance_fade_begin"), &Decal::get_distance_fade_begin); + + ClassDB::bind_method(D_METHOD("set_distance_fade_length", "distance"), &Decal::set_distance_fade_length); + ClassDB::bind_method(D_METHOD("get_distance_fade_length"), &Decal::get_distance_fade_length); + + ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &Decal::set_cull_mask); + ClassDB::bind_method(D_METHOD("get_cull_mask"), &Decal::get_cull_mask); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater"), "set_extents", "get_extents"); + ADD_GROUP("Textures", "texture_"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ALBEDO); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_NORMAL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_orm", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ORM); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_emission", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION); + ADD_GROUP("Parameters", ""); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_emission_energy", "get_emission_energy"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "albedo_mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_albedo_mix", "get_albedo_mix"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_fade", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_normal_fade", "get_normal_fade"); + ADD_GROUP("Vertical Fade", ""); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "upper_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_upper_fade", "get_upper_fade"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lower_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_lower_fade", "get_lower_fade"); + ADD_GROUP("Distance Fade", "distance_fade_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin"), "set_distance_fade_begin", "get_distance_fade_begin"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length"), "set_distance_fade_length", "get_distance_fade_length"); + ADD_GROUP("Cull Mask", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); + + BIND_ENUM_CONSTANT(TEXTURE_ALBEDO); + BIND_ENUM_CONSTANT(TEXTURE_NORMAL); + BIND_ENUM_CONSTANT(TEXTURE_ORM); + BIND_ENUM_CONSTANT(TEXTURE_EMISSION); + BIND_ENUM_CONSTANT(TEXTURE_MAX); +} + +Decal::Decal() { + extents = Vector3(1, 1, 1); + emission_energy = 1.0; + modulate = Color(1, 1, 1, 1); + albedo_mix = 1.0; + cull_mask = (1 << 20) - 1; + upper_fade = 0.3; + lower_fade = 0.3; + normal_fade = 0; + distance_fade_enabled = false; + distance_fade_begin = 10; + distance_fade_length = 1; + + decal = RenderingServer::get_singleton()->decal_create(); + RS::get_singleton()->instance_set_base(get_instance(), decal); +} + +Decal::~Decal() { + RS::get_singleton()->free(decal); +} diff --git a/scene/3d/decal.h b/scene/3d/decal.h new file mode 100644 index 0000000000..665444829d --- /dev/null +++ b/scene/3d/decal.h @@ -0,0 +1,114 @@ +/*************************************************************************/ +/* decal.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 DECAL_H +#define DECAL_H + +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/texture.h" +#include "servers/rendering_server.h" + +class Decal : public VisualInstance3D { + GDCLASS(Decal, VisualInstance3D); + +public: + enum DecalTexture { + TEXTURE_ALBEDO, + TEXTURE_NORMAL, + TEXTURE_ORM, + TEXTURE_EMISSION, + TEXTURE_MAX + }; + +private: + RID decal; + Vector3 extents; + Ref<Texture2D> textures[TEXTURE_MAX]; + float emission_energy; + float albedo_mix; + Color modulate; + uint32_t cull_mask; + float normal_fade; + float upper_fade; + float lower_fade; + bool distance_fade_enabled; + float distance_fade_begin; + float distance_fade_length; + +protected: + static void _bind_methods(); + +public: + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + void set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture); + Ref<Texture2D> get_texture(DecalTexture p_type) const; + + void set_emission_energy(float p_energy); + float get_emission_energy() const; + + void set_albedo_mix(float p_mix); + float get_albedo_mix() const; + + void set_modulate(Color p_modulate); + Color get_modulate() const; + + void set_upper_fade(float p_energy); + float get_upper_fade() const; + + void set_lower_fade(float p_fade); + float get_lower_fade() const; + + void set_normal_fade(float p_fade); + float get_normal_fade() const; + + void set_enable_distance_fade(bool p_enable); + bool is_distance_fade_enabled() const; + + void set_distance_fade_begin(float p_distance); + float get_distance_fade_begin() const; + + void set_distance_fade_length(float p_length); + float get_distance_fade_length() const; + + 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; + + Decal(); + ~Decal(); +}; + +VARIANT_ENUM_CAST(Decal::DecalTexture); + +#endif // DECAL_H diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index a46cd90612..1b6f9b45b9 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -101,15 +101,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 +121,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 +217,6 @@ bool GIProbeData::is_using_two_bounces() const { } RID GIProbeData::get_rid() const { - return probe; } @@ -283,7 +287,6 @@ void GIProbeData::_bind_methods() { } GIProbeData::GIProbeData() { - ao = 0.0; ao_size = 0.5; dynamic_range = 4; @@ -293,12 +296,12 @@ GIProbeData::GIProbeData() { propagation = 0.7; anisotropy_strength = 0.5; interior = false; + use_two_bounces = false; probe = RS::get_singleton()->gi_probe_create(); } GIProbeData::~GIProbeData() { - RS::get_singleton()->free(probe); } @@ -306,7 +309,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 { @@ -317,41 +319,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(); @@ -371,16 +366,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(); @@ -402,9 +395,9 @@ void GIProbe::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { } } -GIProbe::BakeBeginFunc GIProbe::bake_begin_function = NULL; -GIProbe::BakeStepFunc GIProbe::bake_step_function = NULL; -GIProbe::BakeEndFunc GIProbe::bake_end_function = NULL; +GIProbe::BakeBeginFunc GIProbe::bake_begin_function = nullptr; +GIProbe::BakeStepFunc GIProbe::bake_step_function = nullptr; +GIProbe::BakeEndFunc GIProbe::bake_end_function = nullptr; Vector3i GIProbe::get_estimated_cell_size() const { static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 }; @@ -415,9 +408,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]; @@ -431,8 +424,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; @@ -450,7 +443,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())); } @@ -482,11 +474,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")); @@ -510,22 +502,18 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { } void GIProbe::_debug_bake() { - - bake(NULL, true); + 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 { - if (RenderingServer::get_singleton()->is_low_end()) { return TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead."); } @@ -533,7 +521,6 @@ String GIProbe::get_configuration_warning() const { } 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); @@ -559,7 +546,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 c00ee2cb73..b7abfbd01b 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; @@ -161,7 +160,7 @@ public: Vector3 get_extents() const; Vector3i get_estimated_cell_size() const; - void bake(Node *p_from_node = NULL, bool p_create_visual_debug = false); + 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; diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index 8646d4f290..c4480e3ed2 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,149 @@ 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 { - 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) { - 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 +204,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,7 +228,6 @@ 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."); } @@ -253,35 +241,40 @@ String GPUParticles3D::get_configuration_warning() const { if (draw_passes[i].is_valid()) { meshes_found = true; for (int j = 0; j < draw_passes[i]->get_surface_count(); j++) { - anim_material_found = Object::cast_to<ShaderMaterial>(draw_passes[i]->surface_get_material(j).ptr()) != NULL; + anim_material_found = Object::cast_to<ShaderMaterial>(draw_passes[i]->surface_get_material(j).ptr()) != nullptr; 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; + } } } - anim_material_found = anim_material_found || Object::cast_to<ShaderMaterial>(get_material_override().ptr()) != NULL; + anim_material_found = anim_material_found || Object::cast_to<ShaderMaterial>(get_material_override().ptr()) != nullptr; StandardMaterial3D *spat = Object::cast_to<StandardMaterial3D>(get_material_override().ptr()); 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 +283,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()) { @@ -312,12 +302,10 @@ void GPUParticles3D::_validate_property(PropertyInfo &property) const { } 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,7 +313,6 @@ 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); @@ -341,7 +328,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); @@ -403,7 +389,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); } @@ -415,7 +400,6 @@ void GPUParticles3D::_bind_methods() { } GPUParticles3D::GPUParticles3D() { - particles = RS::get_singleton()->particles_create(); set_base(particles); one_shot = false; // Needed so that set_emitting doesn't access uninitialized values @@ -436,6 +420,5 @@ GPUParticles3D::GPUParticles3D() { } GPUParticles3D::~GPUParticles3D() { - RS::get_singleton()->free(particles); } 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..7c9e8851a2 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; diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index be3b369724..9270b548b7 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -35,12 +35,10 @@ #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,65 +58,58 @@ 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); - if (type == RenderingServer::LIGHT_SPOT) { + if (type == RenderingServer::LIGHT_SPOT || type == RenderingServer::LIGHT_OMNI) { 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,7 +139,6 @@ AABB Light3D::get_aabb() const { } Vector<Face3> Light3D::get_faces(uint32_t p_usage_flags) const { - return Vector<Face3>(); } @@ -166,10 +151,21 @@ Light3D::BakeMode Light3D::get_bake_mode() const { return bake_mode; } -void Light3D::_update_visibility() { +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); + update_configuration_warning(); +} + +Ref<Texture2D> Light3D::get_projector() const { + return projector; +} - if (!is_inside_tree()) +void Light3D::_update_visibility() { + if (!is_inside_tree()) { return; + } bool editor_ok = true; @@ -193,9 +189,7 @@ void Light3D::_update_visibility() { } void Light3D::_notification(int p_what) { - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - _update_visibility(); } @@ -205,25 +199,29 @@ 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; + } + + if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_projector") { + property.usage = 0; + } - if (RenderingServer::get_singleton()->is_low_end() && property.name == "shadow_contact") { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + if (get_light_type() != RS::LIGHT_DIRECTIONAL && property.name == "light_angular_distance") { + property.usage = 0; } } 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); @@ -251,10 +249,16 @@ void Light3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bake_mode", "bake_mode"), &Light3D::set_bake_mode); ClassDB::bind_method(D_METHOD("get_bake_mode"), &Light3D::get_bake_mode); + ClassDB::bind_method(D_METHOD("set_projector", "projector"), &Light3D::set_projector); + ClassDB::bind_method(D_METHOD("get_projector"), &Light3D::get_projector); + ADD_GROUP("Light", "light_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_ENERGY); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_projector", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_projector", "get_projector"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_size", PROPERTY_HINT_RANGE, "0,64,0.01,or_greater"), "set_param", "get_param", PARAM_SIZE); + 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"); @@ -262,9 +266,11 @@ void Light3D::_bind_methods() { ADD_GROUP("Shadow", "shadow_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_shadow_color", "get_shadow_color"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_contact", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_CONTACT_SHADOW_SIZE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BIAS); + 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_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"); ADD_GROUP("", ""); @@ -273,10 +279,10 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_INDIRECT_ENERGY); BIND_ENUM_CONSTANT(PARAM_SPECULAR); BIND_ENUM_CONSTANT(PARAM_RANGE); + BIND_ENUM_CONSTANT(PARAM_SIZE); BIND_ENUM_CONSTANT(PARAM_ATTENUATION); BIND_ENUM_CONSTANT(PARAM_SPOT_ANGLE); BIND_ENUM_CONSTANT(PARAM_SPOT_ATTENUATION); - BIND_ENUM_CONSTANT(PARAM_CONTACT_SHADOW_SIZE); BIND_ENUM_CONSTANT(PARAM_SHADOW_MAX_DISTANCE); BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET); BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET); @@ -284,7 +290,9 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_SHADOW_FADE_START); BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS); BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS); - BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE); + BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE); + BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR); + BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS); BIND_ENUM_CONSTANT(PARAM_MAX); BIND_ENUM_CONSTANT(BAKE_DISABLED); @@ -293,12 +301,17 @@ void Light3D::_bind_methods() { } 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: { }; } @@ -318,44 +331,45 @@ Light3D::Light3D(RenderingServer::LightType p_type) { set_param(PARAM_INDIRECT_ENERGY, 1); set_param(PARAM_SPECULAR, 0.5); set_param(PARAM_RANGE, 5); + set_param(PARAM_SIZE, 0); set_param(PARAM_ATTENUATION, 1); set_param(PARAM_SPOT_ANGLE, 45); set_param(PARAM_SPOT_ATTENUATION, 1); - set_param(PARAM_CONTACT_SHADOW_SIZE, 0); set_param(PARAM_SHADOW_MAX_DISTANCE, 0); set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1); set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2); set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5); set_param(PARAM_SHADOW_FADE_START, 0.8); - set_param(PARAM_SHADOW_NORMAL_BIAS, 0.0); - set_param(PARAM_SHADOW_BIAS, 0.15); + set_param(PARAM_SHADOW_PANCAKE_SIZE, 20.0); + set_param(PARAM_SHADOW_BLUR, 1.0); + 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_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; } @@ -365,23 +379,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); @@ -392,16 +402,15 @@ 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); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE); ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_depth_range", PROPERTY_HINT_ENUM, "Stable,Optimized"), "set_shadow_depth_range", "get_shadow_depth_range"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_pancake_size", PROPERTY_HINT_EXP_RANGE, "0,1024,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_PANCAKE_SIZE); BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL); BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS); @@ -413,31 +422,39 @@ void DirectionalLight3D::_bind_methods() { DirectionalLight3D::DirectionalLight3D() : Light3D(RenderingServer::LIGHT_DIRECTIONAL) { - - set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8); - set_param(PARAM_SHADOW_BIAS, 0.1); set_param(PARAM_SHADOW_MAX_DISTANCE, 100); set_param(PARAM_SHADOW_FADE_START, 0.8); - set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25); + // 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; } -void OmniLight3D::_bind_methods() { +String OmniLight3D::get_configuration_warning() const { + String warning = Light3D::get_configuration_warning(); + + if (!has_shadow() && get_projector().is_valid()) { + if (warning != String()) { + warning += "\n\n"; + } + warning += TTR("Projector texture only works with shadows active."); + } + + return warning; +} +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); @@ -452,8 +469,10 @@ 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 { @@ -467,11 +486,17 @@ String SpotLight3D::get_configuration_warning() const { warning += TTR("A SpotLight3D with an angle wider than 90 degrees cannot cast shadows."); } + if (!has_shadow() && get_projector().is_valid()) { + if (warning != String()) { + warning += "\n\n"; + } + warning += TTR("Projector texture only works with shadows active."); + } + return warning; } 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 197e5854ec..f16773f6ae 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -36,7 +36,6 @@ #include "servers/rendering_server.h" class Light3D : public VisualInstance3D { - GDCLASS(Light3D, VisualInstance3D); OBJ_CATEGORY("3D Light Nodes"); @@ -46,10 +45,10 @@ public: PARAM_INDIRECT_ENERGY = RS::LIGHT_PARAM_INDIRECT_ENERGY, PARAM_SPECULAR = RS::LIGHT_PARAM_SPECULAR, PARAM_RANGE = RS::LIGHT_PARAM_RANGE, + PARAM_SIZE = RS::LIGHT_PARAM_SIZE, PARAM_ATTENUATION = RS::LIGHT_PARAM_ATTENUATION, PARAM_SPOT_ANGLE = RS::LIGHT_PARAM_SPOT_ANGLE, PARAM_SPOT_ATTENUATION = RS::LIGHT_PARAM_SPOT_ATTENUATION, - PARAM_CONTACT_SHADOW_SIZE = RS::LIGHT_PARAM_CONTACT_SHADOW_SIZE, PARAM_SHADOW_MAX_DISTANCE = RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE, PARAM_SHADOW_SPLIT_1_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET, PARAM_SHADOW_SPLIT_2_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET, @@ -57,7 +56,9 @@ public: PARAM_SHADOW_FADE_START = RS::LIGHT_PARAM_SHADOW_FADE_START, PARAM_SHADOW_NORMAL_BIAS = RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS, PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS, - PARAM_SHADOW_BIAS_SPLIT_SCALE = RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, + PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE, + PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR, + PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS, PARAM_MAX = RS::LIGHT_PARAM_MAX }; @@ -79,6 +80,7 @@ private: bool editor_only; void _update_visibility(); BakeMode bake_mode; + Ref<Texture2D> projector; // bind helpers @@ -123,6 +125,9 @@ public: void set_bake_mode(BakeMode p_mode); BakeMode get_bake_mode() const; + 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; @@ -134,7 +139,6 @@ VARIANT_ENUM_CAST(Light3D::Param); VARIANT_ENUM_CAST(Light3D::BakeMode); class DirectionalLight3D : public Light3D { - GDCLASS(DirectionalLight3D, Light3D); public: @@ -174,7 +178,6 @@ VARIANT_ENUM_CAST(DirectionalLight3D::ShadowMode) VARIANT_ENUM_CAST(DirectionalLight3D::ShadowDepthRange) class OmniLight3D : public Light3D { - GDCLASS(OmniLight3D, Light3D); public: @@ -194,13 +197,14 @@ public: void set_shadow_mode(ShadowMode p_mode); ShadowMode get_shadow_mode() const; + virtual String get_configuration_warning() const; + OmniLight3D(); }; VARIANT_ENUM_CAST(OmniLight3D::ShadowMode) class SpotLight3D : public Light3D { - GDCLASS(SpotLight3D, Light3D); protected: 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 f352eb24b1..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,45 +106,42 @@ 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(NULL); + get_viewport()->_listener_set(nullptr); get_viewport()->_listener_make_next_current(this); } } 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 30aabf6e00..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()) - return NULL; + if (mesh.is_null()) { + return nullptr; + } Ref<Shape3D> shape = mesh->create_trimesh_shape(); - if (shape.is_null()) - return 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()) - return NULL; + if (mesh.is_null()) { + return nullptr; + } Ref<Shape3D> shape = mesh->create_convex_shape(); - if (shape.is_null()) - return 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,76 +273,76 @@ 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; + } - if (get_material_override() != Ref<Material>()) { - return get_material_override(); - } else if (p_surface < materials.size()) { - return materials[p_surface]; - } else { - Ref<Mesh> mesh = get_mesh(); - - if (mesh.is_null() || p_surface >= mesh->get_surface_count()) { - return Ref<Material>(); - } + Ref<Material> surface_material = get_surface_material(p_surface); + if (surface_material.is_valid()) { + return surface_material; + } + Ref<Mesh> mesh = get_mesh(); + if (mesh.is_valid()) { return mesh->surface_get_material(p_surface); } + + return Ref<Material>(); } 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]; @@ -370,7 +368,6 @@ void MeshInstance3D::create_debug_tangents() { } if (lines.size()) { - Ref<StandardMaterial3D> sm; sm.instance(); @@ -394,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..e29204f702 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() { 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/navigation_3d.cpp b/scene/3d/navigation_3d.cpp index f880f65d37..07a4824c28 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,14 +100,12 @@ 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); 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 a131684a8a..e179261002 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -35,7 +35,6 @@ #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,21 +98,21 @@ 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"); // Search the navigation node and set it { - Navigation3D *nav = NULL; + Navigation3D *nav = nullptr; Node *p = get_parent(); - while (p != NULL) { + while (p != nullptr) { nav = Object::cast_to<Navigation3D>(p); - if (nav != NULL) - p = NULL; - else + if (nav != nullptr) { + p = nullptr; + } else { p = p->get_parent(); + } } set_navigation(nav); @@ -122,13 +121,12 @@ void NavigationAgent3D::_notification(int p_what) { set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { - agent_parent = NULL; - set_navigation(NULL); + agent_parent = nullptr; + set_navigation(nullptr); set_physics_process_internal(false); } 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(NULL), - navigation(NULL), - 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,16 +155,17 @@ 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 == NULL ? RID() : navigation->get_rid()); + NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid()); } void NavigationAgent3D::set_navigation_node(Node *p_nav) { Navigation3D *nav = Object::cast_to<Navigation3D>(p_nav); - ERR_FAIL_COND(nav == NULL); + ERR_FAIL_COND(nav == nullptr); set_navigation(nav); } @@ -244,7 +234,7 @@ Vector3 NavigationAgent3D::get_target_location() const { Vector3 NavigationAgent3D::get_next_location() { update_navigation(); if (navigation_path.size() == 0) { - ERR_FAIL_COND_V(agent_parent == NULL, Vector3()); + ERR_FAIL_COND_V(agent_parent == nullptr, Vector3()); return agent_parent->get_global_transform().origin; } else { return navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0); @@ -252,7 +242,7 @@ Vector3 NavigationAgent3D::get_next_location() { } real_t NavigationAgent3D::distance_to_target() const { - ERR_FAIL_COND_V(agent_parent == NULL, 0.0); + ERR_FAIL_COND_V(agent_parent == nullptr, 0.0); return agent_parent->get_global_transform().origin.distance_to(target_location); } @@ -305,10 +295,15 @@ String NavigationAgent3D::get_configuration_warning() const { } void NavigationAgent3D::update_navigation() { - - if (agent_parent == NULL) return; - if (navigation == NULL) 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 +323,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 +338,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..6dc375ef24 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -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; diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index fa976e5d18..69fd5b02fc 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,19 +43,19 @@ 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 { - Navigation3D *nav = NULL; + Navigation3D *nav = nullptr; Node *p = get_parent(); - while (p != NULL) { + while (p != nullptr) { nav = Object::cast_to<Navigation3D>(p); - if (nav != NULL) - p = NULL; - else + if (nav != nullptr) { + p = nullptr; + } else { p = p->get_parent(); + } } set_navigation(nav); @@ -65,7 +64,7 @@ void NavigationObstacle3D::_notification(int p_what) { set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { - set_navigation(NULL); + set_navigation(nullptr); set_physics_process_internal(false); } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { @@ -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(NULL), - agent(RID()) { +NavigationObstacle3D::NavigationObstacle3D() { agent = NavigationServer3D::get_singleton()->agent_create(); } @@ -98,16 +94,17 @@ 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 == NULL ? RID() : navigation->get_rid()); + NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid()); } void NavigationObstacle3D::set_navigation_node(Node *p_nav) { Navigation3D *nav = Object::cast_to<Navigation3D>(p_nav); - ERR_FAIL_COND(nav == NULL); + ERR_FAIL_COND(nav == nullptr); set_navigation(nav); } @@ -117,7 +114,6 @@ Node *NavigationObstacle3D::get_navigation_node() const { String NavigationObstacle3D::get_configuration_warning() const { if (!Object::cast_to<Node3D>(get_parent())) { - return TTR("The NavigationObstacle3D only serves to provide collision avoidance to a spatial object."); } @@ -151,8 +147,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..c7d2b556af 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; diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 08c0fbf4d1..15ed448a65 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,30 +101,27 @@ 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()); } if (debug_view) { debug_view->queue_delete(); - debug_view = NULL; + debug_view = nullptr; } - navigation = NULL; + navigation = nullptr; } break; } } 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); @@ -184,33 +170,33 @@ void _bake_navigation_mesh(void *p_user_data) { } void NavigationRegion3D::bake_navigation_mesh() { - ERR_FAIL_COND(bake_thread != NULL); + ERR_FAIL_COND(bake_thread != nullptr); BakeThreadsArgs *args = memnew(BakeThreadsArgs); args->nav_region = this; bake_thread = Thread::create(_bake_navigation_mesh, args); - ERR_FAIL_COND(bake_thread == NULL); + ERR_FAIL_COND(bake_thread == nullptr); } void NavigationRegion3D::_bake_finished(Ref<NavigationMesh> p_nav_mesh) { set_navigation_mesh(p_nav_mesh); - bake_thread = NULL; + bake_thread = nullptr; } String NavigationRegion3D::get_configuration_warning() const { - - if (!is_visible_in_tree() || !is_inside_tree()) + if (!is_visible_in_tree() || !is_inside_tree()) { return String(); + } if (!navmesh.is_valid()) { return 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)) + if (Object::cast_to<Navigation3D>(c)) { return String(); + } c = Object::cast_to<Node3D>(c->get_parent()); } @@ -219,7 +205,6 @@ String NavigationRegion3D::get_configuration_warning() const { } 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 +227,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 = NULL; - debug_view = NULL; - bake_thread = NULL; } 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..fcd2efd4ef 100644 --- a/scene/3d/navigation_region_3d.h +++ b/scene/3d/navigation_region_3d.h @@ -38,16 +38,15 @@ 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); diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 7f444d59bf..73f17060df 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -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) + if (E->get()->data.toplevel_active) { continue; //don't propagate to a toplevel + } E->get()->_propagate_transform_changed(p_origin); } #ifdef TOOLS_ENABLED @@ -122,22 +121,22 @@ 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 - data.C = NULL; + } else { + data.C = nullptr; + } if (data.toplevel && !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 @@ -152,20 +151,20 @@ 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 = NULL; - data.C = NULL; + } + data.parent = nullptr; + data.C = nullptr; data.toplevel_active = false; } break; case NOTIFICATION_ENTER_WORLD: { - data.inside_world = true; - data.viewport = NULL; + data.viewport = nullptr; Node *parent = get_parent(); while (parent && !data.viewport) { data.viewport = Object::cast_to<Viewport>(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, NULL, 0); + get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_enter_world, nullptr, 0); } #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,17 +202,15 @@ void Node3D::_notification(int p_what) { #endif if (get_script_instance()) { - - get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_exit_world, NULL, 0); + get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_exit_world, nullptr, 0); } - data.viewport = NULL; + data.viewport = nullptr; data.inside_world = false; } 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,7 +237,6 @@ 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->get_global_transform().affine_inverse() * 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) { - 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; } @@ -484,15 +463,15 @@ bool Node3D::is_scale_disabled() const { } void Node3D::set_as_toplevel(bool p_enabled) { - - if (data.toplevel == p_enabled) + if (data.toplevel == 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; @@ -503,65 +482,64 @@ void Node3D::set_as_toplevel(bool p_enabled) { } bool Node3D::is_set_as_toplevel() const { - return data.toplevel; } -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); @@ -756,7 +719,7 @@ void Node3D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Node3D::is_set_as_toplevel); 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); @@ -821,7 +784,6 @@ void Node3D::_bind_methods() { Node3D::Node3D() : xform_change(this) { - data.dirty = DIRTY_NONE; data.children_lock = 0; @@ -829,7 +791,7 @@ Node3D::Node3D() : data.toplevel = false; data.toplevel_active = false; data.scale = Vector3(1, 1, 1); - data.viewport = NULL; + data.viewport = nullptr; data.inside_world = false; data.visible = true; data.disable_scale = false; @@ -840,8 +802,8 @@ Node3D::Node3D() : #endif data.notify_local_transform = false; data.notify_transform = false; - data.parent = NULL; - data.C = NULL; + data.parent = nullptr; + data.C = nullptr; } Node3D::~Node3D() { diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h index f97a8a97dc..327d4671e9 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; @@ -124,7 +121,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); diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp index 0f1f9bb8a7..40d988ff9f 100644 --- a/scene/3d/path_3d.cpp +++ b/scene/3d/path_3d.cpp @@ -37,9 +37,9 @@ 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) + 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); } @@ -213,11 +207,8 @@ 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); @@ -228,38 +219,34 @@ void PathFollow3D::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { - - path = NULL; + 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(); + } if (!Object::cast_to<Path3D>(get_parent())) { return TTR("PathFollow3D only works when set as a child of a Path3D node."); @@ -274,7 +261,6 @@ String PathFollow3D::get_configuration_warning() const { } 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); @@ -316,16 +302,14 @@ void PathFollow3D::set_offset(float p_offset) { offset = p_offset; if (path) { - if (path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { + if (path->get_curve().is_valid()) { float path_length = path->get_curve()->get_baked_length(); if (loop) { - while (offset > path_length) - offset -= path_length; - - while (offset < 0) - offset += path_length; - + offset = Math::fposmod(offset, path_length); + if (!Math::is_zero_approx(p_offset) && Math::is_zero_approx(offset)) { + offset = path_length; + } } else { offset = CLAMP(offset, 0, path_length); } @@ -338,50 +322,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(); @@ -389,27 +369,23 @@ 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; v_offset = 0; - path = NULL; + path = nullptr; rotation_mode = ROTATION_XYZ; cubic = true; loop = true; diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h index 6f0db8c5c2..7f227a8a6f 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,11 +49,10 @@ public: void set_curve(const Ref<Curve3D> &p_curve); Ref<Curve3D> get_curve() const; - Path3D(); + Path3D() {} }; class PathFollow3D : public Node3D { - GDCLASS(PathFollow3D, Node3D); public: diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 37981f914c..6320af21eb 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -45,72 +45,64 @@ #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); } -Array PhysicsBody3D::get_collision_exceptions() { +TypedArray<PhysicsBody3D> PhysicsBody3D::get_collision_exceptions() { List<RID> exceptions; PhysicsServer3D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); Array ret; @@ -125,7 +117,6 @@ Array 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,7 +124,6 @@ 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."); @@ -146,7 +136,6 @@ void PhysicsBody3D::_set_layers(uint32_t p_mask) { } uint32_t PhysicsBody3D::_get_layers() const { - return get_collision_layer(); } @@ -173,7 +162,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 +186,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 +238,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 +254,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 +261,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 +275,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 +282,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 +295,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 +307,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 +342,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 @@ -385,20 +362,18 @@ void RigidBody3D::_direct_state_changed(Object *p_state) { 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 +387,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 +405,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 +418,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,25 +430,22 @@ 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); } contact_monitor->locked = false; } - state = NULL; + state = nullptr; } void RigidBody3D::_notification(int p_what) { - #ifdef TOOLS_ENABLED if (p_what == NOTIFICATION_ENTER_TREE) { if (Engine::get_singleton()->is_editor_hint()) { @@ -496,16 +463,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 +477,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 +484,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 +527,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 +569,68 @@ 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) { - - if (custom_integrator == 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; } @@ -703,7 +651,6 @@ void RigidBody3D::apply_central_impulse(const Vector3 &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); } @@ -712,27 +659,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); @@ -744,17 +687,15 @@ void RigidBody3D::set_contact_monitor(bool p_enabled) { } memdelete(contact_monitor); - contact_monitor = NULL; + contact_monitor = nullptr; } else { - contact_monitor = memnew(ContactMonitor); contact_monitor->locked = false; } } bool RigidBody3D::is_contact_monitor_enabled() const { - - return contact_monitor != NULL; + return contact_monitor != nullptr; } void RigidBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) { @@ -766,7 +707,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,7 +725,6 @@ Array RigidBody3D::get_colliding_bodies() const { } String RigidBody3D::get_configuration_warning() const { - Transform t = get_transform(); String warning = CollisionObject3D::get_configuration_warning(); @@ -801,7 +740,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); @@ -905,12 +843,11 @@ void RigidBody3D::_bind_methods() { RigidBody3D::RigidBody3D() : PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) { - mode = MODE_RIGID; mass = 1; max_contacts_reported = 0; - state = NULL; + state = nullptr; gravity_scale = 1; linear_damp = -1; @@ -921,16 +858,16 @@ RigidBody3D::RigidBody3D() : ccd = false; custom_integrator = false; - contact_monitor = NULL; + contact_monitor = nullptr; can_sleep = true; PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); } RigidBody3D::~RigidBody3D() { - - if (contact_monitor) + if (contact_monitor) { memdelete(contact_monitor); + } } void RigidBody3D::_reload_physics_characteristics() { @@ -947,7 +884,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 +908,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 +943,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 +965,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 +989,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 +1001,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 +1026,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 +1037,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 +1049,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 +1059,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 +1075,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 +1137,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 +1150,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 +1168,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 +1195,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 +1218,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,7 +1239,6 @@ void KinematicBody3D::_direct_state_changed(Object *p_state) { KinematicBody3D::KinematicBody3D() : PhysicsBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) { - margin = 0.001; locked_axis = 0; on_floor = false; @@ -1318,53 +1247,58 @@ KinematicBody3D::KinematicBody3D() : 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 = NULL; + motion_cache->owner = nullptr; } for (int i = 0; i < slide_colliders.size(); i++) { if (slide_colliders[i].is_valid()) { - slide_colliders.write[i]->owner = NULL; + slide_colliders.write[i]->owner = nullptr; } } } + /////////////////////////////////////// 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 NULL; + 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 NULL; + 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); @@ -1374,23 +1308,22 @@ Object *KinematicCollision3D::get_collider_shape() const { } } - return NULL; + 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,10 +1350,9 @@ void KinematicCollision3D::_bind_methods() { } KinematicCollision3D::KinematicCollision3D() { - collision.collider_shape = 0; collision.local_shape = 0; - owner = NULL; + owner = nullptr; } /////////////////////////////////////// @@ -1469,18 +1401,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 +1457,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 +1531,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 +1614,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 +1752,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 +1991,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 +2016,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")); } @@ -2078,7 +2054,7 @@ void PhysicalBone3D::_notification(int p_what) { parent_skeleton->unbind_physical_bone_from_bone(bone_id); } } - parent_skeleton = NULL; + parent_skeleton = nullptr; if (joint.is_valid()) { PhysicsServer3D::get_singleton()->free(joint); joint = RID(); @@ -2086,7 +2062,6 @@ void PhysicalBone3D::_notification(int p_what) { break; case NOTIFICATION_TRANSFORM_CHANGED: if (Engine::get_singleton()->is_editor_hint()) { - update_offset(); } break; @@ -2094,7 +2069,6 @@ void PhysicalBone3D::_notification(int p_what) { } void PhysicalBone3D::_direct_state_changed(Object *p_state) { - if (!simulate_physics || !_internal_simulate_physics) { return; } @@ -2134,6 +2108,10 @@ void PhysicalBone3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_joint_offset", "offset"), &PhysicalBone3D::set_joint_offset); ClassDB::bind_method(D_METHOD("get_joint_offset"), &PhysicalBone3D::get_joint_offset); + ClassDB::bind_method(D_METHOD("set_joint_rotation", "euler"), &PhysicalBone3D::set_joint_rotation); + ClassDB::bind_method(D_METHOD("get_joint_rotation"), &PhysicalBone3D::get_joint_rotation); + ClassDB::bind_method(D_METHOD("set_joint_rotation_degrees", "euler_degrees"), &PhysicalBone3D::set_joint_rotation_degrees); + ClassDB::bind_method(D_METHOD("get_joint_rotation_degrees"), &PhysicalBone3D::get_joint_rotation_degrees); ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone3D::set_body_offset); ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone3D::get_body_offset); @@ -2159,9 +2137,23 @@ void PhysicalBone3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &PhysicalBone3D::set_gravity_scale); ClassDB::bind_method(D_METHOD("get_gravity_scale"), &PhysicalBone3D::get_gravity_scale); + ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &PhysicalBone3D::set_linear_damp); + ClassDB::bind_method(D_METHOD("get_linear_damp"), &PhysicalBone3D::get_linear_damp); + + ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &PhysicalBone3D::set_angular_damp); + ClassDB::bind_method(D_METHOD("get_angular_damp"), &PhysicalBone3D::get_angular_damp); + + ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &PhysicalBone3D::set_can_sleep); + ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &PhysicalBone3D::is_able_to_sleep); + + ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &PhysicalBone3D::set_axis_lock); + ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &PhysicalBone3D::get_axis_lock); + ADD_GROUP("Joint", "joint_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "joint_type", PROPERTY_HINT_ENUM, "None,PinJoint,ConeJoint,HingeJoint,SliderJoint,6DOFJoint"), "set_joint_type", "get_joint_type"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "joint_offset"), "set_joint_offset", "get_joint_offset"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "joint_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_joint_rotation_degrees", "get_joint_rotation_degrees"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "joint_rotation", PROPERTY_HINT_NONE, "", 0), "set_joint_rotation", "get_joint_rotation"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "body_offset"), "set_body_offset", "get_body_offset"); @@ -2170,6 +2162,17 @@ void PhysicalBone3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-10,10,0.01"), "set_gravity_scale", "get_gravity_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep"); + + ADD_GROUP("Axis Lock", "axis_lock_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_X); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Z); BIND_ENUM_CONSTANT(JOINT_TYPE_NONE); BIND_ENUM_CONSTANT(JOINT_TYPE_PIN); @@ -2181,12 +2184,26 @@ void PhysicalBone3D::_bind_methods() { Skeleton3D *PhysicalBone3D::find_skeleton_parent(Node *p_parent) { if (!p_parent) { - return NULL; + return nullptr; } Skeleton3D *s = Object::cast_to<Skeleton3D>(p_parent); return s ? s : find_skeleton_parent(p_parent->get_parent()); } +void PhysicalBone3D::_update_joint_offset() { + _fix_joint_offset(); + + set_ignore_transform_notification(true); + reset_to_rest_position(); + set_ignore_transform_notification(false); + +#ifdef TOOLS_ENABLED + if (get_gizmo().is_valid()) { + get_gizmo()->redraw(); + } +#endif +} + void PhysicalBone3D::_fix_joint_offset() { // Clamp joint origin to bone origin if (parent_skeleton) { @@ -2195,7 +2212,6 @@ void PhysicalBone3D::_fix_joint_offset() { } void PhysicalBone3D::_reload_joint() { - if (joint.is_valid()) { PhysicsServer3D::get_singleton()->free(joint); joint = RID(); @@ -2216,7 +2232,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); @@ -2225,7 +2240,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); @@ -2236,7 +2250,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); @@ -2248,7 +2261,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); @@ -2264,7 +2276,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) { @@ -2327,13 +2338,14 @@ 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 = NULL; + } + joint_data = nullptr; switch (p_joint_type) { case JOINT_TYPE_PIN: joint_data = memnew(PinJointData); @@ -2358,8 +2370,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 } @@ -2370,16 +2383,31 @@ PhysicalBone3D::JointType PhysicalBone3D::get_joint_type() const { void PhysicalBone3D::set_joint_offset(const Transform &p_offset) { joint_offset = p_offset; - _fix_joint_offset(); + _update_joint_offset(); + _change_notify("joint_rotation_degrees"); +} - set_ignore_transform_notification(true); - reset_to_rest_position(); - set_ignore_transform_notification(false); +const Transform &PhysicalBone3D::get_joint_offset() const { + return joint_offset; +} -#ifdef TOOLS_ENABLED - if (get_gizmo().is_valid()) - get_gizmo()->redraw(); -#endif +void PhysicalBone3D::set_joint_rotation(const Vector3 &p_euler_rad) { + joint_offset.basis.set_euler_scale(p_euler_rad, joint_offset.basis.get_scale()); + + _update_joint_offset(); + _change_notify("joint_offset"); +} + +Vector3 PhysicalBone3D::get_joint_rotation() const { + return joint_offset.basis.get_rotation(); +} + +void PhysicalBone3D::set_joint_rotation_degrees(const Vector3 &p_euler_deg) { + set_joint_rotation(p_euler_deg * Math_PI / 180.0); +} + +Vector3 PhysicalBone3D::get_joint_rotation_degrees() const { + return get_joint_rotation() * 180.0 / Math_PI; } const Transform &PhysicalBone3D::get_body_offset() const { @@ -2390,20 +2418,7 @@ void PhysicalBone3D::set_body_offset(const Transform &p_offset) { body_offset = p_offset; body_offset_inverse = body_offset.affine_inverse(); - _fix_joint_offset(); - - set_ignore_transform_notification(true); - reset_to_rest_position(); - set_ignore_transform_notification(false); - -#ifdef TOOLS_ENABLED - if (get_gizmo().is_valid()) - get_gizmo()->redraw(); -#endif -} - -const Transform &PhysicalBone3D::get_joint_offset() const { - return joint_offset; + _update_joint_offset(); } void PhysicalBone3D::set_simulate_physics(bool p_simulate) { @@ -2424,7 +2439,6 @@ bool PhysicalBone3D::is_simulating_physics() { } void PhysicalBone3D::set_bone_name(const String &p_name) { - bone_name = p_name; bone_id = -1; @@ -2433,34 +2447,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; @@ -2468,12 +2476,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; @@ -2481,43 +2487,64 @@ 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; } -PhysicalBone3D::PhysicalBone3D() : - PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC), -#ifdef TOOLS_ENABLED - gizmo_move_joint(false), -#endif - joint_data(NULL), - parent_skeleton(NULL), - simulate_physics(false), - _internal_simulate_physics(false), - bone_id(-1), - bone_name(""), - bounce(0), - mass(1), - friction(1), - gravity_scale(1) { +void PhysicalBone3D::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 PhysicalBone3D::get_linear_damp() const { + return linear_damp; +} + +void PhysicalBone3D::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 PhysicalBone3D::get_angular_damp() const { + return angular_damp; +} +void PhysicalBone3D::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 PhysicalBone3D::is_able_to_sleep() const { + return can_sleep; +} + +void PhysicalBone3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) { + PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock); +} + +bool PhysicalBone3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const { + return PhysicsServer3D::get_singleton()->body_is_axis_locked(get_rid(), p_axis); +} + +PhysicalBone3D::PhysicalBone3D() : + 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() { @@ -2546,10 +2573,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; @@ -2588,7 +2615,7 @@ void PhysicalBone3D::_stop_physics_simulation() { PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), 0); } if (_internal_simulate_physics) { - PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); + 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); _internal_simulate_physics = false; diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index bf7854b68d..4c58c73942 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -38,7 +38,6 @@ #include "skeleton_3d.h" class PhysicsBody3D : public CollisionObject3D { - GDCLASS(PhysicsBody3D, CollisionObject3D); uint32_t collision_layer; @@ -68,7 +67,7 @@ public: void set_collision_mask_bit(int p_bit, bool p_value); bool get_collision_mask_bit(int p_bit) const; - Array get_collision_exceptions(); + TypedArray<PhysicsBody3D> get_collision_exceptions(); void add_collision_exception_with(Node *p_node); //must be physicsbody void remove_collision_exception_with(Node *p_node); @@ -76,7 +75,6 @@ public: }; class StaticBody3D : public PhysicsBody3D { - GDCLASS(StaticBody3D, PhysicsBody3D); Vector3 constant_linear_velocity; @@ -105,7 +103,6 @@ private: }; class RigidBody3D : public PhysicsBody3D { - GDCLASS(RigidBody3D, PhysicsBody3D); public: @@ -138,15 +135,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 +154,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; }; @@ -261,7 +255,6 @@ VARIANT_ENUM_CAST(RigidBody3D::Mode); class KinematicCollision3D; class KinematicBody3D : public PhysicsBody3D { - GDCLASS(KinematicBody3D, PhysicsBody3D); public: @@ -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,25 +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 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); @@ -575,6 +528,7 @@ protected: private: static Skeleton3D *find_skeleton_parent(Node *p_parent); + void _update_joint_offset(); void _fix_joint_offset(); void _reload_joint(); @@ -599,6 +553,12 @@ public: void set_joint_offset(const Transform &p_offset); const Transform &get_joint_offset() const; + void set_joint_rotation(const Vector3 &p_euler_rad); + Vector3 get_joint_rotation() const; + + void set_joint_rotation_degrees(const Vector3 &p_euler_deg); + Vector3 get_joint_rotation_degrees() const; + void set_body_offset(const Transform &p_offset); const Transform &get_body_offset() const; @@ -624,6 +584,18 @@ public: void set_gravity_scale(real_t p_gravity_scale); real_t get_gravity_scale() const; + void set_linear_damp(real_t p_linear_damp); + real_t get_linear_damp() const; + + void set_angular_damp(real_t p_angular_damp); + real_t get_angular_damp() const; + + void set_can_sleep(bool p_active); + bool is_able_to_sleep() const; + + void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock); + 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); diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp index f6b3e79300..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,77 +42,78 @@ 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 *)NULL; - Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL; + 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; 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..a3225ab01c 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: @@ -102,7 +100,6 @@ public: VARIANT_ENUM_CAST(PinJoint3D::Param); class HingeJoint3D : public Joint3D { - GDCLASS(HingeJoint3D, Joint3D); public: @@ -150,7 +147,6 @@ VARIANT_ENUM_CAST(HingeJoint3D::Param); VARIANT_ENUM_CAST(HingeJoint3D::Flag); class SliderJoint3D : public Joint3D { - GDCLASS(SliderJoint3D, Joint3D); public: @@ -203,7 +199,6 @@ public: VARIANT_ENUM_CAST(SliderJoint3D::Param); class ConeTwistJoint3D : public Joint3D { - GDCLASS(ConeTwistJoint3D, Joint3D); public: @@ -238,7 +233,6 @@ public: VARIANT_ENUM_CAST(ConeTwistJoint3D::Param); class Generic6DOFJoint3D : public Joint3D { - GDCLASS(Generic6DOFJoint3D, Joint3D); public: @@ -305,7 +299,7 @@ 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); static void _bind_methods(); 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 d00af3b128..68f4b3132c 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -36,151 +36,149 @@ #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())) + 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; } 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()) - return 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()); @@ -205,13 +203,13 @@ void RayCast3D::_update_raycast_state() { Transform gt = get_global_transform(); Vector3 to = cast_to; - if (to == Vector3()) + 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,60 +227,52 @@ 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); @@ -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(); @@ -377,28 +368,28 @@ 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 = NULL; + debug_shape = nullptr; } RayCast3D::RayCast3D() { - enabled = false; collided = false; against_shape = 0; collision_mask = 1; cast_to = Vector3(0, -1, 0); - debug_shape = NULL; + debug_shape = nullptr; exclude_parent_body = true; collide_with_areas = false; collide_with_bodies = true; diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h index f8bfb7846a..8f617e5491 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; diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index 24bf8b43d1..b1f19053d9 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -31,18 +31,15 @@ #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); } @@ -57,33 +54,28 @@ float ReflectionProbe::get_interior_ambient_energy() const { } Color ReflectionProbe::get_interior_ambient() const { - return interior_ambient; } 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_interior_ambient_probe_contribution() const { - return interior_ambient_probe_contribution; } 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 +94,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 +113,45 @@ 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,19 +165,17 @@ 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) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; @@ -201,7 +184,6 @@ void ReflectionProbe::_validate_property(PropertyInfo &property) const { } 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); @@ -258,7 +240,6 @@ void ReflectionProbe::_bind_methods() { } ReflectionProbe::ReflectionProbe() { - intensity = 1.0; interior_ambient = Color(0, 0, 0); interior_ambient_probe_contribution = 0; @@ -278,6 +259,5 @@ ReflectionProbe::ReflectionProbe() { } ReflectionProbe::~ReflectionProbe() { - RS::get_singleton()->free(probe); } diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp index 38792bbb58..95fce6b802 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,7 +180,6 @@ void RemoteTransform3D::force_update_cache() { } String RemoteTransform3D::get_configuration_warning() const { - 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."); } @@ -188,7 +188,6 @@ String RemoteTransform3D::get_configuration_warning() const { } 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 +212,6 @@ void RemoteTransform3D::_bind_methods() { } RemoteTransform3D::RemoteTransform3D() { - use_global_coordinates = true; update_remote_position = true; update_remote_rotation = true; diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 1b05641c9d..6723ca04b9 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -33,8 +33,10 @@ #include "core/engine.h" #include "core/message_queue.h" #include "core/project_settings.h" +#include "core/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) { @@ -65,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); @@ -114,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); @@ -149,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(); @@ -179,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)); @@ -196,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) { @@ -209,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(); @@ -236,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) { @@ -244,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; } } @@ -303,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(); @@ -327,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); @@ -343,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) { @@ -366,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 @@ -404,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; @@ -413,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); } @@ -438,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)); @@ -484,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(); @@ -502,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)); @@ -583,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++; @@ -593,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; @@ -601,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() ); @@ -619,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; @@ -639,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--) { @@ -685,19 +661,19 @@ void Skeleton3D::bind_physical_bone_to_bone(int p_bone, PhysicalBone3D *p_physic void Skeleton3D::unbind_physical_bone_from_bone(int p_bone) { ERR_FAIL_INDEX(p_bone, bones.size()); - bones.write[p_bone].physical_bone = NULL; + bones.write[p_bone].physical_bone = nullptr; _rebuild_physical_bones_cache(); } PhysicalBone3D *Skeleton3D::get_physical_bone(int p_bone) { - ERR_FAIL_INDEX_V(p_bone, bones.size(), NULL); + ERR_FAIL_INDEX_V(p_bone, bones.size(), nullptr); return bones[p_bone].physical_bone; } PhysicalBone3D *Skeleton3D::get_physical_bone_parent(int p_bone) { - ERR_FAIL_INDEX_V(p_bone, bones.size(), NULL); + ERR_FAIL_INDEX_V(p_bone, bones.size(), nullptr); if (bones[p_bone].cache_parent_physical_bone) { return bones[p_bone].cache_parent_physical_bone; @@ -707,11 +683,11 @@ PhysicalBone3D *Skeleton3D::get_physical_bone_parent(int p_bone) { } PhysicalBone3D *Skeleton3D::_get_physical_bone_parent(int p_bone) { - ERR_FAIL_INDEX_V(p_bone, bones.size(), NULL); + ERR_FAIL_INDEX_V(p_bone, bones.size(), nullptr); const int parent_bone = bones[p_bone].parent; if (0 > parent_bone) { - return NULL; + return nullptr; } PhysicalBone3D *pb = bones[parent_bone].physical_bone; @@ -728,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)); } @@ -754,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); } @@ -770,7 +745,7 @@ void _pb_start_simulation(const Skeleton3D *p_skeleton, Node *p_node, const Vect } } -void Skeleton3D::physical_bones_start_simulation_on(const Array &p_bones) { +void Skeleton3D::physical_bones_start_simulation_on(const TypedArray<StringName> &p_bones) { set_physics_process_internal(false); Vector<int> sim_bones; @@ -780,11 +755,9 @@ void Skeleton3D::physical_bones_start_simulation_on(const Array &p_bones) { sim_bones.resize(p_bones.size()); int c = 0; for (int i = sim_bones.size() - 1; 0 <= i; --i) { - Variant::Type type = p_bones.get(i).get_type(); - if (Variant::STRING == type || Variant::STRING_NAME == type) { - int bone_id = find_bone(p_bones.get(i)); - if (bone_id != -1) - sim_bones.write[c++] = bone_id; + int bone_id = find_bone(p_bones[i]); + if (bone_id != -1) { + sim_bones.write[c++] = bone_id; } } sim_bones.resize(c); @@ -794,7 +767,6 @@ void Skeleton3D::physical_bones_start_simulation_on(const Array &p_bones) { } 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); } @@ -824,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()); @@ -884,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); @@ -923,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); @@ -936,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; @@ -948,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 2ae04aa575..a21891a32e 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.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; @@ -112,12 +106,16 @@ private: global_pose_override_amount = 0; global_pose_override_reset = false; #ifndef _3D_DISABLED - physical_bone = NULL; - cache_parent_physical_bone = NULL; + physical_bone = nullptr; + cache_parent_physical_bone = nullptr; #endif // _3D_DISABLED } }; + 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; @@ -200,9 +196,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,13 +217,13 @@ 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(); public: void physical_bones_stop_simulation(); - void physical_bones_start_simulation_on(const Array &p_bones); + void physical_bones_start_simulation_on(const TypedArray<StringName> &p_bones); void physical_bones_add_collision_exception(RID p_exception); void physical_bones_remove_collision_exception(RID p_exception); #endif // _3D_DISABLED diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp index a6c3e25399..9023f3c68a 100644 --- a/scene/3d/skeleton_ik_3d.cpp +++ b/scene/3d/skeleton_ik_3d.cpp @@ -42,7 +42,7 @@ FabrikInverseKinematic::ChainItem *FabrikInverseKinematic::ChainItem::find_child return &children.write[i]; } } - return NULL; + return nullptr; } FabrikInverseKinematic::ChainItem *FabrikInverseKinematic::ChainItem::add_child(const BoneId p_bone_id) { @@ -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); @@ -65,7 +64,7 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain chain.chain_root.initial_transform = p_task->skeleton->get_bone_global_pose(chain.chain_root.bone); chain.chain_root.current_pos = chain.chain_root.initial_transform.origin; chain.chain_root.pb = p_task->skeleton->get_physical_bone(chain.chain_root.bone); - chain.middle_chain_item = NULL; + chain.middle_chain_item = nullptr; // Holds all IDs that are composing a single chain in reverse order Vector<BoneId> chain_ids; @@ -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) - chain.middle_chain_item = NULL; + 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 @@ -226,20 +218,18 @@ void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_ if (p_solve_magnet && sub_chain_root == r_chain.middle_chain_item) { // In case of magnet solving this is the tip - sub_chain_root = NULL; + sub_chain_root = nullptr; } else { sub_chain_root = &child; } } else { - // Is tip - sub_chain_root = NULL; + sub_chain_root = nullptr; } } } 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; @@ -251,15 +241,16 @@ FabrikInverseKinematic::Task *FabrikInverseKinematic::create_simple_task(Skeleto if (!build_chain(task)) { free_task(task); - return NULL; + return nullptr; } return task; } 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 - ci = NULL; + } 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,20 +419,12 @@ 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(NULL), - target_node_override(NULL), - task(NULL) { +SkeletonIK3D::SkeletonIK3D() { } SkeletonIK3D::~SkeletonIK3D() { FabrikInverseKinematic::free_task(task); - task = NULL; + task = nullptr; } void SkeletonIK3D::set_root_bone(const StringName &p_root_bone) { @@ -479,7 +464,7 @@ const Transform &SkeletonIK3D::get_target_transform() const { void SkeletonIK3D::set_target_node(const NodePath &p_node) { target_node_path_override = p_node; - target_node_override = NULL; + target_node_override = nullptr; reload_goal(); } @@ -537,23 +522,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 = NULL; + 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 +549,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 ebfebd1e66..0d948f13a9 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(NULL), - bone(-1), - pb(NULL), - 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(NULL), - end_effector(NULL) {} + 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(NULL), - min_distance(0.01), - max_iterations(10), - root_bone(-1) {} + Task() {} }; private: @@ -146,19 +134,19 @@ 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 diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 6d2808cfce..a267c57f5e 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -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(NULL) { +SoftBody3D::PinnedPoint::PinnedPoint() { } SoftBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { @@ -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; @@ -296,12 +288,10 @@ void SoftBody3D::_notification(int p_what) { } 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,11 +416,11 @@ 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) @@ -448,25 +439,22 @@ 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 - PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, NULL); + } 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, NULL); + 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)); } @@ -808,7 +790,7 @@ void SoftBody3D::_remove_pinned_point(int p_point_index) { int SoftBody3D::_get_pinned_point(int p_point_index, SoftBody3D::PinnedPoint *&r_point) const { const int id = _has_pinned_point(p_point_index); if (-1 == id) { - r_point = NULL; + r_point = nullptr; return -1; } else { r_point = const_cast<SoftBody3D::PinnedPoint *>(&pinned_points.ptr()[id]); diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h index 7dd5880985..0063e342f2 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,9 +67,9 @@ 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(); @@ -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(); diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp index 281be3f7d3..9775ecc6c6 100644 --- a/scene/3d/spring_arm_3d.cpp +++ b/scene/3d/spring_arm_3d.cpp @@ -29,38 +29,31 @@ /*************************************************************************/ #include "spring_arm_3d.h" + #include "core/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: if (!Engine::get_singleton()->is_editor_hint()) { - set_process_internal(true); + set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: if (!Engine::get_singleton()->is_editor_hint()) { - set_process_internal(false); + set_physics_process_internal(false); } break; - case NOTIFICATION_INTERNAL_PROCESS: + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: process_spring(); break; } } 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 360e95e76a..3b76cb6499 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,111 +78,98 @@ void SpriteBase3D::_notification(int p_what) { } if (p_what == NOTIFICATION_EXIT_TREE) { - if (parent_sprite) { - parent_sprite->children.erase(pI); - pI = NULL; - parent_sprite = NULL; + pI = nullptr; + parent_sprite = nullptr; } } } 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,8 +197,9 @@ 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(); @@ -260,7 +247,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 +258,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,16 +340,16 @@ void SpriteBase3D::_bind_methods() { } SpriteBase3D::SpriteBase3D() { - color_dirty = true; centered = true; hflip = false; vflip = false; - parent_sprite = NULL; - pI = NULL; + 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 +363,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(); @@ -441,7 +426,7 @@ void Sprite3D::_draw() { // Properly setup UVs for impostor textures (AtlasTexture). Ref<AtlasTexture> atlas_tex = texture; - if (atlas_tex != NULL) { + if (atlas_tex != nullptr) { src_tsize[0] = atlas_tex->get_atlas()->get_width(); src_tsize[1] = atlas_tex->get_atlas()->get_height(); } @@ -458,7 +443,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 +483,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 +510,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 +524,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 +549,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 +565,6 @@ void Sprite3D::set_frame(int p_frame) { } int Sprite3D::get_frame() const { - return frame; } @@ -603,33 +580,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 +613,6 @@ Rect2 Sprite3D::get_item_rect() const { Size2i s; if (region) { - s = region_rect.size; } else { s = texture->get_size(); @@ -646,17 +620,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 +644,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); @@ -705,7 +679,6 @@ void Sprite3D::_bind_methods() { } Sprite3D::Sprite3D() { - region = false; frame = 0; vframes = 1; @@ -715,7 +688,6 @@ Sprite3D::Sprite3D() { //////////////////////////////////////// void AnimatedSprite3D::_draw() { - RID immediate = get_immediate(); RS::get_singleton()->immediate_clear(immediate); @@ -732,11 +704,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 +718,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(); @@ -775,7 +752,7 @@ void AnimatedSprite3D::_draw() { // Properly setup UVs for impostor textures (AtlasTexture). Ref<AtlasTexture> atlas_tex = texture; - if (atlas_tex != NULL) { + if (atlas_tex != nullptr) { src_tsize[0] = atlas_tex->get_atlas()->get_width(); src_tsize[1] = atlas_tex->get_atlas()->get_height(); } @@ -792,7 +769,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 +810,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 +836,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 +877,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 +924,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 +945,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 +974,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 +1013,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 +1058,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,13 +1068,12 @@ 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 { - 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."); } @@ -1108,7 +1082,6 @@ String AnimatedSprite3D::get_configuration_warning() const { } 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 +1107,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..721bed56f1 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 @@ -145,7 +144,6 @@ public: }; class Sprite3D : public SpriteBase3D { - GDCLASS(Sprite3D, SpriteBase3D); Ref<Texture2D> texture; @@ -194,7 +192,6 @@ public: }; class AnimatedSprite3D : public SpriteBase3D { - GDCLASS(AnimatedSprite3D, SpriteBase3D); Ref<SpriteFrames> frames; diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index ac7608a3d5..9c6b940b00 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,12 +93,12 @@ 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 = NULL; + body = nullptr; } } @@ -112,7 +111,6 @@ String VehicleWheel3D::get_configuration_warning() const { } void VehicleWheel3D::_update(PhysicsDirectBodyState3D *s) { - if (m_raycastInfo.m_isInContact) { @@ -145,77 +143,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 +221,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 +291,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.); @@ -385,11 +362,10 @@ VehicleWheel3D::VehicleWheel3D() { m_clippedInvContactDotSuspension = 1.0; m_raycastInfo.m_isInContact = false; - body = NULL; + body = nullptr; } void VehicleBody3D::_update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirectBodyState3D *s) { - wheel.m_raycastInfo.m_isInContact = false; Transform chassisTrans = s->get_transform(); @@ -406,7 +382,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 +406,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); @@ -454,7 +428,7 @@ real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState3D *s) { bool col = ss->intersect_ray(source, target, rr, exclude); - wheel.m_raycastInfo.m_groundObject = 0; + wheel.m_raycastInfo.m_groundObject = nullptr; if (col) { param = source.distance_to(rr.position) / source.distance_to(target); @@ -462,8 +436,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 +489,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 +534,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 +544,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; @@ -668,15 +643,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 +674,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 +692,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; @@ -851,7 +823,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 +830,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 +841,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]; @@ -917,53 +885,50 @@ void VehicleBody3D::_direct_state_changed(Object *p_state) { wheel.m_deltaRotation *= real_t(0.99); //damping of rotation when not in contact } - state = NULL; + state = nullptr; } 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 +945,6 @@ void VehicleBody3D::_bind_methods() { } VehicleBody3D::VehicleBody3D() { - m_pitchControl = 0; m_currentVehicleSpeedKmHour = real_t(0.); m_steeringValue = real_t(0.); @@ -988,7 +952,7 @@ VehicleBody3D::VehicleBody3D() { engine_force = 0; brake = 0; - state = NULL; + state = nullptr; ccd = false; exclude.insert(get_rid()); diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h index d5e896263d..e76f44acfd 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; @@ -152,7 +151,6 @@ public: }; class VehicleBody3D : public RigidBody3D { - GDCLASS(VehicleBody3D, RigidBody3D); float engine_force; diff --git a/scene/3d/velocity_tracker_3d.cpp b/scene/3d/velocity_tracker_3d.cpp index c9b95e6397..db10f3273b 100644 --- a/scene/3d/velocity_tracker_3d.cpp +++ b/scene/3d/velocity_tracker_3d.cpp @@ -32,16 +32,14 @@ #include "core/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..a64b0df1cc 100644 --- a/scene/3d/visibility_notifier_3d.cpp +++ b/scene/3d/visibility_notifier_3d.cpp @@ -37,7 +37,6 @@ #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..3864b398f4 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: diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index 775a9b76e2..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,122 +140,200 @@ 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; } void GeometryInstance3D::_notification(int p_what) { } -void GeometryInstance3D::set_flag(Flags p_flag, bool p_value) { +const StringName *GeometryInstance3D::_instance_uniform_get_remap(const StringName p_name) const { + StringName *r = instance_uniform_property_remap.getptr(p_name); + if (!r) { + String s = p_name; + if (s.begins_with("shader_params/")) { + StringName name = s.replace("shader_params/", ""); + instance_uniform_property_remap[p_name] = name; + return instance_uniform_property_remap.getptr(p_name); + } - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - if (flags[p_flag] == p_value) - return; + return nullptr; + } - flags[p_flag] = p_value; - RS::get_singleton()->instance_geometry_set_flag(get_instance(), (RS::InstanceFlags)p_flag, p_value); + return r; } -bool GeometryInstance3D::get_flag(Flags p_flag) const { +bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value) { + const StringName *r = _instance_uniform_get_remap(p_name); + if (r) { + 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; + } - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + if (p_name == SceneStringNames::get_singleton()->use_dynamic_gi && bool(p_value)) { + set_gi_mode(GI_MODE_DYNAMIC); + return true; + } +#endif + return false; +} - return flags[p_flag]; +bool GeometryInstance3D::_get(const StringName &p_name, Variant &r_ret) const { + const StringName *r = _instance_uniform_get_remap(p_name); + if (r) { + r_ret = get_shader_instance_uniform(*r); + return true; + } + + 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); + for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { + PropertyInfo pi = E->get(); + bool has_def_value = false; + Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), pi.name); + if (def_value.get_type() != Variant::NIL) { + has_def_value = true; + } + if (instance_uniforms.has(pi.name)) { + pi.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE | (has_def_value ? (PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_CHECKED) : 0); + } else { + pi.usage = PROPERTY_USAGE_EDITOR | (has_def_value ? PROPERTY_USAGE_CHECKABLE : 0); //do not save if not changed + } + + pi.name = "shader_params/" + pi.name; + p_list->push_back(pi); + } } 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_custom_aabb(AABB aabb) { +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); + instance_uniforms.erase(p_value); + } else { + instance_uniforms[p_uniform] = p_value; + RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, p_value); + } +} + +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) { 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); @@ -280,6 +343,9 @@ void GeometryInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_lod_max_distance", "mode"), &GeometryInstance3D::set_lod_max_distance); ClassDB::bind_method(D_METHOD("get_lod_max_distance"), &GeometryInstance3D::get_lod_max_distance); + ClassDB::bind_method(D_METHOD("set_shader_instance_uniform", "uniform", "value"), &GeometryInstance3D::set_shader_instance_uniform); + ClassDB::bind_method(D_METHOD("get_shader_instance_uniform", "uniform"), &GeometryInstance3D::get_shader_instance_uniform); + ClassDB::bind_method(D_METHOD("set_lod_min_hysteresis", "mode"), &GeometryInstance3D::set_lod_min_hysteresis); ClassDB::bind_method(D_METHOD("get_lod_min_hysteresis"), &GeometryInstance3D::get_lod_min_hysteresis); @@ -289,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); @@ -297,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"); @@ -313,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() { @@ -325,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 9476c28848..195674f62d 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -37,7 +37,6 @@ #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; @@ -108,16 +112,24 @@ private: float lod_min_hysteresis; float lod_max_hysteresis; + mutable HashMap<StringName, Variant> instance_uniforms; + 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; protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + void _notification(int p_what); 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; @@ -139,12 +151,22 @@ 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; + void set_custom_aabb(AABB aabb); 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 203c3cd812..de5496ee35 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; @@ -592,32 +400,24 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; const Vector3 *vr = vertices.ptr(); Vector<Vector2> uv = a[Mesh::ARRAY_TEX_UV]; - const Vector2 *uvr; + const Vector2 *uvr = nullptr; Vector<Vector3> normals = a[Mesh::ARRAY_NORMAL]; - const Vector3 *nr; + const Vector3 *nr = nullptr; Vector<int> index = a[Mesh::ARRAY_INDEX]; - bool read_uv = false; - bool read_normals = false; - if (uv.size()) { - uvr = uv.ptr(); - read_uv = true; } if (normals.size()) { - read_normals = true; nr = normals.ptr(); } 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]; @@ -626,31 +426,30 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec vtxs[k] = p_xform.xform(vr[ir[j * 3 + k]]); } - if (read_uv) { + if (uvr) { for (int k = 0; k < 3; k++) { uvs[k] = uvr[ir[j * 3 + k]]; } } - if (read_normals) { + if (nr) { for (int k = 0; k < 3; k++) { normal[k] = nr[ir[j * 3 + k]]; } } //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]; @@ -659,21 +458,22 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec vtxs[k] = p_xform.xform(vr[j * 3 + k]); } - if (read_uv) { + if (uvr) { for (int k = 0; k < 3; k++) { uvs[k] = uvr[j * 3 + k]; } } - if (read_normals) { + if (nr) { for (int k = 0; k < 3; k++) { normal[k] = nr[j * 3 + k]; } } //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); } @@ -684,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 @@ -693,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(); @@ -726,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(); @@ -749,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; @@ -790,7 +585,6 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) { }*/ } else { - //go down bake_cells.write[p_idx].emission[0] = 0; @@ -807,11 +601,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; @@ -824,7 +618,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; @@ -839,9 +632,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]; @@ -879,9 +672,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(); } @@ -897,7 +692,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]; } @@ -906,6 +700,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 @@ -917,7 +712,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; @@ -989,7 +783,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]; @@ -1013,8 +806,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]; } @@ -1026,7 +820,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; @@ -1044,7 +837,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 } @@ -1098,9 +890,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; @@ -1114,23 +904,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); } @@ -1138,7 +930,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(); @@ -1161,22 +952,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]; + } } } @@ -1217,6 +1006,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..24071f31f3 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -32,100 +32,93 @@ #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 { - if (!environment.is_valid()) { return TTR("WorldEnvironment requires its \"Environment\" property to contain an Environment to have a visible effect."); } - if (!is_inside_tree()) + if (!is_inside_tree()) { return String(); + } 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)."); @@ -135,7 +128,6 @@ String WorldEnvironment::get_configuration_warning() const { } 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..ddb2af7bd3 100644 --- a/scene/3d/world_environment.h +++ b/scene/3d/world_environment.h @@ -34,7 +34,6 @@ #include "scene/3d/node_3d.h" class WorldEnvironment : public Node { - GDCLASS(WorldEnvironment, Node); Ref<Environment> environment; diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/xr_nodes.cpp index ce7c885a40..f4a514cdd6 100644 --- a/scene/3d/arvr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* arvr_nodes.cpp */ +/* xr_nodes.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,52 +28,54 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "arvr_nodes.h" -#include "core/input/input_filter.h" -#include "servers/arvr/arvr_interface.h" -#include "servers/arvr_server.h" +#include "xr_nodes.h" + +#include "core/input/input.h" +#include "servers/xr/xr_interface.h" +#include "servers/xr_server.h" //////////////////////////////////////////////////////////////////////////////////////////////////// -void ARVRCamera::_notification(int p_what) { +void XRCamera3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - // need to find our ARVROrigin parent and let it know we're its camera! - ARVROrigin *origin = Object::cast_to<ARVROrigin>(get_parent()); - if (origin != NULL) { + // need to find our XROrigin3D parent and let it know we're its camera! + XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent()); + if (origin != nullptr) { origin->set_tracked_camera(this); } }; break; case NOTIFICATION_EXIT_TREE: { - // need to find our ARVROrigin parent and let it know we're no longer its camera! - ARVROrigin *origin = Object::cast_to<ARVROrigin>(get_parent()); - if (origin != NULL) { + // need to find our XROrigin3D parent and let it know we're no longer its camera! + XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent()); + if (origin != nullptr) { origin->clear_tracked_camera_if(this); } }; break; }; }; -String ARVRCamera::get_configuration_warning() const { - if (!is_visible() || !is_inside_tree()) +String XRCamera3D::get_configuration_warning() const { + if (!is_visible() || !is_inside_tree()) { return String(); + } - // must be child node of ARVROrigin! - ARVROrigin *origin = Object::cast_to<ARVROrigin>(get_parent()); - if (origin == NULL) { - return TTR("ARVRCamera must have an ARVROrigin node as its parent."); + // 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."); }; return String(); }; -Vector3 ARVRCamera::project_local_ray_normal(const Point2 &p_pos) const { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, Vector3()); +Vector3 XRCamera3D::project_local_ray_normal(const Point2 &p_pos) const { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, Vector3()); - Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface(); - if (arvr_interface.is_null()) { + Ref<XRInterface> xr_interface = xr_server->get_primary_interface(); + if (xr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass return Camera3D::project_local_ray_normal(p_pos); } @@ -84,20 +86,20 @@ Vector3 ARVRCamera::project_local_ray_normal(const Point2 &p_pos) const { Vector2 cpos = get_viewport()->get_camera_coords(p_pos); Vector3 ray; - CameraMatrix cm = arvr_interface->get_projection_for_eye(ARVRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); + CameraMatrix cm = xr_interface->get_projection_for_eye(XRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); Vector2 screen_he = cm.get_viewport_half_extents(); ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -get_znear()).normalized(); return ray; }; -Point2 ARVRCamera::unproject_position(const Vector3 &p_pos) const { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, Vector2()); +Point2 XRCamera3D::unproject_position(const Vector3 &p_pos) const { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, Vector2()); - Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface(); - if (arvr_interface.is_null()) { + Ref<XRInterface> xr_interface = xr_server->get_primary_interface(); + if (xr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass return Camera3D::unproject_position(p_pos); } @@ -106,7 +108,7 @@ Point2 ARVRCamera::unproject_position(const Vector3 &p_pos) const { Size2 viewport_size = get_viewport()->get_visible_rect().size; - CameraMatrix cm = arvr_interface->get_projection_for_eye(ARVRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); + CameraMatrix cm = xr_interface->get_projection_for_eye(XRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); Plane p(get_camera_transform().xform_inv(p_pos), 1.0); @@ -120,13 +122,13 @@ Point2 ARVRCamera::unproject_position(const Vector3 &p_pos) const { return res; }; -Vector3 ARVRCamera::project_position(const Point2 &p_point, float p_z_depth) const { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, Vector3()); +Vector3 XRCamera3D::project_position(const Point2 &p_point, float p_z_depth) const { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, Vector3()); - Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface(); - if (arvr_interface.is_null()) { + Ref<XRInterface> xr_interface = xr_server->get_primary_interface(); + if (xr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass return Camera3D::project_position(p_point, p_z_depth); } @@ -135,7 +137,7 @@ Vector3 ARVRCamera::project_position(const Point2 &p_point, float p_z_depth) con Size2 viewport_size = get_viewport()->get_visible_rect().size; - CameraMatrix cm = arvr_interface->get_projection_for_eye(ARVRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); + CameraMatrix cm = xr_interface->get_projection_for_eye(XRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); Vector2 vp_he = cm.get_viewport_half_extents(); @@ -149,13 +151,13 @@ Vector3 ARVRCamera::project_position(const Point2 &p_point, float p_z_depth) con return get_camera_transform().xform(p); }; -Vector<Plane> ARVRCamera::get_frustum() const { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, Vector<Plane>()); +Vector<Plane> XRCamera3D::get_frustum() const { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, Vector<Plane>()); - Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface(); - if (arvr_interface.is_null()) { + Ref<XRInterface> xr_interface = xr_server->get_primary_interface(); + if (xr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass return Camera3D::get_frustum(); } @@ -163,21 +165,13 @@ Vector<Plane> ARVRCamera::get_frustum() const { ERR_FAIL_COND_V(!is_inside_world(), Vector<Plane>()); Size2 viewport_size = get_viewport()->get_visible_rect().size; - CameraMatrix cm = arvr_interface->get_projection_for_eye(ARVRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); + CameraMatrix cm = xr_interface->get_projection_for_eye(XRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); return cm.get_projection_planes(get_camera_transform()); }; -ARVRCamera::ARVRCamera(){ - // nothing to do here yet for now.. -}; - -ARVRCamera::~ARVRCamera(){ - // nothing to do here yet for now.. -}; - //////////////////////////////////////////////////////////////////////////////////////////////////// -void ARVRController::_notification(int p_what) { +void XRController3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { set_process_internal(true); @@ -186,13 +180,13 @@ void ARVRController::_notification(int p_what) { set_process_internal(false); }; break; case NOTIFICATION_INTERNAL_PROCESS: { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL(arvr_server); + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); // find the tracker for our controller - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); - if (tracker == NULL) { + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (tracker == nullptr) { // this controller is currently turned off is_active = false; button_states = 0; @@ -206,7 +200,7 @@ void ARVRController::_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); @@ -236,63 +230,63 @@ void ARVRController::_notification(int p_what) { }; }; -void ARVRController::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_controller_id", "controller_id"), &ARVRController::set_controller_id); - ClassDB::bind_method(D_METHOD("get_controller_id"), &ARVRController::get_controller_id); +void XRController3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_controller_id", "controller_id"), &XRController3D::set_controller_id); + ClassDB::bind_method(D_METHOD("get_controller_id"), &XRController3D::get_controller_id); ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_id", PROPERTY_HINT_RANGE, "0,32,1"), "set_controller_id", "get_controller_id"); - ClassDB::bind_method(D_METHOD("get_controller_name"), &ARVRController::get_controller_name); + ClassDB::bind_method(D_METHOD("get_controller_name"), &XRController3D::get_controller_name); // passthroughs to information about our related joystick - ClassDB::bind_method(D_METHOD("get_joystick_id"), &ARVRController::get_joystick_id); - ClassDB::bind_method(D_METHOD("is_button_pressed", "button"), &ARVRController::is_button_pressed); - ClassDB::bind_method(D_METHOD("get_joystick_axis", "axis"), &ARVRController::get_joystick_axis); + ClassDB::bind_method(D_METHOD("get_joystick_id"), &XRController3D::get_joystick_id); + ClassDB::bind_method(D_METHOD("is_button_pressed", "button"), &XRController3D::is_button_pressed); + ClassDB::bind_method(D_METHOD("get_joystick_axis", "axis"), &XRController3D::get_joystick_axis); - ClassDB::bind_method(D_METHOD("get_is_active"), &ARVRController::get_is_active); - ClassDB::bind_method(D_METHOD("get_hand"), &ARVRController::get_hand); + ClassDB::bind_method(D_METHOD("get_is_active"), &XRController3D::get_is_active); + ClassDB::bind_method(D_METHOD("get_hand"), &XRController3D::get_hand); - ClassDB::bind_method(D_METHOD("get_rumble"), &ARVRController::get_rumble); - ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &ARVRController::set_rumble); + ClassDB::bind_method(D_METHOD("get_rumble"), &XRController3D::get_rumble); + ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &XRController3D::set_rumble); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rumble", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_rumble", "get_rumble"); ADD_PROPERTY_DEFAULT("rumble", 0.0); - ClassDB::bind_method(D_METHOD("get_mesh"), &ARVRController::get_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &XRController3D::get_mesh); ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::INT, "button"))); ADD_SIGNAL(MethodInfo("button_release", PropertyInfo(Variant::INT, "button"))); ADD_SIGNAL(MethodInfo("mesh_updated", PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"))); }; -void ARVRController::set_controller_id(int p_controller_id) { +void XRController3D::set_controller_id(int p_controller_id) { // We don't check any bounds here, this controller may not yet be active and just be a place holder until it is. // Note that setting this to 0 means this node is not bound to a controller yet. controller_id = p_controller_id; update_configuration_warning(); }; -int ARVRController::get_controller_id(void) const { +int XRController3D::get_controller_id() const { return controller_id; }; -String ARVRController::get_controller_name(void) const { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, String()); +String XRController3D::get_controller_name() const { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, String()); - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); - if (tracker == NULL) { + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (tracker == nullptr) { return String("Not connected"); }; return tracker->get_name(); }; -int ARVRController::get_joystick_id() const { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, 0); +int XRController3D::get_joystick_id() const { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, 0); - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); - if (tracker == NULL) { + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (tracker == nullptr) { // No tracker? no joystick id... (0 is our first joystick) return -1; }; @@ -300,77 +294,78 @@ int ARVRController::get_joystick_id() const { return tracker->get_joy_id(); }; -bool ARVRController::is_button_pressed(int p_button) const { +bool XRController3D::is_button_pressed(int p_button) const { int joy_id = get_joystick_id(); if (joy_id == -1) { 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 ARVRController::get_joystick_axis(int p_axis) const { +float XRController3D::get_joystick_axis(int p_axis) const { int joy_id = get_joystick_id(); if (joy_id == -1) { 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 ARVRController::get_rumble() const { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, 0.0); +real_t XRController3D::get_rumble() const { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, 0.0); - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); - if (tracker == NULL) { + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (tracker == nullptr) { return 0.0; }; return tracker->get_rumble(); }; -void ARVRController::set_rumble(real_t p_rumble) { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL(arvr_server); +void XRController3D::set_rumble(real_t p_rumble) { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); - if (tracker != NULL) { + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (tracker != nullptr) { tracker->set_rumble(p_rumble); }; }; -Ref<Mesh> ARVRController::get_mesh() const { +Ref<Mesh> XRController3D::get_mesh() const { return mesh; } -bool ARVRController::get_is_active() const { +bool XRController3D::get_is_active() const { return is_active; }; -ARVRPositionalTracker::TrackerHand ARVRController::get_hand() const { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, ARVRPositionalTracker::TRACKER_HAND_UNKNOWN); +XRPositionalTracker::TrackerHand XRController3D::get_hand() const { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, XRPositionalTracker::TRACKER_HAND_UNKNOWN); - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); - if (tracker == NULL) { - return ARVRPositionalTracker::TRACKER_HAND_UNKNOWN; + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (tracker == nullptr) { + return XRPositionalTracker::TRACKER_HAND_UNKNOWN; }; return tracker->get_hand(); }; -String ARVRController::get_configuration_warning() const { - if (!is_visible() || !is_inside_tree()) +String XRController3D::get_configuration_warning() const { + if (!is_visible() || !is_inside_tree()) { return String(); + } - // must be child node of ARVROrigin! - ARVROrigin *origin = Object::cast_to<ARVROrigin>(get_parent()); - if (origin == NULL) { - return TTR("ARVRController must have an ARVROrigin node as its parent."); + // 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 (controller_id == 0) { @@ -380,19 +375,9 @@ String ARVRController::get_configuration_warning() const { return String(); }; -ARVRController::ARVRController() { - controller_id = 1; - is_active = true; - button_states = 0; -}; - -ARVRController::~ARVRController(){ - // nothing to do here yet for now.. -}; - //////////////////////////////////////////////////////////////////////////////////////////////////// -void ARVRAnchor::_notification(int p_what) { +void XRAnchor3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { set_process_internal(true); @@ -401,13 +386,13 @@ void ARVRAnchor::_notification(int p_what) { set_process_internal(false); }; break; case NOTIFICATION_INTERNAL_PROCESS: { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL(arvr_server); + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); // find the tracker for our anchor - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_ANCHOR, anchor_id); - if (tracker == NULL) { + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_ANCHOR, anchor_id); + if (tracker == nullptr) { // this anchor is currently not available is_active = false; } else { @@ -415,7 +400,7 @@ void ARVRAnchor::_notification(int p_what) { Transform transform; // we'll need our world_scale - real_t world_scale = arvr_server->get_world_scale(); + real_t world_scale = xr_server->get_world_scale(); // get our info from our tracker transform.basis = tracker->get_orientation(); @@ -427,7 +412,7 @@ void ARVRAnchor::_notification(int p_what) { transform.basis.orthonormalize(); // apply our reference frame and set our transform - set_transform(arvr_server->get_reference_frame() * transform); + set_transform(xr_server->get_reference_frame() * transform); // check for an updated mesh Ref<Mesh> trackerMesh = tracker->get_mesh(); @@ -442,62 +427,62 @@ void ARVRAnchor::_notification(int p_what) { }; }; -void ARVRAnchor::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_anchor_id", "anchor_id"), &ARVRAnchor::set_anchor_id); - ClassDB::bind_method(D_METHOD("get_anchor_id"), &ARVRAnchor::get_anchor_id); +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"); - ClassDB::bind_method(D_METHOD("get_anchor_name"), &ARVRAnchor::get_anchor_name); + ClassDB::bind_method(D_METHOD("get_anchor_name"), &XRAnchor3D::get_anchor_name); - ClassDB::bind_method(D_METHOD("get_is_active"), &ARVRAnchor::get_is_active); - ClassDB::bind_method(D_METHOD("get_size"), &ARVRAnchor::get_size); + ClassDB::bind_method(D_METHOD("get_is_active"), &XRAnchor3D::get_is_active); + ClassDB::bind_method(D_METHOD("get_size"), &XRAnchor3D::get_size); - ClassDB::bind_method(D_METHOD("get_plane"), &ARVRAnchor::get_plane); + ClassDB::bind_method(D_METHOD("get_plane"), &XRAnchor3D::get_plane); - ClassDB::bind_method(D_METHOD("get_mesh"), &ARVRAnchor::get_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &XRAnchor3D::get_mesh); ADD_SIGNAL(MethodInfo("mesh_updated", PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"))); }; -void ARVRAnchor::set_anchor_id(int p_anchor_id) { +void XRAnchor3D::set_anchor_id(int p_anchor_id) { // We don't check any bounds here, this anchor may not yet be active and just be a place holder until it is. // Note that setting this to 0 means this node is not bound to an anchor yet. anchor_id = p_anchor_id; update_configuration_warning(); }; -int ARVRAnchor::get_anchor_id(void) const { +int XRAnchor3D::get_anchor_id() const { return anchor_id; }; -Vector3 ARVRAnchor::get_size() const { +Vector3 XRAnchor3D::get_size() const { return size; }; -String ARVRAnchor::get_anchor_name(void) const { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, String()); +String XRAnchor3D::get_anchor_name() const { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, String()); - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_ANCHOR, anchor_id); - if (tracker == NULL) { + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_ANCHOR, anchor_id); + if (tracker == nullptr) { return String("Not connected"); }; return tracker->get_name(); }; -bool ARVRAnchor::get_is_active() const { +bool XRAnchor3D::get_is_active() const { return is_active; }; -String ARVRAnchor::get_configuration_warning() const { - if (!is_visible() || !is_inside_tree()) +String XRAnchor3D::get_configuration_warning() const { + if (!is_visible() || !is_inside_tree()) { return String(); + } - // must be child node of ARVROrigin! - ARVROrigin *origin = Object::cast_to<ARVROrigin>(get_parent()); - if (origin == NULL) { - return TTR("ARVRAnchor must have an ARVROrigin node as its parent."); + // 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 (anchor_id == 0) { @@ -507,7 +492,7 @@ String ARVRAnchor::get_configuration_warning() const { return String(); }; -Plane ARVRAnchor::get_plane() const { +Plane XRAnchor3D::get_plane() const { Vector3 location = get_translation(); Basis orientation = get_transform().basis; @@ -516,67 +501,60 @@ Plane ARVRAnchor::get_plane() const { return plane; }; -Ref<Mesh> ARVRAnchor::get_mesh() const { +Ref<Mesh> XRAnchor3D::get_mesh() const { return mesh; } -ARVRAnchor::ARVRAnchor() { - anchor_id = 1; - is_active = true; -}; - -ARVRAnchor::~ARVRAnchor(){ - // nothing to do here yet for now.. -}; - //////////////////////////////////////////////////////////////////////////////////////////////////// -String ARVROrigin::get_configuration_warning() const { - if (!is_visible() || !is_inside_tree()) +String XROrigin3D::get_configuration_warning() const { + if (!is_visible() || !is_inside_tree()) { return String(); + } - if (tracked_camera == NULL) - return TTR("ARVROrigin requires an ARVRCamera child node."); + if (tracked_camera == nullptr) { + return TTR("XROrigin3D requires an XRCamera3D child node."); + } return String(); }; -void ARVROrigin::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_world_scale", "world_scale"), &ARVROrigin::set_world_scale); - ClassDB::bind_method(D_METHOD("get_world_scale"), &ARVROrigin::get_world_scale); +void XROrigin3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_world_scale", "world_scale"), &XROrigin3D::set_world_scale); + ClassDB::bind_method(D_METHOD("get_world_scale"), &XROrigin3D::get_world_scale); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale"); }; -void ARVROrigin::set_tracked_camera(ARVRCamera *p_tracked_camera) { +void XROrigin3D::set_tracked_camera(XRCamera3D *p_tracked_camera) { tracked_camera = p_tracked_camera; }; -void ARVROrigin::clear_tracked_camera_if(ARVRCamera *p_tracked_camera) { +void XROrigin3D::clear_tracked_camera_if(XRCamera3D *p_tracked_camera) { if (tracked_camera == p_tracked_camera) { - tracked_camera = NULL; + tracked_camera = nullptr; }; }; -float ARVROrigin::get_world_scale() const { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, 1.0); +float XROrigin3D::get_world_scale() const { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, 1.0); - return arvr_server->get_world_scale(); + return xr_server->get_world_scale(); }; -void ARVROrigin::set_world_scale(float p_world_scale) { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL(arvr_server); +void XROrigin3D::set_world_scale(float p_world_scale) { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); - arvr_server->set_world_scale(p_world_scale); + xr_server->set_world_scale(p_world_scale); }; -void ARVROrigin::_notification(int p_what) { - // get our ARVRServer - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL(arvr_server); +void XROrigin3D::_notification(int p_what) { + // get our XRServer + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -587,13 +565,13 @@ void ARVROrigin::_notification(int p_what) { }; break; case NOTIFICATION_INTERNAL_PROCESS: { // set our world origin to our node transform - arvr_server->set_world_origin(get_global_transform()); + xr_server->set_world_origin(get_global_transform()); // check if we have a primary interface - Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface(); - if (arvr_interface.is_valid() && tracked_camera != NULL) { + Ref<XRInterface> xr_interface = xr_server->get_primary_interface(); + if (xr_interface.is_valid() && tracked_camera != nullptr) { // get our positioning transform for our headset - Transform t = arvr_interface->get_transform_for_eye(ARVRInterface::EYE_MONO, Transform()); + Transform t = xr_interface->get_transform_for_eye(XRInterface::EYE_MONO, Transform()); // now apply this to our camera tracked_camera->set_transform(t); @@ -603,19 +581,11 @@ void ARVROrigin::_notification(int p_what) { break; }; - // send our notification to all active ARVR interfaces, they may need to react to it also - for (int i = 0; i < arvr_server->get_interface_count(); i++) { - Ref<ARVRInterface> interface = arvr_server->get_interface(i); + // send our notification to all active XE interfaces, they may need to react to it also + for (int i = 0; i < xr_server->get_interface_count(); i++) { + Ref<XRInterface> interface = xr_server->get_interface(i); if (interface.is_valid() && interface->is_initialized()) { interface->notification(p_what); } } }; - -ARVROrigin::ARVROrigin() { - tracked_camera = NULL; -}; - -ARVROrigin::~ARVROrigin(){ - // nothing to do here yet for now.. -}; diff --git a/scene/3d/arvr_nodes.h b/scene/3d/xr_nodes.h index bc5df2e174..4d4f82aa38 100644 --- a/scene/3d/arvr_nodes.h +++ b/scene/3d/xr_nodes.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* arvr_nodes.h */ +/* xr_nodes.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,24 +28,23 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef ARVR_NODES_H -#define ARVR_NODES_H +#ifndef XR_NODES_H +#define XR_NODES_H #include "scene/3d/camera_3d.h" #include "scene/3d/node_3d.h" #include "scene/resources/mesh.h" -#include "servers/arvr/arvr_positional_tracker.h" +#include "servers/xr/xr_positional_tracker.h" /** @author Bastiaan Olij <mux213@gmail.com> **/ /* - ARVRCamera is a subclass of camera which will register itself with its parent ARVROrigin and as a result is automatically positioned + XRCamera is a subclass of camera which will register itself with its parent XROrigin and as a result is automatically positioned */ -class ARVRCamera : public Camera3D { - - GDCLASS(ARVRCamera, Camera3D); +class XRCamera3D : public Camera3D { + GDCLASS(XRCamera3D, Camera3D); protected: void _notification(int p_what); @@ -58,24 +57,23 @@ public: virtual Vector3 project_position(const Point2 &p_point, float p_z_depth) const; virtual Vector<Plane> get_frustum() const; - ARVRCamera(); - ~ARVRCamera(); + XRCamera3D() {} + ~XRCamera3D() {} }; /* - ARVRController is a helper node that automatically updates its position based on tracker data. + XRController3D is a helper node that automatically updates its position based on tracker data. - It must be a child node of our ARVROrigin node + It must be a child node of our XROrigin node */ -class ARVRController : public Node3D { - - GDCLASS(ARVRController, Node3D); +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; @@ -95,27 +93,27 @@ public: void set_rumble(real_t p_rumble); bool get_is_active() const; - ARVRPositionalTracker::TrackerHand get_hand() const; + XRPositionalTracker::TrackerHand get_hand() const; - Ref<Mesh> get_mesh(void) const; + Ref<Mesh> get_mesh() const; String get_configuration_warning() const; - ARVRController(); - ~ARVRController(); + XRController3D() {} + ~XRController3D() {} }; /* - ARVRAnchor is a helper node that automatically updates its position based on anchor data, it represents a real world location. - It must be a child node of our ARVROrigin node + XRAnchor3D is a helper node that automatically updates its position based on anchor data, it represents a real world location. + It must be a child node of our XROrigin3D node */ -class ARVRAnchor : public Node3D { - GDCLASS(ARVRAnchor, Node3D); +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,36 +123,35 @@ 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; - ARVRAnchor(); - ~ARVRAnchor(); + XRAnchor3D() {} + ~XRAnchor3D() {} }; /* - ARVROrigin is special spatial node that acts as our origin point mapping our real world center of our tracking volume into our virtual world. + XROrigin3D is special spatial node that acts as our origin point mapping our real world center of our tracking volume into our virtual world. It is this point that you will move around the world as the player 'moves while standing still', i.e. the player moves through teleporting or controller inputs as opposed to physically moving. Our camera and controllers will always be child nodes and thus place relative to this origin point. - This node will automatically locate any camera child nodes and update its position while our ARVRController node will handle tracked controllers. + This node will automatically locate any camera child nodes and update its position while our XRController3D node will handle tracked controllers. */ -class ARVROrigin : public Node3D { - - GDCLASS(ARVROrigin, Node3D); +class XROrigin3D : public Node3D { + GDCLASS(XROrigin3D, Node3D); private: - ARVRCamera *tracked_camera; + XRCamera3D *tracked_camera = nullptr; protected: void _notification(int p_what); @@ -163,14 +160,14 @@ protected: public: String get_configuration_warning() const; - void set_tracked_camera(ARVRCamera *p_tracked_camera); - void clear_tracked_camera_if(ARVRCamera *p_tracked_camera); + void set_tracked_camera(XRCamera3D *p_tracked_camera); + void clear_tracked_camera_if(XRCamera3D *p_tracked_camera); float get_world_scale() const; void set_world_scale(float p_world_scale); - ARVROrigin(); - ~ARVROrigin(); + XROrigin3D() {} + ~XROrigin3D() {} }; -#endif /* ARVR_NODES_H */ +#endif /* XR_NODES_H */ |