summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/arvr_nodes.cpp6
-rw-r--r--scene/3d/arvr_nodes.h2
-rw-r--r--scene/3d/camera.cpp11
-rw-r--r--scene/3d/camera.h2
-rw-r--r--scene/3d/cpu_particles.cpp2
-rw-r--r--scene/3d/navigation_mesh.cpp84
-rw-r--r--scene/3d/navigation_mesh.h21
-rw-r--r--scene/3d/particles.cpp2
-rw-r--r--scene/3d/proximity_group.cpp1
-rw-r--r--scene/3d/spatial.cpp23
-rw-r--r--scene/3d/vehicle_body.cpp14
-rw-r--r--scene/3d/vehicle_body.h3
-rw-r--r--scene/3d/visual_instance.cpp7
-rw-r--r--scene/3d/visual_instance.h2
14 files changed, 154 insertions, 26 deletions
diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp
index 52fa96ee4a..4e88948ce2 100644
--- a/scene/3d/arvr_nodes.cpp
+++ b/scene/3d/arvr_nodes.cpp
@@ -127,7 +127,7 @@ Point2 ARVRCamera::unproject_position(const Vector3 &p_pos) const {
return res;
};
-Vector3 ARVRCamera::project_position(const Point2 &p_point) const {
+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());
@@ -135,7 +135,7 @@ Vector3 ARVRCamera::project_position(const Point2 &p_point) const {
Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface();
if (arvr_interface.is_null()) {
// we might be in the editor or have VR turned off, just call superclass
- return Camera::project_position(p_point);
+ return Camera::project_position(p_point, p_z_depth);
}
if (!is_inside_tree()) {
@@ -155,7 +155,7 @@ Vector3 ARVRCamera::project_position(const Point2 &p_point) const {
point.y = (1.0 - (p_point.y / viewport_size.y)) * 2.0 - 1.0;
point *= vp_size;
- Vector3 p(point.x, point.y, -get_znear());
+ Vector3 p(point.x, point.y, -p_z_depth);
return get_camera_transform().xform(p);
};
diff --git a/scene/3d/arvr_nodes.h b/scene/3d/arvr_nodes.h
index 0833e18d48..8e735f7110 100644
--- a/scene/3d/arvr_nodes.h
+++ b/scene/3d/arvr_nodes.h
@@ -55,7 +55,7 @@ public:
virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const;
virtual Point2 unproject_position(const Vector3 &p_pos) const;
- virtual Vector3 project_position(const Point2 &p_point) const;
+ virtual Vector3 project_position(const Point2 &p_point, float p_z_depth = 0) const;
virtual Vector<Plane> get_frustum() const;
ARVRCamera();
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 8b91f56344..29002c6701 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -391,13 +391,17 @@ Point2 Camera::unproject_position(const Vector3 &p_pos) const {
return res;
}
-Vector3 Camera::project_position(const Point2 &p_point) const {
+Vector3 Camera::project_position(const Point2 &p_point, float p_z_depth) const {
if (!is_inside_tree()) {
ERR_EXPLAIN("Camera is not inside scene.");
ERR_FAIL_COND_V(!is_inside_tree(), Vector3());
}
+ if (p_z_depth == 0) {
+ return get_global_transform().origin;
+ }
+
Size2 viewport_size = get_viewport()->get_visible_rect().size;
CameraMatrix cm;
@@ -415,7 +419,7 @@ Vector3 Camera::project_position(const Point2 &p_point) const {
point.y = (1.0 - (p_point.y / viewport_size.y)) * 2.0 - 1.0;
point *= vp_size;
- Vector3 p(point.x, point.y, -near);
+ Vector3 p(point.x, point.y, -p_z_depth);
return get_camera_transform().xform(p);
}
@@ -490,7 +494,7 @@ void Camera::_bind_methods() {
ClassDB::bind_method(D_METHOD("project_ray_origin", "screen_point"), &Camera::project_ray_origin);
ClassDB::bind_method(D_METHOD("unproject_position", "world_point"), &Camera::unproject_position);
ClassDB::bind_method(D_METHOD("is_position_behind", "world_point"), &Camera::is_position_behind);
- ClassDB::bind_method(D_METHOD("project_position", "screen_point"), &Camera::project_position);
+ ClassDB::bind_method(D_METHOD("project_position", "screen_point", "z_depth"), &Camera::project_position, DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_perspective", "fov", "z_near", "z_far"), &Camera::set_perspective);
ClassDB::bind_method(D_METHOD("set_orthogonal", "size", "z_near", "z_far"), &Camera::set_orthogonal);
ClassDB::bind_method(D_METHOD("set_frustum", "size", "offset", "z_near", "z_far"), &Camera::set_frustum);
@@ -524,6 +528,7 @@ void Camera::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera::set_doppler_tracking);
ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera::get_doppler_tracking);
ClassDB::bind_method(D_METHOD("get_frustum"), &Camera::get_frustum);
+ ClassDB::bind_method(D_METHOD("get_camera_rid"), &Camera::get_camera);
ClassDB::bind_method(D_METHOD("set_cull_mask_bit", "layer", "enable"), &Camera::set_cull_mask_bit);
ClassDB::bind_method(D_METHOD("get_cull_mask_bit", "layer"), &Camera::get_cull_mask_bit);
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index fe8cb84f0d..cbcefbb0ae 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -143,7 +143,7 @@ public:
virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const;
virtual Point2 unproject_position(const Vector3 &p_pos) const;
bool is_position_behind(const Vector3 &p_pos) const;
- virtual Vector3 project_position(const Point2 &p_point) const;
+ virtual Vector3 project_position(const Point2 &p_point, float p_z_depth = 0) const;
Vector<Vector3> get_near_plane_points() const;
diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp
index d4e242dcb7..138c446fea 100644
--- a/scene/3d/cpu_particles.cpp
+++ b/scene/3d/cpu_particles.cpp
@@ -212,7 +212,7 @@ String CPUParticles::get_configuration_warning() const {
get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid())) {
if (warnings != String())
warnings += "\n";
- warnings += "- " + TTR("CPUParticles animation requires the usage of a SpatialMaterial with \"Billboard Particles\" enabled.");
+ warnings += "- " + TTR("CPUParticles animation requires the usage of a SpatialMaterial whose Billboard Mode is set to \"Particle Billboard\".");
}
return warnings;
diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp
index 003f76664d..f82543b789 100644
--- a/scene/3d/navigation_mesh.cpp
+++ b/scene/3d/navigation_mesh.cpp
@@ -73,6 +73,41 @@ int NavigationMesh::get_sample_partition_type() const {
return static_cast<int>(partition_type);
}
+void NavigationMesh::set_parsed_geometry_type(int p_value) {
+ ERR_FAIL_COND(p_value >= PARSED_GEOMETRY_MAX);
+ parsed_geometry_type = static_cast<ParsedGeometryType>(p_value);
+ _change_notify();
+}
+
+int NavigationMesh::get_parsed_geometry_type() const {
+ return parsed_geometry_type;
+}
+
+void NavigationMesh::set_collision_mask(uint32_t p_mask) {
+
+ collision_mask = p_mask;
+}
+
+uint32_t NavigationMesh::get_collision_mask() const {
+
+ return collision_mask;
+}
+
+void NavigationMesh::set_collision_mask_bit(int p_bit, bool p_value) {
+
+ uint32_t mask = get_collision_mask();
+ if (p_value)
+ mask |= 1 << p_bit;
+ else
+ mask &= ~(1 << p_bit);
+ set_collision_mask(mask);
+}
+
+bool NavigationMesh::get_collision_mask_bit(int p_bit) const {
+
+ return get_collision_mask() & (1 << p_bit);
+}
+
void NavigationMesh::set_cell_size(float p_value) {
cell_size = p_value;
}
@@ -204,6 +239,7 @@ bool NavigationMesh::get_filter_walkable_low_height_spans() const {
void NavigationMesh::set_vertices(const PoolVector<Vector3> &p_vertices) {
vertices = p_vertices;
+ _change_notify();
}
PoolVector<Vector3> NavigationMesh::get_vertices() const {
@@ -217,6 +253,7 @@ void NavigationMesh::_set_polygons(const Array &p_array) {
for (int i = 0; i < p_array.size(); i++) {
polygons.write[i].indices = p_array[i];
}
+ _change_notify();
}
Array NavigationMesh::_get_polygons() const {
@@ -235,6 +272,7 @@ void NavigationMesh::add_polygon(const Vector<int> &p_polygon) {
Polygon polygon;
polygon.indices = p_polygon;
polygons.push_back(polygon);
+ _change_notify();
}
int NavigationMesh::get_polygon_count() const {
@@ -340,6 +378,15 @@ void NavigationMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sample_partition_type", "sample_partition_type"), &NavigationMesh::set_sample_partition_type);
ClassDB::bind_method(D_METHOD("get_sample_partition_type"), &NavigationMesh::get_sample_partition_type);
+ ClassDB::bind_method(D_METHOD("set_parsed_geometry_type", "geometry_type"), &NavigationMesh::set_parsed_geometry_type);
+ ClassDB::bind_method(D_METHOD("get_parsed_geometry_type"), &NavigationMesh::get_parsed_geometry_type);
+
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &NavigationMesh::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &NavigationMesh::get_collision_mask);
+
+ ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &NavigationMesh::set_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &NavigationMesh::get_collision_mask_bit);
+
ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &NavigationMesh::set_cell_size);
ClassDB::bind_method(D_METHOD("get_cell_size"), &NavigationMesh::get_cell_size);
@@ -405,10 +452,16 @@ void NavigationMesh::_bind_methods() {
BIND_CONSTANT(SAMPLE_PARTITION_MONOTONE);
BIND_CONSTANT(SAMPLE_PARTITION_LAYERS);
+ BIND_CONSTANT(PARSED_GEOMETRY_MESH_INSTANCES);
+ BIND_CONSTANT(PARSED_GEOMETRY_STATIC_COLLIDERS);
+ BIND_CONSTANT(PARSED_GEOMETRY_BOTH);
+
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sample_partition_type/sample_partition_type", PROPERTY_HINT_ENUM, "Watershed,Monotone,Layers"), "set_sample_partition_type", "get_sample_partition_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Both"), "set_parsed_geometry_type", "get_parsed_geometry_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell/size", PROPERTY_HINT_RANGE, "0.1,1.0,0.01,or_greater"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell/height", PROPERTY_HINT_RANGE, "0.1,1.0,0.01,or_greater"), "set_cell_height", "get_cell_height");
@@ -429,6 +482,15 @@ void NavigationMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter/filter_walkable_low_height_spans"), "set_filter_walkable_low_height_spans", "get_filter_walkable_low_height_spans");
}
+void NavigationMesh::_validate_property(PropertyInfo &property) const {
+ if (property.name == "geometry/collision_mask") {
+ if (parsed_geometry_type == PARSED_GEOMETRY_MESH_INSTANCES) {
+ property.usage = 0;
+ return;
+ }
+ }
+}
+
NavigationMesh::NavigationMesh() {
cell_size = 0.3f;
cell_height = 0.2f;
@@ -445,7 +507,8 @@ NavigationMesh::NavigationMesh() {
detail_sample_max_error = 1.0f;
partition_type = SAMPLE_PARTITION_WATERSHED;
-
+ parsed_geometry_type = PARSED_GEOMETRY_MESH_INSTANCES;
+ collision_mask = 0xFFFFFFFF;
filter_low_hanging_obstacles = false;
filter_ledge_spans = false;
filter_walkable_low_height_spans = false;
@@ -566,8 +629,17 @@ void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh> &p_na
navigation->navmesh_remove(nav_id);
nav_id = -1;
}
+
+ if (navmesh.is_valid()) {
+ navmesh->remove_change_receptor(this);
+ }
+
navmesh = p_navmesh;
+ if (navmesh.is_valid()) {
+ navmesh->add_change_receptor(this);
+ }
+
if (navigation && navmesh.is_valid() && enabled) {
nav_id = navigation->navmesh_add(navmesh, get_relative_transform(navigation), this);
}
@@ -617,6 +689,11 @@ void NavigationMeshInstance::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
}
+void NavigationMeshInstance::_changed_callback(Object *p_changed, const char *p_prop) {
+ update_gizmo();
+ update_configuration_warning();
+}
+
NavigationMeshInstance::NavigationMeshInstance() {
debug_view = NULL;
@@ -625,3 +702,8 @@ NavigationMeshInstance::NavigationMeshInstance() {
enabled = true;
set_notify_transform(true);
}
+
+NavigationMeshInstance::~NavigationMeshInstance() {
+ if (navmesh.is_valid())
+ navmesh->remove_change_receptor(this);
+}
diff --git a/scene/3d/navigation_mesh.h b/scene/3d/navigation_mesh.h
index 74531e2423..5fbf3998ff 100644
--- a/scene/3d/navigation_mesh.h
+++ b/scene/3d/navigation_mesh.h
@@ -57,6 +57,7 @@ class NavigationMesh : public Resource {
protected:
static void _bind_methods();
+ virtual void _validate_property(PropertyInfo &property) const;
void _set_polygons(const Array &p_array);
Array _get_polygons() const;
@@ -69,6 +70,13 @@ public:
SAMPLE_PARTITION_MAX
};
+ enum ParsedGeometryType {
+ PARSED_GEOMETRY_MESH_INSTANCES = 0,
+ PARSED_GEOMETRY_STATIC_COLLIDERS,
+ PARSED_GEOMETRY_BOTH,
+ PARSED_GEOMETRY_MAX
+ };
+
protected:
float cell_size;
float cell_height;
@@ -85,6 +93,8 @@ protected:
float detail_sample_max_error;
SamplePartitionType partition_type;
+ ParsedGeometryType parsed_geometry_type;
+ uint32_t collision_mask;
bool filter_low_hanging_obstacles;
bool filter_ledge_spans;
@@ -95,6 +105,15 @@ public:
void set_sample_partition_type(int p_value);
int get_sample_partition_type() const;
+ void set_parsed_geometry_type(int p_value);
+ int get_parsed_geometry_type() const;
+
+ void set_collision_mask(uint32_t p_mask);
+ uint32_t get_collision_mask() const;
+
+ void set_collision_mask_bit(int p_bit, bool p_value);
+ bool get_collision_mask_bit(int p_bit) const;
+
void set_cell_size(float p_value);
float get_cell_size() const;
@@ -174,6 +193,7 @@ class NavigationMeshInstance : public Spatial {
protected:
void _notification(int p_what);
static void _bind_methods();
+ void _changed_callback(Object *p_changed, const char *p_prop);
public:
void set_enabled(bool p_enabled);
@@ -185,6 +205,7 @@ public:
String get_configuration_warning() const;
NavigationMeshInstance();
+ ~NavigationMeshInstance();
};
#endif // NAVIGATION_MESH_H
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp
index 57ab01f7be..156560f802 100644
--- a/scene/3d/particles.cpp
+++ b/scene/3d/particles.cpp
@@ -268,7 +268,7 @@ String Particles::get_configuration_warning() const {
process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) {
if (warnings != String())
warnings += "\n";
- warnings += "- " + TTR("Particles animation requires the usage of a SpatialMaterial with \"Billboard Particles\" enabled.");
+ warnings += "- " + TTR("Particles animation requires the usage of a SpatialMaterial whose Billboard Mode is set to \"Particle Billboard\".");
}
}
diff --git a/scene/3d/proximity_group.cpp b/scene/3d/proximity_group.cpp
index 12eab2e4e8..96dc3304f2 100644
--- a/scene/3d/proximity_group.cpp
+++ b/scene/3d/proximity_group.cpp
@@ -204,6 +204,7 @@ ProximityGroup::ProximityGroup() {
group_version = 0;
dispatch_mode = MODE_PROXY;
+ cell_size = 1.0;
grid_radius = Vector3(1, 1, 1);
set_notify_transform(true);
};
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index 05fd984f93..efd418e3c7 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -676,28 +676,29 @@ void Spatial::set_identity() {
void Spatial::look_at(const Vector3 &p_target, const Vector3 &p_up) {
- Transform lookat(get_global_transform());
- if (lookat.origin == p_target) {
+ Vector3 origin(get_global_transform().origin);
+ look_at_from_position(origin, p_target, p_up);
+}
+
+void Spatial::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up) {
+
+ if (p_pos == p_target) {
ERR_EXPLAIN("Node origin and target are in the same position, look_at() failed");
ERR_FAIL();
}
- if (p_up.cross(p_target - lookat.origin) == Vector3()) {
+ if (p_up.cross(p_target - p_pos) == Vector3()) {
ERR_EXPLAIN("Up vector and direction between node origin and target are aligned, look_at() failed");
ERR_FAIL();
}
- Vector3 original_scale(lookat.basis.get_scale());
- lookat = lookat.looking_at(p_target, p_up);
- // as basis was normalized, we just need to apply original scale back
- lookat.basis.scale(original_scale);
- set_global_transform(lookat);
-}
-
-void Spatial::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up) {
Transform lookat;
lookat.origin = p_pos;
+
+ Vector3 original_scale(get_global_transform().basis.get_scale());
lookat = lookat.looking_at(p_target, p_up);
+ // as basis was normalized, we just need to apply original scale back
+ lookat.basis.scale(original_scale);
set_global_transform(lookat);
}
diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp
index fde135c972..32b8219ee0 100644
--- a/scene/3d/vehicle_body.cpp
+++ b/scene/3d/vehicle_body.cpp
@@ -270,6 +270,8 @@ void VehicleWheel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_skidinfo"), &VehicleWheel::get_skidinfo);
+ ClassDB::bind_method(D_METHOD("get_rpm"), &VehicleWheel::get_rpm);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_traction"), "set_use_as_traction", "is_used_as_traction");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_steering"), "set_use_as_steering", "is_used_as_steering");
ADD_GROUP("Wheel", "wheel_");
@@ -311,6 +313,11 @@ float VehicleWheel::get_skidinfo() const {
return m_skidInfo;
}
+float VehicleWheel::get_rpm() const {
+
+ return m_rpm;
+}
+
VehicleWheel::VehicleWheel() {
steers = false;
@@ -865,12 +872,11 @@ void VehicleBody::_direct_state_changed(Object *p_state) {
real_t proj2 = fwd.dot(vel);
wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelRadius);
- wheel.m_rotation += wheel.m_deltaRotation;
-
- } else {
- wheel.m_rotation += wheel.m_deltaRotation;
}
+ wheel.m_rotation += wheel.m_deltaRotation;
+ wheel.m_rpm = ((wheel.m_deltaRotation / step) * 60) / Math_TAU;
+
wheel.m_deltaRotation *= real_t(0.99); //damping of rotation when not in contact
}
diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h
index 7e7571df4d..9e3fe72282 100644
--- a/scene/3d/vehicle_body.h
+++ b/scene/3d/vehicle_body.h
@@ -68,6 +68,7 @@ class VehicleWheel : public Spatial {
real_t m_steering;
real_t m_rotation;
real_t m_deltaRotation;
+ real_t m_rpm;
real_t m_rollInfluence;
//real_t m_engineForce;
real_t m_brake;
@@ -134,6 +135,8 @@ public:
float get_skidinfo() const;
+ float get_rpm() const;
+
String get_configuration_warning() const;
VehicleWheel();
diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp
index 1aded826c0..99c86f0406 100644
--- a/scene/3d/visual_instance.cpp
+++ b/scene/3d/visual_instance.cpp
@@ -271,6 +271,11 @@ float GeometryInstance::get_extra_cull_margin() const {
return extra_cull_margin;
}
+void GeometryInstance::set_custom_aabb(AABB aabb) {
+
+ VS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb);
+}
+
void GeometryInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_material_override", "material"), &GeometryInstance::set_material_override);
@@ -297,6 +302,8 @@ void GeometryInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance::set_extra_cull_margin);
ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
+ ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &GeometryInstance::set_custom_aabb);
+
ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance::get_aabb);
ADD_GROUP("Geometry", "");
diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h
index f5b7479bb1..0e7d9be505 100644
--- a/scene/3d/visual_instance.h
+++ b/scene/3d/visual_instance.h
@@ -139,6 +139,8 @@ public:
void set_extra_cull_margin(float p_margin);
float get_extra_cull_margin() const;
+ void set_custom_aabb(AABB aabb);
+
GeometryInstance();
};