Skip to content

Commit

Permalink
Fix Occluder to properly share resources
Browse files Browse the repository at this point in the history
In order to properly support the resource sharing paradigm, Occluders are split into Instances and Resources in the VisualServer. Instances are owned by a Scenario, and Resources are global. OccluderShape resources can now correctly be shared by multiple OccluderInstances.
  • Loading branch information
lawnjelly committed Feb 16, 2022
1 parent 685d4b4 commit 3c2df49
Show file tree
Hide file tree
Showing 20 changed files with 729 additions and 387 deletions.
2 changes: 1 addition & 1 deletion doc/classes/OccluderShapeSphere.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</method>
</methods>
<members>
<member name="spheres" type="Array" setter="set_spheres" getter="get_spheres" default="[ ]">
<member name="spheres" type="Array" setter="set_spheres" getter="get_spheres" default="[ Plane( 0, 0, 0, 1 ) ]">
The sphere data can be accessed as an array of [Plane]s. The position of each sphere is stored in the [code]normal[/code], and the radius is stored in the [code]d[/code] value of the plane.
</member>
</members>
Expand Down
47 changes: 22 additions & 25 deletions scene/3d/occluder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@

void Occluder::resource_changed(RES res) {
update_gizmo();

if (_shape.is_valid()) {
_shape->update_shape_to_visual_server();
}
}

