From dcf199b0aeff821661521af879bd0403a7a09bb0 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Mon, 17 Apr 2023 14:23:05 -0700 Subject: [PATCH] Take item and skeleton transforms into account when calculating mesh AABB in 2D --- doc/classes/RenderingServer.xml | 8 ++++++++ drivers/gles3/storage/mesh_storage.cpp | 15 +++++++++++---- drivers/gles3/storage/mesh_storage.h | 2 +- servers/rendering/dummy/storage/mesh_storage.h | 2 +- servers/rendering/renderer_canvas_cull.h | 6 ++++++ servers/rendering/renderer_canvas_render.cpp | 7 ++++++- .../renderer_rd/storage_rd/mesh_storage.cpp | 15 +++++++++++---- .../renderer_rd/storage_rd/mesh_storage.h | 2 +- servers/rendering/rendering_server_default.h | 2 ++ servers/rendering/storage/mesh_storage.h | 2 +- servers/rendering_server.cpp | 2 ++ servers/rendering_server.h | 9 +++++++++ 12 files changed, 59 insertions(+), 13 deletions(-) diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 78572c4aa726..061780bb4954 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -891,6 +891,14 @@ [b]Note:[/b] When using the OpenGL backend or when running in headless mode, this function always returns [code]null[/code]. + + + + + Returns the bounding rectangle for a canvas item in local space, as calculated by the renderer. This bound is used internally for culling. + [b]Warning:[/b] This function is intended for debugging in the editor, and will pass through and return a zero [Rect2] in exported projects. + + diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index 44c9dc714c01..123252fca830 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -502,7 +502,7 @@ AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const { return mesh->custom_aabb; } -AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { +AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton, Transform3D p_transform) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); ERR_FAIL_COND_V(!mesh, AABB()); @@ -534,7 +534,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { if (skeleton->use_2d) { for (int j = 0; j < bs; j++) { - if (skbones[0].size == Vector3()) { + if (skbones[j].size == Vector3(-1, -1, -1)) { continue; //bone is unused } @@ -550,7 +550,14 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { mtx.basis.rows[1][1] = dataptr[5]; mtx.origin.y = dataptr[7]; - AABB baabb = mtx.xform(skbones[j]); + Vector2 t_x = skeleton->base_transform_2d.columns[0]; + Vector2 t_y = skeleton->base_transform_2d.columns[1]; + Vector2 origin = skeleton->base_transform_2d.columns[2]; + Transform3D skeleton_transform = Transform3D(Vector3(t_x.x, t_x.y, 0.0), Vector3(t_y.x, t_y.y, 0.0), Vector3(0.0, 0.0, 1.0), Vector3(origin.x, origin.y, 0.0)); + + Transform3D transform = skeleton_transform.affine_inverse() * p_transform; + + AABB baabb = transform.affine_inverse().xform(mtx.xform(transform.xform(skbones[j]))); if (first) { laabb = baabb; @@ -561,7 +568,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { } } else { for (int j = 0; j < bs; j++) { - if (skbones[0].size == Vector3()) { + if (skbones[j].size == Vector3(-1, -1, -1)) { continue; //bone is unused } diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h index f9122771f9d8..60b248fe71db 100644 --- a/drivers/gles3/storage/mesh_storage.h +++ b/drivers/gles3/storage/mesh_storage.h @@ -296,7 +296,7 @@ class MeshStorage : public RendererMeshStorage { virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override; virtual AABB mesh_get_custom_aabb(RID p_mesh) const override; - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override; + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID(), Transform3D p_transform = Transform3D()) override; virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override; virtual void mesh_clear(RID p_mesh) override; diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index aba362c95650..8e484eb9b526 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -114,7 +114,7 @@ class MeshStorage : public RendererMeshStorage { virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {} virtual AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); } - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); } + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID(), Transform3D p_transform = Transform3D()) override { return AABB(); } virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {} virtual void mesh_clear(RID p_mesh) override; diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 1106fc4f1ed5..a57ee573f23d 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -317,6 +317,12 @@ class RendererCanvasCull { void update_visibility_notifiers(); + Rect2 _debug_canvas_item_get_rect(RID p_item) { + Item *canvas_item = canvas_item_owner.get_or_null(p_item); + ERR_FAIL_COND_V(!canvas_item, Rect2()); + return canvas_item->get_rect(); + } + bool free(RID p_rid); RendererCanvasCull(); ~RendererCanvasCull(); diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp index af0ec621e5e7..2716dcf2e2d9 100644 --- a/servers/rendering/renderer_canvas_render.cpp +++ b/servers/rendering/renderer_canvas_render.cpp @@ -80,7 +80,12 @@ const Rect2 &RendererCanvasRender::Item::get_rect() const { } break; case Item::Command::TYPE_MESH: { const Item::CommandMesh *mesh = static_cast(c); - AABB aabb = RSG::mesh_storage->mesh_get_aabb(mesh->mesh, skeleton); + + Vector2 t_x = xform.columns[0]; + Vector2 t_y = xform.columns[1]; + Vector2 origin = xform.columns[2]; + Transform3D transform = Transform3D(Vector3(t_x.x, t_x.y, 0.0), Vector3(t_y.x, t_y.y, 0.0), Vector3(0.0, 0.0, 1.0), Vector3(origin.x, origin.y, 0.0)); + AABB aabb = RSG::mesh_storage->mesh_get_aabb(mesh->mesh, skeleton, transform); r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index b91e73c88580..2e8f03b8b2f4 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -597,7 +597,7 @@ AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const { return mesh->custom_aabb; } -AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { +AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton, Transform3D p_transform) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); ERR_FAIL_COND_V(!mesh, AABB()); @@ -627,7 +627,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { if (skeleton->use_2d) { for (int j = 0; j < bs; j++) { - if (skbones[0].size == Vector3()) { + if (skbones[j].size == Vector3(-1, -1, -1)) { continue; //bone is unused } @@ -643,7 +643,14 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { mtx.basis.rows[1][1] = dataptr[5]; mtx.origin.y = dataptr[7]; - AABB baabb = mtx.xform(skbones[j]); + Vector2 t_x = skeleton->base_transform_2d.columns[0]; + Vector2 t_y = skeleton->base_transform_2d.columns[1]; + Vector2 origin = skeleton->base_transform_2d.columns[2]; + Transform3D skeleton_transform = Transform3D(Vector3(t_x.x, t_x.y, 0.0), Vector3(t_y.x, t_y.y, 0.0), Vector3(0.0, 0.0, 1.0), Vector3(origin.x, origin.y, 0.0)); + + Transform3D transform = skeleton_transform.affine_inverse() * p_transform; + + AABB baabb = transform.affine_inverse().xform(mtx.xform(transform.xform(skbones[j]))); if (first) { laabb = baabb; @@ -654,7 +661,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { } } else { for (int j = 0; j < bs; j++) { - if (skbones[0].size == Vector3()) { + if (skbones[j].size == Vector3(-1, -1, -1)) { continue; //bone is unused } diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index c92152394123..2f661fe5aca1 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -352,7 +352,7 @@ class MeshStorage : public RendererMeshStorage { virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override; virtual AABB mesh_get_custom_aabb(RID p_mesh) const override; - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override; + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID(), Transform3D p_transform = Transform3D()) override; virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override; virtual void mesh_clear(RID p_mesh) override; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 249e5c2d9dfb..bd47bac857e7 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -923,6 +923,8 @@ class RenderingServerDefault : public RenderingServer { FUNC1(canvas_set_shadow_texture_size, int) + FUNC1R(Rect2, _debug_canvas_item_get_rect, RID) + /* GLOBAL SHADER UNIFORMS */ #undef server_name diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h index 76e46a696a69..1716a70dff0d 100644 --- a/servers/rendering/storage/mesh_storage.h +++ b/servers/rendering/storage/mesh_storage.h @@ -68,7 +68,7 @@ class RendererMeshStorage { virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0; + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID(), Transform3D p_transform = Transform3D()) = 0; virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index cc09825298a7..f0c6cfb34b92 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2631,6 +2631,8 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_set_visibility_notifier", "item", "enable", "area", "enter_callable", "exit_callable"), &RenderingServer::canvas_item_set_visibility_notifier); ClassDB::bind_method(D_METHOD("canvas_item_set_canvas_group_mode", "item", "mode", "clear_margin", "fit_empty", "fit_margin", "blur_mipmaps"), &RenderingServer::canvas_item_set_canvas_group_mode, DEFVAL(5.0), DEFVAL(false), DEFVAL(0.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("debug_canvas_item_get_rect", "item"), &RenderingServer::debug_canvas_item_get_rect); + BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH); BIND_ENUM_CONSTANT(NINE_PATCH_TILE); BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index a28374444386..07f34351f284 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1457,6 +1457,15 @@ class RenderingServer : public Object { virtual void canvas_set_shadow_texture_size(int p_size) = 0; + Rect2 debug_canvas_item_get_rect(RID p_item) { +#ifdef TOOLS_ENABLED + return _debug_canvas_item_get_rect(p_item); +#else + return Rect2(); +#endif + } + virtual Rect2 _debug_canvas_item_get_rect(RID p_item) = 0; + /* GLOBAL SHADER UNIFORMS */ enum GlobalShaderParameterType {