diff options
Diffstat (limited to 'scene/3d')
-rw-r--r-- | scene/3d/audio_stream_player_3d.cpp | 2 | ||||
-rw-r--r-- | scene/3d/cpu_particles_3d.cpp | 6 | ||||
-rw-r--r-- | scene/3d/gpu_particles_3d.cpp | 6 | ||||
-rw-r--r-- | scene/3d/lightmap_gi.cpp | 2 | ||||
-rw-r--r-- | scene/3d/lightmapper.h | 1 | ||||
-rw-r--r-- | scene/3d/look_at_modifier_3d.cpp | 60 | ||||
-rw-r--r-- | scene/3d/look_at_modifier_3d.h | 8 | ||||
-rw-r--r-- | scene/3d/physics/collision_shape_3d.cpp | 98 | ||||
-rw-r--r-- | scene/3d/physics/collision_shape_3d.h | 22 | ||||
-rw-r--r-- | scene/3d/voxel_gi.cpp | 49 | ||||
-rw-r--r-- | scene/3d/voxel_gi.h | 4 | ||||
-rw-r--r-- | scene/3d/voxelizer.cpp | 71 | ||||
-rw-r--r-- | scene/3d/voxelizer.h | 14 |
13 files changed, 304 insertions, 39 deletions
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 98bee2115c..eb75650399 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -834,7 +834,7 @@ void AudioStreamPlayer3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater"), "set_unit_size", "get_unit_size"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_db", PROPERTY_HINT_RANGE, "-24,6,suffix:dB"), "set_max_db", "get_max_db"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,4,0.01,or_greater"), "set_pitch_scale", "get_pitch_scale"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_playing", "is_playing"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_ONESHOT, "", PROPERTY_USAGE_EDITOR), "set_playing", "is_playing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,or_greater,suffix:m"), "set_max_distance", "get_max_distance"); diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index 5b84bf903f..4424032653 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -543,6 +543,10 @@ AABB CPUParticles3D::capture_aabb() const { } void CPUParticles3D::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "emitting") { + p_property.hint = one_shot ? PROPERTY_HINT_ONESHOT : PROPERTY_HINT_NONE; + } + if (p_property.name == "emission_sphere_radius" && (emission_shape != EMISSION_SHAPE_SPHERE && emission_shape != EMISSION_SHAPE_SPHERE_SURFACE)) { p_property.usage = PROPERTY_USAGE_NONE; } @@ -1481,7 +1485,7 @@ void CPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("restart"), &CPUParticles3D::restart); ClassDB::bind_method(D_METHOD("capture_aabb"), &CPUParticles3D::capture_aabb); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp,suffix:s"), "set_lifetime", "get_lifetime"); diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index b48a3a87c7..760409d9a0 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -414,6 +414,10 @@ AABB GPUParticles3D::capture_aabb() const { } void GPUParticles3D::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "emitting") { + p_property.hint = one_shot ? PROPERTY_HINT_ONESHOT : PROPERTY_HINT_NONE; + } + if (p_property.name.begins_with("draw_pass_")) { int index = p_property.name.get_slicec('_', 2).to_int() - 1; if (index >= draw_passes.size()) { @@ -744,7 +748,7 @@ void GPUParticles3D::_bind_methods() { ADD_SIGNAL(MethodInfo("finished")); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting"); ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false. ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amount_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001"), "set_amount_ratio", "get_amount_ratio"); diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index cdbd95d930..aa4445a7ba 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -1189,6 +1189,8 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa return BAKE_ERROR_MESHES_INVALID; } else if (bake_err == Lightmapper::BAKE_ERROR_ATLAS_TOO_SMALL) { return BAKE_ERROR_ATLAS_TOO_SMALL; + } else if (bake_err == Lightmapper::BAKE_ERROR_USER_ABORTED) { + return BAKE_ERROR_USER_ABORTED; } // POSTBAKE: Save Textures. diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h index 9aa8ef8ccb..1228c63edc 100644 --- a/scene/3d/lightmapper.h +++ b/scene/3d/lightmapper.h @@ -147,6 +147,7 @@ public: BAKE_ERROR_TEXTURE_EXCEEDS_MAX_SIZE, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES, BAKE_ERROR_ATLAS_TOO_SMALL, + BAKE_ERROR_USER_ABORTED, }; enum BakeQuality { diff --git a/scene/3d/look_at_modifier_3d.cpp b/scene/3d/look_at_modifier_3d.cpp index 8aa6a3f9c3..47a8a9050e 100644 --- a/scene/3d/look_at_modifier_3d.cpp +++ b/scene/3d/look_at_modifier_3d.cpp @@ -33,7 +33,7 @@ void LookAtModifier3D::_validate_property(PropertyInfo &p_property) const { SkeletonModifier3D::_validate_property(p_property); - if (p_property.name == "bone" || p_property.name == "origin_bone") { + if (p_property.name == "bone_name" || p_property.name == "origin_bone_name") { Skeleton3D *skeleton = get_skeleton(); if (skeleton) { p_property.hint = PROPERTY_HINT_ENUM; @@ -49,11 +49,11 @@ void LookAtModifier3D::_validate_property(PropertyInfo &p_property) const { p_property.usage = PROPERTY_USAGE_NONE; } } else if (origin_from == ORIGIN_FROM_EXTERNAL_NODE) { - if (p_property.name == "origin_bone") { + if (p_property.name == "origin_bone" || p_property.name == "origin_bone_name") { p_property.usage = PROPERTY_USAGE_NONE; } } else { - if (p_property.name == "origin_external_node" || p_property.name == "origin_bone") { + if (p_property.name == "origin_external_node" || p_property.name == "origin_bone" || p_property.name == "origin_bone_name") { p_property.usage = PROPERTY_USAGE_NONE; } } @@ -75,8 +75,29 @@ PackedStringArray LookAtModifier3D::get_configuration_warnings() const { return warnings; } +void LookAtModifier3D::set_bone_name(const String &p_bone_name) { + bone_name = p_bone_name; + Skeleton3D *sk = get_skeleton(); + if (sk) { + set_bone(sk->find_bone(bone_name)); + } +} + +String LookAtModifier3D::get_bone_name() const { + return bone_name; +} + void LookAtModifier3D::set_bone(int p_bone) { bone = p_bone; + Skeleton3D *sk = get_skeleton(); + if (sk) { + if (bone <= -1 || bone >= sk->get_bone_count()) { + WARN_PRINT("Bone index out of range!"); + bone = -1; + } else { + bone_name = sk->get_bone_name(bone); + } + } } int LookAtModifier3D::get_bone() const { @@ -132,8 +153,29 @@ LookAtModifier3D::OriginFrom LookAtModifier3D::get_origin_from() const { return origin_from; } +void LookAtModifier3D::set_origin_bone_name(const String &p_bone_name) { + origin_bone_name = p_bone_name; + Skeleton3D *sk = get_skeleton(); + if (sk) { + set_origin_bone(sk->find_bone(origin_bone_name)); + } +} + +String LookAtModifier3D::get_origin_bone_name() const { + return origin_bone_name; +} + void LookAtModifier3D::set_origin_bone(int p_bone) { origin_bone = p_bone; + Skeleton3D *sk = get_skeleton(); + if (sk) { + if (origin_bone <= -1 || origin_bone >= sk->get_bone_count()) { + WARN_PRINT("Bone index out of range!"); + origin_bone = -1; + } else { + origin_bone_name = sk->get_bone_name(origin_bone); + } + } } int LookAtModifier3D::get_origin_bone() const { @@ -330,6 +372,8 @@ void LookAtModifier3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_target_node", "target_node"), &LookAtModifier3D::set_target_node); ClassDB::bind_method(D_METHOD("get_target_node"), &LookAtModifier3D::get_target_node); + ClassDB::bind_method(D_METHOD("set_bone_name", "bone_name"), &LookAtModifier3D::set_bone_name); + ClassDB::bind_method(D_METHOD("get_bone_name"), &LookAtModifier3D::get_bone_name); ClassDB::bind_method(D_METHOD("set_bone", "bone"), &LookAtModifier3D::set_bone); ClassDB::bind_method(D_METHOD("get_bone"), &LookAtModifier3D::get_bone); ClassDB::bind_method(D_METHOD("set_forward_axis", "forward_axis"), &LookAtModifier3D::set_forward_axis); @@ -343,6 +387,8 @@ void LookAtModifier3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_origin_from", "origin_from"), &LookAtModifier3D::set_origin_from); ClassDB::bind_method(D_METHOD("get_origin_from"), &LookAtModifier3D::get_origin_from); + ClassDB::bind_method(D_METHOD("set_origin_bone_name", "bone_name"), &LookAtModifier3D::set_origin_bone_name); + ClassDB::bind_method(D_METHOD("get_origin_bone_name"), &LookAtModifier3D::get_origin_bone_name); ClassDB::bind_method(D_METHOD("set_origin_bone", "bone"), &LookAtModifier3D::set_origin_bone); ClassDB::bind_method(D_METHOD("get_origin_bone"), &LookAtModifier3D::get_origin_bone); ClassDB::bind_method(D_METHOD("set_origin_external_node", "external_node"), &LookAtModifier3D::set_origin_external_node); @@ -397,14 +443,16 @@ void LookAtModifier3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_node", PROPERTY_HINT_NODE_TYPE, "Node3D"), "set_target_node", "get_target_node"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "bone", PROPERTY_HINT_ENUM, ""), "set_bone", "get_bone"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "bone_name", PROPERTY_HINT_ENUM_SUGGESTION, ""), "set_bone_name", "get_bone_name"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_bone", "get_bone"); ADD_PROPERTY(PropertyInfo(Variant::INT, "forward_axis", PROPERTY_HINT_ENUM, "+X,-X,+Y,-Y,+Z,-Z"), "set_forward_axis", "get_forward_axis"); ADD_PROPERTY(PropertyInfo(Variant::INT, "primary_rotation_axis", PROPERTY_HINT_ENUM, "X,Y,Z"), "set_primary_rotation_axis", "get_primary_rotation_axis"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_secondary_rotation"), "set_use_secondary_rotation", "is_using_secondary_rotation"); ADD_GROUP("Origin Settings", "origin_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "origin_from", PROPERTY_HINT_ENUM, "Self,SpecificBone,ExternalNode"), "set_origin_from", "get_origin_from"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "origin_bone", PROPERTY_HINT_ENUM, ""), "set_origin_bone", "get_origin_bone"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "origin_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, ""), "set_origin_bone_name", "get_origin_bone_name"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "origin_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_origin_bone", "get_origin_bone"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "origin_external_node", PROPERTY_HINT_NODE_TYPE, "Node3D"), "set_origin_external_node", "get_origin_external_node"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "origin_offset"), "set_origin_offset", "get_origin_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "origin_safe_margin", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater,suffix:m"), "set_origin_safe_margin", "get_origin_safe_margin"); @@ -474,7 +522,7 @@ void LookAtModifier3D::_process_modification() { destination = skeleton->get_bone_pose_rotation(bone); } else { Transform3D origin_tr; - if (origin_from == ORIGIN_FROM_SPECIFIC_BONE && origin_bone < skeleton->get_bone_count()) { + if (origin_from == ORIGIN_FROM_SPECIFIC_BONE && origin_bone >= 0 && origin_bone < skeleton->get_bone_count()) { origin_tr = skeleton->get_global_transform() * skeleton->get_bone_global_pose(origin_bone); } else if (origin_from == ORIGIN_FROM_EXTERNAL_NODE) { Node3D *origin_src = Object::cast_to<Node3D>(get_node_or_null(origin_external_node)); diff --git a/scene/3d/look_at_modifier_3d.h b/scene/3d/look_at_modifier_3d.h index 5f3c4e8b1c..9329edf3c9 100644 --- a/scene/3d/look_at_modifier_3d.h +++ b/scene/3d/look_at_modifier_3d.h @@ -54,7 +54,8 @@ public: }; private: - int bone = 0; + String bone_name; + int bone = -1; Vector3 forward_vector; Vector3 forward_vector_nrm; @@ -64,6 +65,7 @@ private: bool use_secondary_rotation = true; OriginFrom origin_from = ORIGIN_FROM_SELF; + String origin_bone_name; int origin_bone = -1; NodePath origin_external_node; @@ -123,6 +125,8 @@ protected: virtual void _process_modification() override; public: + void set_bone_name(const String &p_bone_name); + String get_bone_name() const; void set_bone(int p_bone); int get_bone() const; @@ -135,6 +139,8 @@ public: void set_origin_from(OriginFrom p_origin_from); OriginFrom get_origin_from() const; + void set_origin_bone_name(const String &p_bone_name); + String get_origin_bone_name() const; void set_origin_bone(int p_bone); int get_origin_bone() const; void set_origin_external_node(const NodePath &p_external_node); diff --git a/scene/3d/physics/collision_shape_3d.cpp b/scene/3d/physics/collision_shape_3d.cpp index 304fa74b06..362c61026b 100644 --- a/scene/3d/physics/collision_shape_3d.cpp +++ b/scene/3d/physics/collision_shape_3d.cpp @@ -81,12 +81,19 @@ void CollisionShape3D::_update_in_shape_owner(bool p_xform_only) { void CollisionShape3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_PARENTED: { +#ifdef DEBUG_ENABLED + if (debug_color == get_placeholder_default_color()) { + debug_color = SceneTree::get_singleton()->get_debug_collisions_color(); + } +#endif // DEBUG_ENABLED + collision_object = Object::cast_to<CollisionObject3D>(get_parent()); if (collision_object) { owner_id = collision_object->create_shape_owner(this); if (shape.is_valid()) { collision_object->shape_owner_add_shape(owner_id, shape); } + _update_in_shape_owner(); } } break; @@ -166,11 +173,26 @@ void CollisionShape3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape3D::get_shape); ClassDB::bind_method(D_METHOD("set_disabled", "enable"), &CollisionShape3D::set_disabled); ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape3D::is_disabled); + ClassDB::bind_method(D_METHOD("make_convex_from_siblings"), &CollisionShape3D::make_convex_from_siblings); ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_siblings", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); + +#ifdef DEBUG_ENABLED + ClassDB::bind_method(D_METHOD("set_debug_color", "color"), &CollisionShape3D::set_debug_color); + ClassDB::bind_method(D_METHOD("get_debug_color"), &CollisionShape3D::get_debug_color); + + ClassDB::bind_method(D_METHOD("set_enable_debug_fill", "enable"), &CollisionShape3D::set_debug_fill_enabled); + ClassDB::bind_method(D_METHOD("get_enable_debug_fill"), &CollisionShape3D::get_debug_fill_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_color"), "set_debug_color", "get_debug_color"); + // Default value depends on a project setting, override for doc generation purposes. + ADD_PROPERTY_DEFAULT("debug_color", get_placeholder_default_color()); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_fill"), "set_enable_debug_fill", "get_enable_debug_fill"); +#endif // DEBUG_ENABLED } void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) { @@ -178,11 +200,27 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) { return; } if (shape.is_valid()) { + shape->disconnect_changed(callable_mp(this, &CollisionShape3D::shape_changed)); shape->disconnect_changed(callable_mp((Node3D *)this, &Node3D::update_gizmos)); } shape = p_shape; if (shape.is_valid()) { +#ifdef DEBUG_ENABLED + if (shape->get_debug_color() != get_placeholder_default_color()) { + set_debug_color(shape->get_debug_color()); + set_debug_fill_enabled(shape->get_debug_fill()); + } else if (get_debug_color() != get_placeholder_default_color()) { + shape->set_debug_color(debug_color); + shape->set_debug_fill(debug_fill); + } else { + set_debug_color(SceneTree::get_singleton()->get_debug_collisions_color()); + shape->set_debug_color(SceneTree::get_singleton()->get_debug_collisions_color()); + shape->set_debug_fill(debug_fill); + } +#endif // DEBUG_ENABLED + shape->connect_changed(callable_mp((Node3D *)this, &Node3D::update_gizmos)); + shape->connect_changed(callable_mp(this, &CollisionShape3D::shape_changed)); } update_gizmos(); if (collision_object) { @@ -215,6 +253,66 @@ bool CollisionShape3D::is_disabled() const { return disabled; } +#ifdef DEBUG_ENABLED +void CollisionShape3D::set_debug_color(const Color &p_color) { + if (p_color == get_placeholder_default_color()) { + debug_color = SceneTree::get_singleton()->get_debug_collisions_color(); + } else if (debug_color != p_color) { + debug_color = p_color; + + if (shape.is_valid()) { + shape->set_debug_color(p_color); + } + } +} + +Color CollisionShape3D::get_debug_color() const { + return debug_color; +} + +void CollisionShape3D::set_debug_fill_enabled(bool p_enable) { + if (debug_fill == p_enable) { + return; + } + + debug_fill = p_enable; + + if (shape.is_valid()) { + shape->set_debug_fill(p_enable); + } +} + +bool CollisionShape3D::get_debug_fill_enabled() const { + return debug_fill; +} + +bool CollisionShape3D::_property_can_revert(const StringName &p_name) const { + if (p_name == "debug_color") { + return true; + } + return false; +} + +bool CollisionShape3D::_property_get_revert(const StringName &p_name, Variant &r_property) const { + if (p_name == "debug_color") { + r_property = SceneTree::get_singleton()->get_debug_collisions_color(); + return true; + } + return false; +} +#endif // DEBUG_ENABLED + +void CollisionShape3D::shape_changed() { +#ifdef DEBUG_ENABLED + if (shape->get_debug_color() != debug_color) { + set_debug_color(shape->get_debug_color()); + } + if (shape->get_debug_fill() != debug_fill) { + set_debug_fill_enabled(shape->get_debug_fill()); + } +#endif // DEBUG_ENABLED +} + CollisionShape3D::CollisionShape3D() { //indicator = RenderingServer::get_singleton()->mesh_create(); set_notify_local_transform(true); diff --git a/scene/3d/physics/collision_shape_3d.h b/scene/3d/physics/collision_shape_3d.h index 15f6ef73cb..0eaecb9f61 100644 --- a/scene/3d/physics/collision_shape_3d.h +++ b/scene/3d/physics/collision_shape_3d.h @@ -43,6 +43,13 @@ class CollisionShape3D : public Node3D { uint32_t owner_id = 0; CollisionObject3D *collision_object = nullptr; +#ifdef DEBUG_ENABLED + Color debug_color = get_placeholder_default_color(); + bool debug_fill = true; + + static const Color get_placeholder_default_color() { return Color(0.0, 0.0, 0.0, 0.0); } +#endif // DEBUG_ENABLED + #ifndef DISABLE_DEPRECATED void resource_changed(Ref<Resource> res); #endif @@ -55,6 +62,13 @@ protected: void _notification(int p_what); static void _bind_methods(); +#ifdef DEBUG_ENABLED + bool _property_can_revert(const StringName &p_name) const; + bool _property_get_revert(const StringName &p_name, Variant &r_property) const; +#endif // DEBUG_ENABLED + + void shape_changed(); + public: void make_convex_from_siblings(); @@ -64,6 +78,14 @@ public: void set_disabled(bool p_disabled); bool is_disabled() const; +#ifdef DEBUG_ENABLED + void set_debug_color(const Color &p_color); + Color get_debug_color() const; + + void set_debug_fill_enabled(bool p_enable); + bool get_debug_fill_enabled() const; +#endif // DEBUG_ENABLED + PackedStringArray get_configuration_warnings() const override; CollisionShape3D(); diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index 80ff176a98..5fec7021eb 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -389,6 +389,17 @@ VoxelGI::BakeBeginFunc VoxelGI::bake_begin_function = nullptr; VoxelGI::BakeStepFunc VoxelGI::bake_step_function = nullptr; VoxelGI::BakeEndFunc VoxelGI::bake_end_function = nullptr; +static int voxelizer_plot_bake_base = 0; +static int voxelizer_plot_bake_total = 0; + +static bool voxelizer_plot_bake_step_function(int current, int) { + return VoxelGI::bake_step_function((voxelizer_plot_bake_base + current) * 500 / voxelizer_plot_bake_total, RTR("Plotting Meshes")); +} + +static bool voxelizer_sdf_bake_step_function(int current, int total) { + return VoxelGI::bake_step_function(500 + current * 500 / total, RTR("Generating Distance Field")); +} + Vector3i VoxelGI::get_estimated_cell_size() const { static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 }; int cell_subdiv = subdiv_value[subdiv]; @@ -432,22 +443,27 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) { _find_meshes(p_from_node, mesh_list); if (bake_begin_function) { - bake_begin_function(mesh_list.size() + 1); + bake_begin_function(); } - int pmc = 0; + Voxelizer::BakeStepFunc voxelizer_step_func = bake_step_function != nullptr ? voxelizer_plot_bake_step_function : nullptr; + voxelizer_plot_bake_total = voxelizer_plot_bake_base = 0; for (PlotMesh &E : mesh_list) { - if (bake_step_function) { - bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(mesh_list.size())); + voxelizer_plot_bake_total += baker.get_bake_steps(E.mesh); + } + for (PlotMesh &E : mesh_list) { + if (baker.plot_mesh(E.local_xform, E.mesh, E.instance_materials, E.override_material, voxelizer_step_func) != Voxelizer::BAKE_RESULT_OK) { + baker.end_bake(); + if (bake_end_function) { + bake_end_function(); + } + return; } - - pmc++; - - baker.plot_mesh(E.local_xform, E.mesh, E.instance_materials, E.override_material); + voxelizer_plot_bake_base += baker.get_bake_steps(E.mesh); } if (bake_step_function) { - bake_step_function(pmc++, RTR("Finishing Plot")); + bake_step_function(500, RTR("Finishing Plot")); } baker.end_bake(); @@ -476,19 +492,22 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) { } if (bake_step_function) { - bake_step_function(pmc++, RTR("Generating Distance Field")); + bake_step_function(500, RTR("Generating Distance Field")); } - Vector<uint8_t> df = baker.get_sdf_3d_image(); + voxelizer_step_func = bake_step_function != nullptr ? voxelizer_sdf_bake_step_function : nullptr; - RS::get_singleton()->voxel_gi_set_baked_exposure_normalization(probe_data_new->get_rid(), exposure_normalization); + Vector<uint8_t> df; + if (baker.get_sdf_3d_image(df, voxelizer_step_func) == Voxelizer::BAKE_RESULT_OK) { + RS::get_singleton()->voxel_gi_set_baked_exposure_normalization(probe_data_new->get_rid(), exposure_normalization); - probe_data_new->allocate(baker.get_to_cell_space_xform(), AABB(-size / 2, size), baker.get_voxel_gi_octree_size(), baker.get_voxel_gi_octree_cells(), baker.get_voxel_gi_data_cells(), df, baker.get_voxel_gi_level_cell_count()); + probe_data_new->allocate(baker.get_to_cell_space_xform(), AABB(-size / 2, size), baker.get_voxel_gi_octree_size(), baker.get_voxel_gi_octree_cells(), baker.get_voxel_gi_data_cells(), df, baker.get_voxel_gi_level_cell_count()); - set_probe_data(probe_data_new); + set_probe_data(probe_data_new); #ifdef TOOLS_ENABLED - probe_data_new->set_edited(true); //so it gets saved + probe_data_new->set_edited(true); //so it gets saved #endif + } } if (bake_end_function) { diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h index 7d7787f721..d7e0d74d36 100644 --- a/scene/3d/voxel_gi.h +++ b/scene/3d/voxel_gi.h @@ -108,8 +108,8 @@ public: }; - typedef void (*BakeBeginFunc)(int); - typedef void (*BakeStepFunc)(int, const String &); + typedef void (*BakeBeginFunc)(); + typedef bool (*BakeStepFunc)(int, const String &); typedef void (*BakeEndFunc)(); private: diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index 99392e9ba0..1074cad11e 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -382,8 +382,24 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material return mc; } -void Voxelizer::plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material) { - ERR_FAIL_COND_MSG(!p_xform.is_finite(), "Invalid mesh bake transform."); +int Voxelizer::get_bake_steps(Ref<Mesh> &p_mesh) const { + int bake_total = 0; + for (int i = 0; i < p_mesh->get_surface_count(); i++) { + if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { + continue; // Only triangles. + } + Array a = p_mesh->surface_get_arrays(i); + Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; + Vector<int> index = a[Mesh::ARRAY_INDEX]; + bake_total += (index.size() > 0 ? index.size() : vertices.size()) / 3; + } + return bake_total; +} + +Voxelizer::BakeResult Voxelizer::plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material, BakeStepFunc p_bake_step_func) { + ERR_FAIL_COND_V_MSG(!p_xform.is_finite(), BAKE_RESULT_INVALID_PARAMETER, "Invalid mesh bake transform."); + + int bake_total = get_bake_steps(p_mesh), bake_current = 0; for (int i = 0; i < p_mesh->get_surface_count(); i++) { if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { @@ -428,6 +444,13 @@ void Voxelizer::plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const V Vector2 uvs[3]; Vector3 normal[3]; + bake_current++; + if (p_bake_step_func != nullptr && (bake_current & 2047) == 1) { + if (p_bake_step_func(bake_current, bake_total)) { + return BAKE_RESULT_CANCELLED; + } + } + for (int k = 0; k < 3; k++) { vtxs[k] = p_xform.xform(vr[ir[j * 3 + k]]); } @@ -460,6 +483,13 @@ void Voxelizer::plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const V Vector2 uvs[3]; Vector3 normal[3]; + bake_current++; + if (p_bake_step_func != nullptr && (bake_current & 2047) == 1) { + if (p_bake_step_func(bake_current, bake_total)) { + return BAKE_RESULT_CANCELLED; + } + } + for (int k = 0; k < 3; k++) { vtxs[k] = p_xform.xform(vr[j * 3 + k]); } @@ -487,6 +517,8 @@ void Voxelizer::plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const V } max_original_cells = bake_cells.size(); + + return BAKE_RESULT_OK; } void Voxelizer::_sort() { @@ -821,7 +853,7 @@ static void edt(float *f, int stride, int n) { #undef square -Vector<uint8_t> Voxelizer::get_sdf_3d_image() const { +Voxelizer::BakeResult Voxelizer::get_sdf_3d_image(Vector<uint8_t> &r_image, BakeStepFunc p_bake_step_function) const { Vector3i octree_size = get_voxel_gi_octree_size(); uint32_t float_count = octree_size.x * octree_size.y * octree_size.z; @@ -849,9 +881,17 @@ Vector<uint8_t> Voxelizer::get_sdf_3d_image() const { //process in each direction + int bake_total = octree_size.x * 2 + octree_size.y, bake_current = 0; + //xy->z - for (int i = 0; i < octree_size.x; i++) { + for (int i = 0; i < octree_size.x; i++, bake_current++) { + if (p_bake_step_function) { + if (p_bake_step_function(bake_current, bake_total)) { + memdelete_arr(work_memory); + return BAKE_RESULT_CANCELLED; + } + } for (int j = 0; j < octree_size.y; j++) { edt(&work_memory[i + j * y_mult], z_mult, octree_size.z); } @@ -859,23 +899,34 @@ Vector<uint8_t> Voxelizer::get_sdf_3d_image() const { //xz->y - for (int i = 0; i < octree_size.x; i++) { + for (int i = 0; i < octree_size.x; i++, bake_current++) { + if (p_bake_step_function) { + if (p_bake_step_function(bake_current, bake_total)) { + memdelete_arr(work_memory); + return BAKE_RESULT_CANCELLED; + } + } for (int j = 0; j < octree_size.z; j++) { edt(&work_memory[i + j * z_mult], y_mult, octree_size.y); } } //yz->x - for (int i = 0; i < octree_size.y; i++) { + for (int i = 0; i < octree_size.y; i++, bake_current++) { + if (p_bake_step_function) { + if (p_bake_step_function(bake_current, bake_total)) { + memdelete_arr(work_memory); + return BAKE_RESULT_CANCELLED; + } + } for (int j = 0; j < octree_size.z; j++) { edt(&work_memory[i * y_mult + j * z_mult], 1, octree_size.x); } } - Vector<uint8_t> image3d; - image3d.resize(float_count); + r_image.resize(float_count); { - uint8_t *w = image3d.ptrw(); + uint8_t *w = r_image.ptrw(); for (uint32_t i = 0; i < float_count; i++) { uint32_t d = uint32_t(Math::sqrt(work_memory[i])); if (d == 0) { @@ -888,7 +939,7 @@ Vector<uint8_t> Voxelizer::get_sdf_3d_image() const { memdelete_arr(work_memory); - return image3d; + return BAKE_RESULT_OK; } #undef INF diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h index 08d018eee9..41e7767308 100644 --- a/scene/3d/voxelizer.h +++ b/scene/3d/voxelizer.h @@ -34,6 +34,15 @@ #include "scene/resources/multimesh.h" class Voxelizer { +public: + enum BakeResult { + BAKE_RESULT_OK, + BAKE_RESULT_INVALID_PARAMETER, + BAKE_RESULT_CANCELLED, + }; + + typedef bool (*BakeStepFunc)(int, int); + private: enum : uint32_t { CHILD_EMPTY = 0xFFFFFFFF @@ -112,7 +121,8 @@ private: public: void begin_bake(int p_subdiv, const AABB &p_bounds, float p_exposure_normalization); - void plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material); + int get_bake_steps(Ref<Mesh> &p_mesh) const; + BakeResult plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material, BakeStepFunc p_bake_step_function); void end_bake(); int get_voxel_gi_octree_depth() const; @@ -121,7 +131,7 @@ public: Vector<uint8_t> get_voxel_gi_octree_cells() const; Vector<uint8_t> get_voxel_gi_data_cells() const; Vector<int> get_voxel_gi_level_cell_count() const; - Vector<uint8_t> get_sdf_3d_image() const; + BakeResult get_sdf_3d_image(Vector<uint8_t> &r_image, BakeStepFunc p_bake_step_function) const; Ref<MultiMesh> create_debug_multimesh(); |