void Occluder::set_shape(const Ref<OccluderShape> &p_shape) {
Expand All @@ -52,16 +48,9 @@ void Occluder::set_shape(const Ref<OccluderShape> &p_shape) {
if (_shape.is_valid()) {
_shape->register_owner(this);

// Especially in the editor, the shape can be added AFTER the occluder
// is added to the world. This means the shape scenario will not be set.
// To remedy this we make sure the scenario etc is refreshed as soon as
// a shape is set on the occluder.
if (is_inside_world() && get_world().is_valid()) {
_shape->notification_enter_world(get_world()->get_scenario());
_shape->update_shape_to_visual_server();
if (is_inside_tree()) {
_shape->update_active_to_visual_server(is_visible_in_tree());
_shape->update_transform_to_visual_server(get_global_transform());
if (_occluder_instance.is_valid()) {
VisualServer::get_singleton()->occluder_instance_link_resource(_occluder_instance, p_shape->get_rid());
}
}
}
Expand Down Expand Up @@ -115,21 +104,25 @@ void Occluder::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
ERR_FAIL_COND(get_world().is_null());
if (_shape.is_valid()) {
_shape->notification_enter_world(get_world()->get_scenario());
_shape->update_active_to_visual_server(is_visible_in_tree());
_shape->update_shape_to_visual_server();
_shape->update_transform_to_visual_server(get_global_transform());

if (_occluder_instance.is_valid()) {
VisualServer::get_singleton()->occluder_instance_set_scenario(_occluder_instance, get_world()->get_scenario());
if (get_shape().is_valid()) {
VisualServer::get_singleton()->occluder_instance_link_resource(_occluder_instance, get_shape()->get_rid());
}
VisualServer::get_singleton()->occluder_instance_set_active(_occluder_instance, is_visible_in_tree());
VisualServer::get_singleton()->occluder_instance_set_transform(_occluder_instance, get_global_transform());
}

#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
set_process_internal(true);
}
#endif
} break;
case NOTIFICATION_EXIT_WORLD: {
if (_shape.is_valid()) {
_shape->notification_exit_world();
if (_occluder_instance.is_valid()) {
VisualServer::get_singleton()->occluder_instance_set_scenario(_occluder_instance, RID());
}
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
Expand All @@ -138,14 +131,13 @@ void Occluder::_notification(int p_what) {
#endif
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
if (_shape.is_valid() && is_inside_tree()) {
_shape->update_active_to_visual_server(is_visible_in_tree());
if (_occluder_instance.is_valid() && is_inside_tree()) {
VisualServer::get_singleton()->occluder_instance_set_active(_occluder_instance, is_visible_in_tree());
}
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
if (_shape.is_valid()) {
_shape->update_transform_to_visual_server(get_global_transform());

if (_occluder_instance.is_valid()) {
VisualServer::get_singleton()->occluder_instance_set_transform(_occluder_instance, get_global_transform());
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
update_configuration_warning();
Expand All @@ -171,10 +163,15 @@ void Occluder::_bind_methods() {
}

Occluder::Occluder() {
_occluder_instance = RID_PRIME(VisualServer::get_singleton()->occluder_instance_create());
set_notify_transform(true);
}

Occluder::~Occluder() {
if (_occluder_instance != RID()) {
VisualServer::get_singleton()->free(_occluder_instance);
}

if (!_shape.is_null()) {
_shape->unregister_owner(this);
}
Expand Down
1 change: 1 addition & 0 deletions scene/3d/occluder.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Occluder : public Spatial {
friend class OccluderSpatialGizmo;
friend class OccluderEditorPlugin;

RID _occluder_instance;
Ref<OccluderShape> _shape;

void resource_changed(RES res);
Expand Down
38 changes: 16 additions & 22 deletions scene/resources/occluder_shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,28 +41,16 @@
void OccluderShape::_bind_methods() {
}

OccluderShape::OccluderShape(RID p_shape) {
_shape = p_shape;
OccluderShape::OccluderShape() {
_shape = RID_PRIME(VisualServer::get_singleton()->occluder_resource_create());
}

OccluderShape::~OccluderShape() {
if (_shape != RID()) {
if (_shape.is_valid()) {
VisualServer::get_singleton()->free(_shape);
}
}

void OccluderShape::update_transform_to_visual_server(const Transform &p_global_xform) {
VisualServer::get_singleton()->occluder_set_transform(get_shape(), p_global_xform);
}

void OccluderShape::update_active_to_visual_server(bool p_active) {
VisualServer::get_singleton()->occluder_set_active(get_shape(), p_active);
}

void OccluderShape::notification_exit_world() {
VisualServer::get_singleton()->occluder_set_scenario(_shape, RID(), VisualServer::OCCLUDER_TYPE_UNDEFINED);
}

#ifdef TOOLS_ENABLED
AABB OccluderShape::get_fallback_gizmo_aabb() const {
return AABB(Vector3(-0.5, -0.5, -0.5), Vector3(1, 1, 1));
Expand Down Expand Up @@ -105,7 +93,7 @@ AABB OccluderShapeSphere::get_fallback_gizmo_aabb() const {
#endif

void OccluderShapeSphere::update_shape_to_visual_server() {
VisualServer::get_singleton()->occluder_spheres_update(get_shape(), _spheres);
VisualServer::get_singleton()->occluder_resource_spheres_update(get_shape(), _spheres);
}

Transform OccluderShapeSphere::center_node(const Transform &p_global_xform, const Transform &p_parent_xform, real_t p_snap) {
Expand Down Expand Up @@ -189,10 +177,6 @@ Transform OccluderShapeSphere::center_node(const Transform &p_global_xform, cons
return new_local_xform;
}

void OccluderShapeSphere::notification_enter_world(RID p_scenario) {
VisualServer::get_singleton()->occluder_set_scenario(get_shape(), p_scenario, VisualServer::OCCLUDER_TYPE_SPHERE);
}

void OccluderShapeSphere::set_spheres(const Vector<Plane> &p_spheres) {
#ifdef TOOLS_ENABLED
// try and detect special circumstance of adding a new sphere in the editor
Expand Down Expand Up @@ -221,6 +205,7 @@ void OccluderShapeSphere::set_spheres(const Vector<Plane> &p_spheres) {
_update_aabb();
#endif

update_shape_to_visual_server();
notify_change_to_owners();
}

Expand All @@ -232,6 +217,7 @@ void OccluderShapeSphere::set_sphere_position(int p_idx, const Vector3 &p_positi
#ifdef TOOLS_ENABLED
_update_aabb();
#endif
update_shape_to_visual_server();
notify_change_to_owners();
}
}
Expand All @@ -244,10 +230,18 @@ void OccluderShapeSphere::set_sphere_radius(int p_idx, real_t p_radius) {
#ifdef TOOLS_ENABLED
_update_aabb();
#endif
update_shape_to_visual_server();
notify_change_to_owners();
}
}

OccluderShapeSphere::OccluderShapeSphere() :
OccluderShape(RID_PRIME(VisualServer::get_singleton()->occluder_create())) {
OccluderShapeSphere::OccluderShapeSphere() {
if (get_shape().is_valid()) {
VisualServer::get_singleton()->occluder_resource_prepare(get_shape(), VisualServer::OCCLUDER_TYPE_SPHERE);
}

// Create a default sphere
Vector<Plane> planes;
planes.push_back(Plane(Vector3(0, 0, 0), 1));
set_spheres(planes);
}
10 changes: 2 additions & 8 deletions scene/resources/occluder_shape.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,12 @@ class OccluderShape : public Resource {
static void _bind_methods();

RID get_shape() const { return _shape; }
OccluderShape(RID p_shape);
OccluderShape();

public:
virtual RID get_rid() const { return _shape; }
~OccluderShape();

virtual void notification_enter_world(RID p_scenario) = 0;
virtual void update_shape_to_visual_server() = 0;
void update_transform_to_visual_server(const Transform &p_global_xform);
void update_active_to_visual_server(bool p_active);
void notification_exit_world();
virtual Transform center_node(const Transform &p_global_xform, const Transform &p_parent_xform, real_t p_snap) = 0;

#ifdef TOOLS_ENABLED
Expand Down Expand Up @@ -87,8 +82,7 @@ class OccluderShapeSphere : public OccluderShape {
void set_sphere_position(int p_idx, const Vector3 &p_position);
void set_sphere_radius(int p_idx, real_t p_radius);

virtual void notification_enter_world(RID p_scenario);
virtual void update_shape_to_visual_server();
void update_shape_to_visual_server();
virtual Transform center_node(const Transform &p_global_xform, const Transform &p_parent_xform, real_t p_snap);

#ifdef TOOLS_ENABLED
Expand Down
18 changes: 11 additions & 7 deletions scene/resources/occluder_shape_polygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ void OccluderShapePolygon::set_polygon_point(int p_idx, const Vector2 &p_point)

_poly_pts_local_raw.set(p_idx, p_point);
_sanitize_points();
update_shape_to_visual_server();
notify_change_to_owners();
}

Expand All @@ -118,18 +119,21 @@ void OccluderShapePolygon::set_hole_point(int p_idx, const Vector2 &p_point) {

_hole_pts_local_raw.set(p_idx, p_point);
_sanitize_points();
update_shape_to_visual_server();
notify_change_to_owners();
}

void OccluderShapePolygon::set_polygon_points(const PoolVector<Vector2> &p_points) {
_poly_pts_local_raw = p_points;
_sanitize_points();
update_shape_to_visual_server();
notify_change_to_owners();
}

void OccluderShapePolygon::set_hole_points(const PoolVector<Vector2> &p_points) {
_hole_pts_local_raw = p_points;
_sanitize_points();
update_shape_to_visual_server();
notify_change_to_owners();
}

Expand All @@ -141,10 +145,6 @@ PoolVector<Vector2> OccluderShapePolygon::get_hole_points() const {
return _hole_pts_local_raw;
}

void OccluderShapePolygon::notification_enter_world(RID p_scenario) {
VisualServer::get_singleton()->occluder_set_scenario(get_shape(), p_scenario, VisualServer::OCCLUDER_TYPE_MESH);
}

void OccluderShapePolygon::update_shape_to_visual_server() {
if (_poly_pts_local.size() < 3)
return;
Expand Down Expand Up @@ -179,11 +179,12 @@ void OccluderShapePolygon::update_shape_to_visual_server() {

face.plane = Plane(Vector3(0, 0, 0), Vector3(0, 0, -1));

VisualServer::get_singleton()->occluder_mesh_update(get_shape(), md);
VisualServer::get_singleton()->occluder_resource_mesh_update(get_shape(), md);
}

void OccluderShapePolygon::set_two_way(bool p_two_way) {
_settings_two_way = p_two_way;
update_shape_to_visual_server();
notify_change_to_owners();
}

Expand Down Expand Up @@ -221,8 +222,11 @@ void OccluderShapePolygon::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "hole_points"), "set_hole_points", "get_hole_points");
}

OccluderShapePolygon::OccluderShapePolygon() :
OccluderShape(RID_PRIME(VisualServer::get_singleton()->occluder_create())) {
OccluderShapePolygon::OccluderShapePolygon() {
if (get_shape().is_valid()) {
VisualServer::get_singleton()->occluder_resource_prepare(get_shape(), VisualServer::OCCLUDER_TYPE_MESH);
}

clear();

PoolVector<Vector2> points;
Expand Down
3 changes: 1 addition & 2 deletions scene/resources/occluder_shape_polygon.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ class OccluderShapePolygon : public OccluderShape {

void clear();

virtual void notification_enter_world(RID p_scenario);
virtual void update_shape_to_visual_server();
void update_shape_to_visual_server();
virtual Transform center_node(const Transform &p_global_xform, const Transform &p_parent_xform, real_t p_snap);

#ifdef TOOLS_ENABLED
Expand Down
Loading

0 comments on commit 3c2df49

Please sign in to comment.