diff options
Diffstat (limited to 'scene/3d')
-rw-r--r-- | scene/3d/collision_object_3d.cpp | 4 | ||||
-rw-r--r-- | scene/3d/collision_object_3d.h | 2 | ||||
-rw-r--r-- | scene/3d/light_3d.cpp | 4 | ||||
-rw-r--r-- | scene/3d/light_3d.h | 2 | ||||
-rw-r--r-- | scene/3d/lightmap_gi.cpp | 2 | ||||
-rw-r--r-- | scene/3d/navigation_obstacle_3d.cpp | 7 | ||||
-rw-r--r-- | scene/3d/node_3d.cpp | 5 | ||||
-rw-r--r-- | scene/3d/occluder_instance_3d.cpp | 548 | ||||
-rw-r--r-- | scene/3d/occluder_instance_3d.h | 128 | ||||
-rw-r--r-- | scene/3d/physics_body_3d.cpp | 31 | ||||
-rw-r--r-- | scene/3d/physics_body_3d.h | 8 | ||||
-rw-r--r-- | scene/3d/ray_cast_3d.cpp | 27 | ||||
-rw-r--r-- | scene/3d/ray_cast_3d.h | 6 | ||||
-rw-r--r-- | scene/3d/skeleton_3d.cpp | 2 | ||||
-rw-r--r-- | scene/3d/spring_arm_3d.cpp | 8 | ||||
-rw-r--r-- | scene/3d/sprite_3d.cpp | 3 | ||||
-rw-r--r-- | scene/3d/visual_instance_3d.cpp | 8 | ||||
-rw-r--r-- | scene/3d/visual_instance_3d.h | 2 | ||||
-rw-r--r-- | scene/3d/voxel_gi.cpp | 2 | ||||
-rw-r--r-- | scene/3d/xr_nodes.cpp | 8 |
20 files changed, 646 insertions, 161 deletions
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index df7c044f9e..3ab09550fa 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -484,7 +484,7 @@ uint32_t CollisionObject3D::create_shape_owner(Object *p_owner) { id = shapes.back()->key() + 1; } - sd.owner = p_owner; + sd.owner_id = p_owner ? p_owner->get_instance_id() : ObjectID(); shapes[id] = sd; @@ -563,7 +563,7 @@ Transform3D CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const Object *CollisionObject3D::shape_owner_get_owner(uint32_t p_owner) const { ERR_FAIL_COND_V(!shapes.has(p_owner), nullptr); - return shapes[p_owner].owner; + return ObjectDB::get_instance(shapes[p_owner].owner_id); } void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3D> &p_shape) { diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index f560753543..e92843d784 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -57,7 +57,7 @@ private: PhysicsServer3D::BodyMode body_mode = PhysicsServer3D::BODY_MODE_STATIC; struct ShapeData { - Object *owner = nullptr; + ObjectID owner_id; Transform3D xform; struct ShapeBase { RID debug_shape; diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 0a0507207a..d88bb815bc 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -247,7 +247,7 @@ void Light3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01"), "set_param", "get_param", PARAM_SIZE); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR); - ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Dynamic,Static"), "set_bake_mode", "get_bake_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI/SDFGI only)"), "set_bake_mode", "get_bake_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); ADD_GROUP("Shadow", "shadow_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow"); @@ -284,8 +284,8 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_MAX); BIND_ENUM_CONSTANT(BAKE_DISABLED); - BIND_ENUM_CONSTANT(BAKE_DYNAMIC); BIND_ENUM_CONSTANT(BAKE_STATIC); + BIND_ENUM_CONSTANT(BAKE_DYNAMIC); } Light3D::Light3D(RenderingServer::LightType p_type) { diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index 93dc8155bb..d5d2aee43d 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -63,8 +63,8 @@ public: enum BakeMode { BAKE_DISABLED, + BAKE_STATIC, BAKE_DYNAMIC, - BAKE_STATIC }; private: diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 715c421632..825742da35 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -217,7 +217,7 @@ LightmapGIData::~LightmapGIData() { void LightmapGI::_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()) { + if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { bool all_have_uv2_and_normal = true; diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index b1f6f0cf91..ba6c50d98c 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -54,9 +54,9 @@ void NavigationObstacle3D::_validate_property(PropertyInfo &p_property) const { void NavigationObstacle3D::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_READY: { - initialize_agent(); + case NOTIFICATION_ENTER_TREE: { parent_node3d = Object::cast_to<Node3D>(get_parent()); + reevaluate_agent_radius(); if (parent_node3d != nullptr) { // place agent on navigation map first or else the RVO agent callback creation fails silently later NavigationServer3D::get_singleton()->agent_set_map(get_rid(), parent_node3d->get_world_3d()->get_navigation_map()); @@ -91,6 +91,7 @@ void NavigationObstacle3D::_notification(int p_what) { NavigationObstacle3D::NavigationObstacle3D() { agent = NavigationServer3D::get_singleton()->agent_create(); + initialize_agent(); } NavigationObstacle3D::~NavigationObstacle3D() { @@ -118,7 +119,7 @@ void NavigationObstacle3D::initialize_agent() { void NavigationObstacle3D::reevaluate_agent_radius() { if (!estimate_radius) { NavigationServer3D::get_singleton()->agent_set_radius(agent, radius); - } else if (parent_node3d) { + } else if (parent_node3d && parent_node3d->is_inside_tree()) { NavigationServer3D::get_singleton()->agent_set_radius(agent, estimate_agent_radius()); } } diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index a992d2aaf2..cad1201d63 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -300,8 +300,9 @@ Node3D *Node3D::get_parent_node_3d() const { } Transform3D Node3D::get_relative_transform(const Node *p_parent) const { - if (p_parent == this) + if (p_parent == this) { return Transform3D(); + } ERR_FAIL_COND_V(!data.parent, Transform3D()); @@ -990,7 +991,7 @@ void Node3D::_bind_methods() { ADD_GROUP("Transform", ""); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians", PROPERTY_USAGE_EDITOR), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "quaternion", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_quaternion", "get_quaternion"); ADD_PROPERTY(PropertyInfo(Variant::BASIS, "basis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_basis", "get_basis"); diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp index e0e2eae4a5..0277171922 100644 --- a/scene/3d/occluder_instance_3d.cpp +++ b/scene/3d/occluder_instance_3d.cpp @@ -30,41 +30,24 @@ #include "occluder_instance_3d.h" #include "core/core_string_names.h" +#include "core/math/geometry_2d.h" +#include "core/math/triangulate.h" +#include "scene/3d/importer_mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h" +#include "scene/resources/importer_mesh.h" +#include "scene/resources/surface_tool.h" + +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" +#endif RID Occluder3D::get_rid() const { - if (!occluder.is_valid()) { - occluder = RS::get_singleton()->occluder_create(); - RS::get_singleton()->occluder_set_mesh(occluder, vertices, indices); - } return occluder; } -void Occluder3D::set_vertices(PackedVector3Array p_vertices) { - vertices = p_vertices; - if (occluder.is_valid()) { - RS::get_singleton()->occluder_set_mesh(occluder, vertices, indices); - } - _update_changes(); -} - -PackedVector3Array Occluder3D::get_vertices() const { - return vertices; -} - -void Occluder3D::set_indices(PackedInt32Array p_indices) { - indices = p_indices; - if (occluder.is_valid()) { - RS::get_singleton()->occluder_set_mesh(occluder, vertices, indices); - } - _update_changes(); -} +void Occluder3D::_update() { + _update_arrays(vertices, indices); -PackedInt32Array Occluder3D::get_indices() const { - return indices; -} - -void Occluder3D::_update_changes() { aabb = AABB(); const Vector3 *ptr = vertices.ptr(); @@ -75,9 +58,18 @@ void Occluder3D::_update_changes() { debug_lines.clear(); debug_mesh.unref(); + RS::get_singleton()->occluder_set_mesh(occluder, vertices, indices); emit_changed(); } +PackedVector3Array Occluder3D::get_vertices() const { + return vertices; +} + +PackedInt32Array Occluder3D::get_indices() const { + return indices; +} + Vector<Vector3> Occluder3D::get_debug_lines() const { if (!debug_lines.is_empty()) { return debug_lines; @@ -87,14 +79,18 @@ Vector<Vector3> Occluder3D::get_debug_lines() const { return Vector<Vector3>(); } + const Vector3 *vertices_ptr = vertices.ptr(); + debug_lines.resize(indices.size() / 3 * 6); + Vector3 *line_ptr = debug_lines.ptrw(); + int line_i = 0; for (int i = 0; i < indices.size() / 3; i++) { for (int j = 0; j < 3; j++) { int a = indices[i * 3 + j]; int b = indices[i * 3 + (j + 1) % 3]; ERR_FAIL_INDEX_V_MSG(a, vertices.size(), Vector<Vector3>(), "Occluder indices are out of range."); ERR_FAIL_INDEX_V_MSG(b, vertices.size(), Vector<Vector3>(), "Occluder indices are out of range."); - debug_lines.push_back(vertices[a]); - debug_lines.push_back(vertices[b]); + line_ptr[line_i++] = vertices_ptr[a]; + line_ptr[line_i++] = vertices_ptr[b]; } } return debug_lines; @@ -105,7 +101,7 @@ Ref<ArrayMesh> Occluder3D::get_debug_mesh() const { return debug_mesh; } - if (indices.size() % 3 != 0) { + if (vertices.is_empty() || indices.is_empty() || indices.size() % 3 != 0) { return debug_mesh; } @@ -123,18 +119,17 @@ AABB Occluder3D::get_aabb() const { return aabb; } -void Occluder3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &Occluder3D::set_vertices); - ClassDB::bind_method(D_METHOD("get_vertices"), &Occluder3D::get_vertices); - - ClassDB::bind_method(D_METHOD("set_indices", "indices"), &Occluder3D::set_indices); - ClassDB::bind_method(D_METHOD("get_indices"), &Occluder3D::get_indices); +void Occluder3D::_notification(int p_what) { + if (p_what == NOTIFICATION_POSTINITIALIZE) { + _update(); + } +} - ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_vertices", "get_vertices"); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "indices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_indices", "get_indices"); +void Occluder3D::_bind_methods() { } Occluder3D::Occluder3D() { + occluder = RS::get_singleton()->occluder_create(); } Occluder3D::~Occluder3D() { @@ -142,6 +137,291 @@ Occluder3D::~Occluder3D() { RS::get_singleton()->free(occluder); } } + +///////////////////////////////////////////////// + +void ArrayOccluder3D::set_arrays(PackedVector3Array p_vertices, PackedInt32Array p_indices) { + vertices = p_vertices; + indices = p_indices; + _update(); +} + +void ArrayOccluder3D::set_vertices(PackedVector3Array p_vertices) { + vertices = p_vertices; + _update(); +} + +void ArrayOccluder3D::set_indices(PackedInt32Array p_indices) { + indices = p_indices; + _update(); +} + +void ArrayOccluder3D::_update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) { + r_vertices = vertices; + r_indices = indices; +} + +void ArrayOccluder3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_arrays", "vertices", "indices"), &ArrayOccluder3D::set_arrays); + + ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &ArrayOccluder3D::set_vertices); + ClassDB::bind_method(D_METHOD("get_vertices"), &ArrayOccluder3D::get_vertices); + + ClassDB::bind_method(D_METHOD("set_indices", "indices"), &ArrayOccluder3D::set_indices); + ClassDB::bind_method(D_METHOD("get_indices"), &ArrayOccluder3D::get_indices); + + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_vertices", "get_vertices"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "indices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_indices", "get_indices"); +} + +ArrayOccluder3D::ArrayOccluder3D() { +} + +ArrayOccluder3D::~ArrayOccluder3D() { +} + +///////////////////////////////////////////////// + +void QuadOccluder3D::set_size(const Vector2 &p_size) { + if (size == p_size) { + return; + } + + size = p_size.max(Vector2()); + ; + _update(); +} + +Vector2 QuadOccluder3D::get_size() const { + return size; +} + +void QuadOccluder3D::_update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) { + Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f); + + r_vertices = { + Vector3(-_size.x, -_size.y, 0), + Vector3(-_size.x, _size.y, 0), + Vector3(_size.x, _size.y, 0), + Vector3(_size.x, -_size.y, 0), + }; + + r_indices = { + 0, 1, 2, + 0, 2, 3 + }; +} + +void QuadOccluder3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_size", "size"), &QuadOccluder3D::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &QuadOccluder3D::get_size); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); +} + +QuadOccluder3D::QuadOccluder3D() { +} + +QuadOccluder3D::~QuadOccluder3D() { +} + +///////////////////////////////////////////////// + +void BoxOccluder3D::set_size(const Vector3 &p_size) { + if (size == p_size) { + return; + } + + size = Vector3(MAX(p_size.x, 0.0f), MAX(p_size.y, 0.0f), MAX(p_size.z, 0.0f)); + ; + _update(); +} + +Vector3 BoxOccluder3D::get_size() const { + return size; +} + +void BoxOccluder3D::_update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) { + Vector3 _size = Vector3(size.x / 2.0f, size.y / 2.0f, size.z / 2.0f); + + r_vertices = { + // front + Vector3(-_size.x, -_size.y, _size.z), + Vector3(_size.x, -_size.y, _size.z), + Vector3(_size.x, _size.y, _size.z), + Vector3(-_size.x, _size.y, _size.z), + // back + Vector3(-_size.x, -_size.y, -_size.z), + Vector3(_size.x, -_size.y, -_size.z), + Vector3(_size.x, _size.y, -_size.z), + Vector3(-_size.x, _size.y, -_size.z), + }; + + r_indices = { + // front + 0, 1, 2, + 2, 3, 0, + // right + 1, 5, 6, + 6, 2, 1, + // back + 7, 6, 5, + 5, 4, 7, + // left + 4, 0, 3, + 3, 7, 4, + // bottom + 4, 5, 1, + 1, 0, 4, + // top + 3, 2, 6, + 6, 7, 3 + }; +} + +void BoxOccluder3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_size", "size"), &BoxOccluder3D::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &BoxOccluder3D::get_size); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size"), "set_size", "get_size"); +} + +BoxOccluder3D::BoxOccluder3D() { +} + +BoxOccluder3D::~BoxOccluder3D() { +} + +///////////////////////////////////////////////// + +void SphereOccluder3D::set_radius(float p_radius) { + if (radius == p_radius) { + return; + } + + radius = MAX(p_radius, 0.0f); + _update(); +} + +float SphereOccluder3D::get_radius() const { + return radius; +} + +void SphereOccluder3D::_update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) { + r_vertices.resize((RINGS + 2) * (RADIAL_SEGMENTS + 1)); + int vertex_i = 0; + Vector3 *vertex_ptr = r_vertices.ptrw(); + + r_indices.resize((RINGS + 1) * RADIAL_SEGMENTS * 6); + int idx_i = 0; + int *idx_ptr = r_indices.ptrw(); + + int current_row = 0; + int previous_row = 0; + int point = 0; + for (int j = 0; j <= (RINGS + 1); j++) { + float v = j / float(RINGS + 1); + float w = Math::sin(Math_PI * v); + float y = Math::cos(Math_PI * v); + for (int i = 0; i <= RADIAL_SEGMENTS; i++) { + float u = i / float(RADIAL_SEGMENTS); + + float x = Math::cos(u * Math_TAU); + float z = Math::sin(u * Math_TAU); + vertex_ptr[vertex_i++] = Vector3(x * w, y, z * w) * radius; + + if (i > 0 && j > 0) { + idx_ptr[idx_i++] = previous_row + i - 1; + idx_ptr[idx_i++] = previous_row + i; + idx_ptr[idx_i++] = current_row + i - 1; + + idx_ptr[idx_i++] = previous_row + i; + idx_ptr[idx_i++] = current_row + i; + idx_ptr[idx_i++] = current_row + i - 1; + } + + point++; + } + + previous_row = current_row; + current_row = point; + } +} + +void SphereOccluder3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereOccluder3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &SphereOccluder3D::get_radius); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius"), "set_radius", "get_radius"); +} + +SphereOccluder3D::SphereOccluder3D() { +} + +SphereOccluder3D::~SphereOccluder3D() { +} + +///////////////////////////////////////////////// + +void PolygonOccluder3D::set_polygon(const Vector<Vector2> &p_polygon) { + polygon = p_polygon; + _update(); +} + +Vector<Vector2> PolygonOccluder3D::get_polygon() const { + return polygon; +} + +void PolygonOccluder3D::_update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) { + if (polygon.size() < 3) { + r_vertices.clear(); + r_indices.clear(); + return; + } + + Vector<Point2> occluder_polygon = polygon; + if (Triangulate::get_area(occluder_polygon) > 0) { + occluder_polygon.reverse(); + } + + Vector<int> occluder_indices = Geometry2D::triangulate_polygon(occluder_polygon); + + if (occluder_indices.size() < 3) { + r_vertices.clear(); + r_indices.clear(); + ERR_FAIL_MSG("Failed to triangulate PolygonOccluder3D. Make sure the polygon doesn't have any intersecting edges."); + } + + r_vertices.resize(occluder_polygon.size()); + Vector3 *vertex_ptr = r_vertices.ptrw(); + const Vector2 *polygon_ptr = occluder_polygon.ptr(); + for (int i = 0; i < occluder_polygon.size(); i++) { + vertex_ptr[i] = Vector3(polygon_ptr[i].x, polygon_ptr[i].y, 0.0); + } + + r_indices.resize(occluder_indices.size()); + memcpy(r_indices.ptrw(), occluder_indices.ptr(), occluder_indices.size() * sizeof(int)); +} + +bool PolygonOccluder3D::_has_editable_3d_polygon_no_depth() const { + return false; +} + +void PolygonOccluder3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &PolygonOccluder3D::set_polygon); + ClassDB::bind_method(D_METHOD("get_polygon"), &PolygonOccluder3D::get_polygon); + + ClassDB::bind_method(D_METHOD("_has_editable_3d_polygon_no_depth"), &PolygonOccluder3D::_has_editable_3d_polygon_no_depth); + + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon"); +} + +PolygonOccluder3D::PolygonOccluder3D() { +} + +PolygonOccluder3D::~PolygonOccluder3D() { +} + ///////////////////////////////////////////////// AABB OccluderInstance3D::get_aabb() const { @@ -175,6 +455,13 @@ void OccluderInstance3D::set_occluder(const Ref<Occluder3D> &p_occluder) { update_gizmos(); update_configuration_warnings(); + +#ifdef TOOLS_ENABLED + // PolygonOccluder3D is edited via an editor plugin, this ensures the plugin is shown/hidden when necessary + if (Engine::get_singleton()->is_editor_hint()) { + EditorNode::get_singleton()->call_deferred(SNAME("edit_current")); + } +#endif } void OccluderInstance3D::_occluder_changed() { @@ -195,6 +482,14 @@ uint32_t OccluderInstance3D::get_bake_mask() const { return bake_mask; } +void OccluderInstance3D::set_bake_simplification_distance(float p_dist) { + bake_simplification_dist = MAX(p_dist, 0.0f); +} + +float OccluderInstance3D::get_bake_simplification_distance() const { + return bake_simplification_dist; +} + void OccluderInstance3D::set_bake_mask_value(int p_layer_number, bool p_value) { ERR_FAIL_COND_MSG(p_layer_number < 1, "Render layer number must be between 1 and 20 inclusive."); ERR_FAIL_COND_MSG(p_layer_number > 20, "Render layer number must be between 1 and 20 inclusive."); @@ -221,6 +516,47 @@ bool OccluderInstance3D::_bake_material_check(Ref<Material> p_material) { return true; } +void OccluderInstance3D::_bake_surface(const Transform3D &p_transform, Array p_surface_arrays, Ref<Material> p_material, float p_simplification_dist, PackedVector3Array &r_vertices, PackedInt32Array &r_indices) { + if (!_bake_material_check(p_material)) { + return; + } + ERR_FAIL_COND_MSG(p_surface_arrays.size() != Mesh::ARRAY_MAX, "Invalid surface array."); + + PackedVector3Array vertices = p_surface_arrays[Mesh::ARRAY_VERTEX]; + PackedInt32Array indices = p_surface_arrays[Mesh::ARRAY_INDEX]; + + if (vertices.size() == 0 || indices.size() == 0) { + return; + } + + Vector3 *vertices_ptr = vertices.ptrw(); + for (int j = 0; j < vertices.size(); j++) { + vertices_ptr[j] = p_transform.xform(vertices_ptr[j]); + } + + if (!Math::is_zero_approx(p_simplification_dist) && SurfaceTool::simplify_func) { + float error_scale = SurfaceTool::simplify_scale_func((float *)vertices.ptr(), vertices.size(), sizeof(Vector3)); + float target_error = p_simplification_dist / error_scale; + float error = -1.0f; + int target_index_count = MIN(indices.size(), 36); + uint32_t index_count = SurfaceTool::simplify_func((unsigned int *)indices.ptrw(), (unsigned int *)indices.ptr(), indices.size(), (float *)vertices.ptr(), vertices.size(), sizeof(Vector3), target_index_count, target_error, &error); + indices.resize(index_count); + } + + SurfaceTool::strip_mesh_arrays(vertices, indices); + + int vertex_offset = r_vertices.size(); + r_vertices.resize(vertex_offset + vertices.size()); + memcpy(r_vertices.ptrw() + vertex_offset, vertices.ptr(), vertices.size() * sizeof(Vector3)); + + int index_offset = r_indices.size(); + r_indices.resize(index_offset + indices.size()); + int *idx_ptr = r_indices.ptrw(); + for (int j = 0; j < indices.size(); j++) { + idx_ptr[index_offset + j] = vertex_offset + indices[j]; + } +} + void OccluderInstance3D::_bake_node(Node *p_node, PackedVector3Array &r_vertices, PackedInt32Array &r_indices) { MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); if (mi && mi->is_visible_in_tree()) { @@ -243,58 +579,76 @@ void OccluderInstance3D::_bake_node(Node *p_node, PackedVector3Array &r_vertices Transform3D global_to_local = get_global_transform().affine_inverse() * mi->get_global_transform(); for (int i = 0; i < mesh->get_surface_count(); i++) { - if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { - continue; - } + _bake_surface(global_to_local, mesh->surface_get_arrays(i), mi->get_active_material(i), bake_simplification_dist, r_vertices, r_indices); + } + } + } - if (mi->get_surface_override_material(i).is_valid()) { - if (!_bake_material_check(mi->get_surface_override_material(i))) { - continue; - } - } else { - if (!_bake_material_check(mesh->surface_get_material(i))) { - continue; - } - } + for (int i = 0; i < p_node->get_child_count(); i++) { + Node *child = p_node->get_child(i); + if (!child->get_owner()) { + continue; // may be a helper + } - Array arrays = mesh->surface_get_arrays(i); + _bake_node(child, r_vertices, r_indices); + } +} - int vertex_offset = r_vertices.size(); - PackedVector3Array vertices = arrays[Mesh::ARRAY_VERTEX]; - r_vertices.resize(r_vertices.size() + vertices.size()); +void OccluderInstance3D::bake_single_node(const Node3D *p_node, float p_simplification_distance, PackedVector3Array &r_vertices, PackedInt32Array &r_indices) { + ERR_FAIL_COND(!p_node); - Vector3 *vtx_ptr = r_vertices.ptrw(); - for (int j = 0; j < vertices.size(); j++) { - vtx_ptr[vertex_offset + j] = global_to_local.xform(vertices[j]); - } + Transform3D xform = p_node->is_inside_tree() ? p_node->get_global_transform() : p_node->get_transform(); - int index_offset = r_indices.size(); - PackedInt32Array indices = arrays[Mesh::ARRAY_INDEX]; - r_indices.resize(r_indices.size() + indices.size()); + const MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); + if (mi) { + Ref<Mesh> mesh = mi->get_mesh(); + bool valid = true; - int *idx_ptr = r_indices.ptrw(); - for (int j = 0; j < indices.size(); j++) { - idx_ptr[index_offset + j] = vertex_offset + indices[j]; - } + if (mesh.is_null()) { + valid = false; + } + + if (valid && !_bake_material_check(mi->get_material_override())) { + valid = false; + } + + if (valid) { + for (int i = 0; i < mesh->get_surface_count(); i++) { + _bake_surface(xform, mesh->surface_get_arrays(i), mi->get_active_material(i), p_simplification_distance, r_vertices, r_indices); } } } - for (int i = 0; i < p_node->get_child_count(); i++) { - Node *child = p_node->get_child(i); - if (!child->get_owner()) { - continue; //maybe a helper + const ImporterMeshInstance3D *imi = Object::cast_to<ImporterMeshInstance3D>(p_node); + if (imi) { + Ref<ImporterMesh> mesh = imi->get_mesh(); + bool valid = true; + + if (mesh.is_null()) { + valid = false; } - _bake_node(child, r_vertices, r_indices); + if (valid) { + for (int i = 0; i < mesh->get_surface_count(); i++) { + Ref<Material> material = imi->get_surface_material(i); + if (material.is_null()) { + material = mesh->get_surface_material(i); + } + _bake_surface(xform, mesh->get_surface_arrays(i), material, p_simplification_distance, r_vertices, r_indices); + } + } } } -OccluderInstance3D::BakeError OccluderInstance3D::bake(Node *p_from_node, String p_occluder_path) { +OccluderInstance3D::BakeError OccluderInstance3D::bake_scene(Node *p_from_node, String p_occluder_path) { if (p_occluder_path.is_empty()) { if (get_occluder().is_null()) { return BAKE_ERROR_NO_SAVE_PATH; } + p_occluder_path = get_occluder()->get_path(); + if (!p_occluder_path.is_resource_file()) { + return BAKE_ERROR_NO_SAVE_PATH; + } } PackedVector3Array vertices; @@ -306,16 +660,25 @@ OccluderInstance3D::BakeError OccluderInstance3D::bake(Node *p_from_node, String return BAKE_ERROR_NO_MESHES; } - Ref<Occluder3D> occ; + Ref<ArrayOccluder3D> occ; if (get_occluder().is_valid()) { occ = get_occluder(); - } else { + set_occluder(Ref<Occluder3D>()); // clear + } + + if (occ.is_null()) { occ.instantiate(); - occ->set_path(p_occluder_path); } - occ->set_vertices(vertices); - occ->set_indices(indices); + occ->set_arrays(vertices, indices); + + Error err = ResourceSaver::save(p_occluder_path, occ); + + if (err != OK) { + return BAKE_ERROR_CANT_SAVE; + } + + occ->set_path(p_occluder_path); set_occluder(occ); return BAKE_ERROR_OK; @@ -333,28 +696,49 @@ TypedArray<String> OccluderInstance3D::get_configuration_warnings() const { } if (occluder.is_null()) { - warnings.push_back(TTR("No occluder mesh is defined in the Occluder property, so no occlusion culling will be performed using this OccluderInstance3D.\nTo resolve this, select the OccluderInstance3D then use the Bake Occluders button at the top of the 3D editor viewport.")); - } else if (occluder->get_vertices().size() < 3) { - // Using the "New Occluder" dropdown button won't result in a correct occluder, - // so warn the user about this. - warnings.push_back(TTR("The occluder mesh has less than 3 vertices, so no occlusion culling will be performed using this OccluderInstance3D.\nTo generate a proper occluder mesh, select the OccluderInstance3D then use the Bake Occluders button at the top of the 3D editor viewport.")); + warnings.push_back(TTR("No occluder mesh is defined in the Occluder property, so no occlusion culling will be performed using this OccluderInstance3D.\nTo resolve this, set the Occluder property to one of the primitive occluder types or bake the scene meshes by selecting the OccluderInstance3D and pressing the Bake Occluders button at the top of the 3D editor viewport.")); + } else { + Ref<ArrayOccluder3D> arr_occluder = occluder; + if (arr_occluder.is_valid() && arr_occluder->get_indices().size() < 3) { + // Setting a new ArrayOccluder3D from the inspector will create an empty occluder, + // so warn the user about this. + warnings.push_back(TTR("The occluder mesh has less than 3 vertices, so no occlusion culling will be performed using this OccluderInstance3D.\nTo generate a proper occluder mesh, select the OccluderInstance3D then use the Bake Occluders button at the top of the 3D editor viewport.")); + } + Ref<PolygonOccluder3D> poly_occluder = occluder; + if (poly_occluder.is_valid() && poly_occluder->get_polygon().size() < 3) { + warnings.push_back(TTR("The polygon occluder has less than 3 vertices, so no occlusion culling will be performed using this OccluderInstance3D.\nVertices can be added in the inspector or using the polygon editing tools at the top of the 3D editor viewport.")); + } } return warnings; } +bool OccluderInstance3D::_is_editable_3d_polygon() const { + return Ref<PolygonOccluder3D>(occluder).is_valid(); +} + +Ref<Resource> OccluderInstance3D::_get_editable_3d_polygon_resource() const { + return occluder; +} + void OccluderInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bake_mask", "mask"), &OccluderInstance3D::set_bake_mask); ClassDB::bind_method(D_METHOD("get_bake_mask"), &OccluderInstance3D::get_bake_mask); ClassDB::bind_method(D_METHOD("set_bake_mask_value", "layer_number", "value"), &OccluderInstance3D::set_bake_mask_value); ClassDB::bind_method(D_METHOD("get_bake_mask_value", "layer_number"), &OccluderInstance3D::get_bake_mask_value); + ClassDB::bind_method(D_METHOD("set_bake_simplification_distance", "simplification_distance"), &OccluderInstance3D::set_bake_simplification_distance); + ClassDB::bind_method(D_METHOD("get_bake_simplification_distance"), &OccluderInstance3D::get_bake_simplification_distance); ClassDB::bind_method(D_METHOD("set_occluder", "occluder"), &OccluderInstance3D::set_occluder); ClassDB::bind_method(D_METHOD("get_occluder"), &OccluderInstance3D::get_occluder); + ClassDB::bind_method(D_METHOD("_is_editable_3d_polygon"), &OccluderInstance3D::_is_editable_3d_polygon); + ClassDB::bind_method(D_METHOD("_get_editable_3d_polygon_resource"), &OccluderInstance3D::_get_editable_3d_polygon_resource); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "occluder", PROPERTY_HINT_RESOURCE_TYPE, "Occluder3D"), "set_occluder", "get_occluder"); ADD_GROUP("Bake", "bake_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_bake_mask", "get_bake_mask"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_simplification_distance", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_bake_simplification_distance", "get_bake_simplification_distance"); } OccluderInstance3D::OccluderInstance3D() { diff --git a/scene/3d/occluder_instance_3d.h b/scene/3d/occluder_instance_3d.h index 8a8d4c9af4..669ddba775 100644 --- a/scene/3d/occluder_instance_3d.h +++ b/scene/3d/occluder_instance_3d.h @@ -37,24 +37,23 @@ class Occluder3D : public Resource { GDCLASS(Occluder3D, Resource); RES_BASE_EXTENSION("occ"); - mutable RID occluder; - mutable Ref<ArrayMesh> debug_mesh; - mutable Vector<Vector3> debug_lines; - AABB aabb; - + RID occluder; PackedVector3Array vertices; PackedInt32Array indices; + AABB aabb; - void _update_changes(); + mutable Ref<ArrayMesh> debug_mesh; + mutable Vector<Vector3> debug_lines; protected: + void _update(); + virtual void _update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) = 0; + static void _bind_methods(); + void _notification(int p_what); public: - void set_vertices(PackedVector3Array p_vertices); PackedVector3Array get_vertices() const; - - void set_indices(PackedInt32Array p_indices); PackedInt32Array get_indices() const; Vector<Vector3> get_debug_lines() const; @@ -63,7 +62,102 @@ public: virtual RID get_rid() const override; Occluder3D(); - ~Occluder3D(); + virtual ~Occluder3D(); +}; + +class ArrayOccluder3D : public Occluder3D { + GDCLASS(ArrayOccluder3D, Occluder3D); + + PackedVector3Array vertices; + PackedInt32Array indices; + +protected: + virtual void _update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) override; + static void _bind_methods(); + +public: + void set_arrays(PackedVector3Array p_vertices, PackedInt32Array p_indices); + void set_vertices(PackedVector3Array p_vertices); + void set_indices(PackedInt32Array p_indices); + + ArrayOccluder3D(); + ~ArrayOccluder3D(); +}; + +class QuadOccluder3D : public Occluder3D { + GDCLASS(QuadOccluder3D, Occluder3D); + +private: + Vector2 size = Vector2(1.0f, 1.0f); + +protected: + virtual void _update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) override; + static void _bind_methods(); + +public: + Vector2 get_size() const; + void set_size(const Vector2 &p_size); + + QuadOccluder3D(); + ~QuadOccluder3D(); +}; + +class BoxOccluder3D : public Occluder3D { + GDCLASS(BoxOccluder3D, Occluder3D); + +private: + Vector3 size = Vector3(1.0f, 1.0f, 1.0f); + +protected: + virtual void _update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) override; + static void _bind_methods(); + +public: + Vector3 get_size() const; + void set_size(const Vector3 &p_size); + + BoxOccluder3D(); + ~BoxOccluder3D(); +}; + +class SphereOccluder3D : public Occluder3D { + GDCLASS(SphereOccluder3D, Occluder3D); + +private: + static constexpr int RINGS = 7; + static constexpr int RADIAL_SEGMENTS = 7; + float radius = 1.0f; + +protected: + virtual void _update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) override; + static void _bind_methods(); + +public: + float get_radius() const; + void set_radius(float p_radius); + + SphereOccluder3D(); + ~SphereOccluder3D(); +}; + +class PolygonOccluder3D : public Occluder3D { + GDCLASS(PolygonOccluder3D, Occluder3D); + +private: + Vector<Vector2> polygon; + + bool _has_editable_3d_polygon_no_depth() const; + +protected: + virtual void _update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) override; + static void _bind_methods(); + +public: + void set_polygon(const Vector<Vector2> &p_polygon); + Vector<Vector2> get_polygon() const; + + PolygonOccluder3D(); + ~PolygonOccluder3D(); }; class OccluderInstance3D : public VisualInstance3D { @@ -72,12 +166,17 @@ class OccluderInstance3D : public VisualInstance3D { private: Ref<Occluder3D> occluder; uint32_t bake_mask = 0xFFFFFFFF; + float bake_simplification_dist = 0.1f; void _occluder_changed(); - bool _bake_material_check(Ref<Material> p_material); + static bool _bake_material_check(Ref<Material> p_material); + static void _bake_surface(const Transform3D &p_transform, Array p_surface_arrays, Ref<Material> p_material, float p_simplification_dist, PackedVector3Array &r_vertices, PackedInt32Array &r_indices); void _bake_node(Node *p_node, PackedVector3Array &r_vertices, PackedInt32Array &r_indices); + bool _is_editable_3d_polygon() const; + Ref<Resource> _get_editable_3d_polygon_resource() const; + protected: static void _bind_methods(); @@ -88,6 +187,7 @@ public: BAKE_ERROR_OK, BAKE_ERROR_NO_SAVE_PATH, BAKE_ERROR_NO_MESHES, + BAKE_ERROR_CANT_SAVE, }; void set_occluder(const Ref<Occluder3D> &p_occluder); @@ -99,10 +199,14 @@ public: void set_bake_mask(uint32_t p_mask); uint32_t get_bake_mask() const; + void set_bake_simplification_distance(float p_dist); + float get_bake_simplification_distance() const; + void set_bake_mask_value(int p_layer_number, bool p_enable); bool get_bake_mask_value(int p_layer_number) const; - BakeError bake(Node *p_from_node, String p_occluder_path = ""); + BakeError bake_scene(Node *p_from_node, String p_occluder_path = ""); + static void bake_single_node(const Node3D *p_node, float p_simplification_distance, PackedVector3Array &r_vertices, PackedInt32Array &r_indices); OccluderInstance3D(); ~OccluderInstance3D(); diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index b3192a5bb5..13a38f3b9f 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -34,8 +34,8 @@ #include "scene/scene_string_names.h" void PhysicsBody3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("move_and_collide", "linear_velocity", "test_only", "safe_margin", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(1)); - ClassDB::bind_method(D_METHOD("test_move", "from", "linear_velocity", "collision", "safe_margin", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(1)); + ClassDB::bind_method(D_METHOD("move_and_collide", "distance", "test_only", "safe_margin", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(1)); + ClassDB::bind_method(D_METHOD("test_move", "from", "distance", "collision", "safe_margin", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(1)); ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &PhysicsBody3D::set_axis_lock); ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &PhysicsBody3D::get_axis_lock); @@ -91,11 +91,8 @@ void PhysicsBody3D::remove_collision_exception_with(Node *p_node) { PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid()); } -Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_linear_velocity, bool p_test_only, real_t p_margin, int p_max_collisions) { - // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky - double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time(); - - PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_linear_velocity * delta, p_margin); +Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_distance, bool p_test_only, real_t p_margin, int p_max_collisions) { + PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_distance, p_margin); parameters.max_collisions = p_max_collisions; PhysicsServer3D::MotionResult result; @@ -170,7 +167,7 @@ bool PhysicsBody3D::move_and_collide(const PhysicsServer3D::MotionParameters &p_ return colliding; } -bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_linear_velocity, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, int p_max_collisions) { +bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_distance, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, int p_max_collisions) { ERR_FAIL_COND_V(!is_inside_tree(), false); PhysicsServer3D::MotionResult *r = nullptr; @@ -182,10 +179,7 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_linear r = &temp_result; } - // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky - double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time(); - - PhysicsServer3D::MotionParameters parameters(p_from, p_linear_velocity * delta, p_margin); + PhysicsServer3D::MotionParameters parameters(p_from, p_distance, p_margin); bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r); @@ -1233,7 +1227,7 @@ bool CharacterBody3D::move_and_slide() { if (motion_mode == MOTION_MODE_GROUNDED) { _move_and_slide_grounded(delta, was_on_floor); } else { - _move_and_slide_free(delta); + _move_and_slide_floating(delta); } // Compute real velocity. @@ -1512,7 +1506,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo } } -void CharacterBody3D::_move_and_slide_free(double p_delta) { +void CharacterBody3D::_move_and_slide_floating(double p_delta) { Vector3 motion = motion_velocity * p_delta; platform_rid = RID(); @@ -1929,7 +1923,7 @@ const Vector3 &CharacterBody3D::get_up_direction() const { } void CharacterBody3D::set_up_direction(const Vector3 &p_up_direction) { - ERR_FAIL_COND_MSG(p_up_direction == Vector3(), "up_direction can't be equal to Vector3.ZERO, consider using Free motion mode instead."); + ERR_FAIL_COND_MSG(p_up_direction == Vector3(), "up_direction can't be equal to Vector3.ZERO, consider using Floating motion mode instead."); up_direction = p_up_direction.normalized(); } @@ -2000,12 +1994,11 @@ void CharacterBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody3D::_get_slide_collision); ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &CharacterBody3D::_get_last_slide_collision); - ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Free", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Floating", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_direction"), "set_up_direction", "get_up_direction"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_motion_velocity", "get_motion_velocity"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides"); - ADD_GROUP("Free Mode", "free_mode_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle"); ADD_GROUP("Floor", "floor_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_stop_on_slope"), "set_floor_stop_on_slope_enabled", "is_floor_stop_on_slope_enabled"); @@ -2020,7 +2013,7 @@ void CharacterBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED); - BIND_ENUM_CONSTANT(MOTION_MODE_FREE); + BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING); BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_ALWAYS); BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY); @@ -2028,7 +2021,7 @@ void CharacterBody3D::_bind_methods() { } void CharacterBody3D::_validate_property(PropertyInfo &property) const { - if (motion_mode == MOTION_MODE_FREE) { + if (motion_mode == MOTION_MODE_FLOATING) { if (property.name.begins_with("floor_") || property.name == "up_direction" || property.name == "slide_on_ceiling") { property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index e37b841117..67dc7382c3 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -50,11 +50,11 @@ protected: uint16_t locked_axis = 0; - Ref<KinematicCollision3D> _move(const Vector3 &p_linear_velocity, bool p_test_only = false, real_t p_margin = 0.001, int p_max_collisions = 1); + Ref<KinematicCollision3D> _move(const Vector3 &p_distance, bool p_test_only = false, real_t p_margin = 0.001, int p_max_collisions = 1); public: bool move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true); - bool test_move(const Transform3D &p_from, const Vector3 &p_linear_velocity, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, int p_max_collisions = 1); + bool test_move(const Transform3D &p_from, const Vector3 &p_distance, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, int p_max_collisions = 1); void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock); bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const; @@ -345,7 +345,7 @@ class CharacterBody3D : public PhysicsBody3D { public: enum MotionMode { MOTION_MODE_GROUNDED, - MOTION_MODE_FREE, + MOTION_MODE_FLOATING, }; enum MovingPlatformApplyVelocityOnLeave { PLATFORM_VEL_ON_LEAVE_ALWAYS, @@ -468,7 +468,7 @@ private: void set_moving_platform_apply_velocity_on_leave(MovingPlatformApplyVelocityOnLeave p_on_leave_velocity); MovingPlatformApplyVelocityOnLeave get_moving_platform_apply_velocity_on_leave() const; - void _move_and_slide_free(double p_delta); + void _move_and_slide_floating(double p_delta); void _move_and_slide_grounded(double p_delta, bool p_was_on_floor); Ref<KinematicCollision3D> _get_slide_collision(int p_bounce); diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp index 3bb65d07a0..b251aa38ba 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -243,30 +243,29 @@ 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) { - return; - } - add_exception_rid(co->get_rid()); +void RayCast3D::add_exception(const CollisionObject3D *p_node) { + ERR_FAIL_NULL_MSG(p_node, "The passed Node must be an instance of CollisionObject3D."); + add_exception_rid(p_node->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) { - return; - } - remove_exception_rid(co->get_rid()); +void RayCast3D::remove_exception(const CollisionObject3D *p_node) { + ERR_FAIL_NULL_MSG(p_node, "The passed Node must be an instance of CollisionObject3D."); + remove_exception_rid(p_node->get_rid()); } void RayCast3D::clear_exceptions() { exclude.clear(); + + if (exclude_parent_body && is_inside_tree()) { + CollisionObject3D *parent = Object::cast_to<CollisionObject3D>(get_parent()); + if (parent) { + exclude.insert(parent->get_rid()); + } + } } void RayCast3D::set_collide_with_areas(bool p_enabled) { diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h index a53e2c83fc..ad85001591 100644 --- a/scene/3d/ray_cast_3d.h +++ b/scene/3d/ray_cast_3d.h @@ -33,6 +33,8 @@ #include "scene/3d/node_3d.h" +class CollisionObject3D; + class RayCast3D : public Node3D { GDCLASS(RayCast3D, Node3D); @@ -116,9 +118,9 @@ public: Vector3 get_collision_normal() const; void add_exception_rid(const RID &p_rid); - void add_exception(const Object *p_object); + void add_exception(const CollisionObject3D *p_node); void remove_exception_rid(const RID &p_rid); - void remove_exception(const Object *p_object); + void remove_exception(const CollisionObject3D *p_node); void clear_exceptions(); RayCast3D(); diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 3957a1653f..b6b5920f69 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -506,7 +506,7 @@ int Skeleton3D::get_bone_axis_forward_enum(int p_bone) { // Skeleton creation api void Skeleton3D::add_bone(const String &p_name) { - ERR_FAIL_COND(p_name.is_empty() || p_name.find(":") != -1 || p_name.find("/") != -1); + ERR_FAIL_COND(p_name.is_empty() || p_name.contains(":") || p_name.contains("/")); for (int i = 0; i < bones.size(); i++) { ERR_FAIL_COND(bones[i].name == p_name); diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp index e0cd44e05b..8a8964f69a 100644 --- a/scene/3d/spring_arm_3d.cpp +++ b/scene/3d/spring_arm_3d.cpp @@ -185,14 +185,14 @@ void SpringArm3D::process_spring() { } current_spring_length = spring_length * motion_delta; - Transform3D childs_transform; - childs_transform.origin = get_global_transform().origin + cast_direction * (spring_length * motion_delta); + Transform3D child_transform; + child_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; - child->set_global_transform(childs_transform); + child_transform.basis = child->get_global_transform().basis; + child->set_global_transform(child_transform); } } } diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index a37fce9469..331d58927b 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -1088,8 +1088,9 @@ void AnimatedSprite3D::set_frame(int p_frame) { 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) { diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index 0db2fe9fc6..005bb5a737 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -247,7 +247,7 @@ bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value) } #ifndef DISABLE_DEPRECATED if (p_name == SceneStringNames::get_singleton()->use_in_baked_light && bool(p_value)) { - set_gi_mode(GI_MODE_BAKED); + set_gi_mode(GI_MODE_STATIC); return true; } @@ -358,7 +358,7 @@ void GeometryInstance3D::set_gi_mode(GIMode p_mode) { 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: { + case GI_MODE_STATIC: { 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); @@ -462,7 +462,7 @@ void GeometryInstance3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_bias", PROPERTY_HINT_RANGE, "0.001,128,0.001"), "set_lod_bias", "get_lod_bias"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_occlusion_culling"), "set_ignore_occlusion_culling", "is_ignoring_occlusion_culling"); 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_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI only)"), "set_gi_mode", "get_gi_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, String::utf8("1×,2×,4×,8×")), "set_lightmap_scale", "get_lightmap_scale"); ADD_GROUP("Visibility Range", "visibility_range_"); @@ -479,7 +479,7 @@ void GeometryInstance3D::_bind_methods() { BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY); BIND_ENUM_CONSTANT(GI_MODE_DISABLED); - BIND_ENUM_CONSTANT(GI_MODE_BAKED); + BIND_ENUM_CONSTANT(GI_MODE_STATIC); BIND_ENUM_CONSTANT(GI_MODE_DYNAMIC); BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_1X); diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index dd0eb25001..be964e5080 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -89,7 +89,7 @@ public: enum GIMode { GI_MODE_DISABLED, - GI_MODE_BAKED, + GI_MODE_STATIC, GI_MODE_DYNAMIC }; diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index 35ac1792e9..bfe3c80a4f 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -282,7 +282,7 @@ Vector3 VoxelGI::get_extents() const { void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node); - if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { + if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { AABB aabb = mesh->get_aabb(); diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index a054f35d2e..66d1b97056 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -482,22 +482,22 @@ void XRController3D::_unbind_tracker() { void XRController3D::_button_pressed(const String &p_name) { // just pass it on... - emit_signal("button_pressed", p_name); + emit_signal(SNAME("button_pressed"), p_name); } void XRController3D::_button_released(const String &p_name) { // just pass it on... - emit_signal("button_released", p_name); + emit_signal(SNAME("button_released"), p_name); } void XRController3D::_input_value_changed(const String &p_name, float p_value) { // just pass it on... - emit_signal("input_value_changed", p_name, p_value); + emit_signal(SNAME("input_value_changed"), p_name, p_value); } void XRController3D::_input_axis_changed(const String &p_name, Vector2 p_value) { // just pass it on... - emit_signal("input_axis_changed", p_name, p_value); + emit_signal(SNAME("input_axis_changed"), p_name, p_value); } bool XRController3D::is_button_pressed(const StringName &p_name) const { |