From 5ab7ba9aa7d6075e1e20757efa4acc80a2037b3c Mon Sep 17 00:00:00 2001 From: DxUr Date: Sat, 4 Nov 2023 17:16:32 +0100 Subject: [PATCH 01/17] Add Custom Projection Add custom_projection property to Camera3D --- doc/classes/Camera3D.xml | 7 ++++ .../plugins/gizmos/camera_3d_gizmo_plugin.cpp | 4 ++ scene/3d/camera_3d.cpp | 40 ++++++++++++++++++- scene/3d/camera_3d.h | 6 ++- servers/rendering/renderer_scene_cull.cpp | 10 +++++ servers/rendering/renderer_scene_cull.h | 5 ++- servers/rendering/rendering_method.h | 1 + servers/rendering/rendering_server_default.h | 1 + servers/rendering_server.cpp | 1 + servers/rendering_server.h | 1 + 10 files changed, 72 insertions(+), 4 deletions(-) diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml index 27194122d56..f10fa88c2f0 100644 --- a/doc/classes/Camera3D.xml +++ b/doc/classes/Camera3D.xml @@ -172,6 +172,10 @@ If [code]true[/code], the ancestor [Viewport] is currently using this camera. If multiple cameras are in the scene, one will always be made current. For example, if two [Camera3D] nodes are present in the scene and only one is current, setting one camera's [member current] to [code]false[/code] will cause the other camera to be made current. + + The camera's [Projection]. This can be changed from the default to apply custom projection matrix. + [b]Note:[/b] Only effective if [member projection] is [constant PROJECTION_CUSTOM]. + If not [constant DOPPLER_TRACKING_DISABLED], this camera will simulate the [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] for objects changed in particular [code]_process[/code] methods. See [enum DopplerTracking] for possible values. @@ -222,6 +226,9 @@ Frustum projection. This mode allows adjusting [member frustum_offset] to create "tilted frustum" effects. + + Custom projection. This mode allows using [member custom_projection]. + Preserves the horizontal aspect ratio; also known as Vert- scaling. This is usually the best option for projects running in portrait mode, as taller aspect ratios will benefit from a wider vertical FOV. diff --git a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp index 63a48d4165d..f9eb8a95fd6 100644 --- a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp @@ -264,6 +264,10 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector3 tup(0, up.y + hsize / 2, side.z); ADD_TRIANGLE(tup + offset, side + up + offset, nside + up + offset); } break; + + case Camera3D::PROJECTION_CUSTOM: { + // Show Nothing + } } #undef ADD_TRIANGLE diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index c70fa3ca2e7..6089fb1aa2c 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -55,6 +55,11 @@ void Camera3D::_update_camera_mode() { case PROJECTION_FRUSTUM: { set_frustum(size, frustum_offset, _near, _far); } break; + case PROJECTION_CUSTOM: { + RenderingServer::get_singleton()->camera_set_custom(camera, c_proj); + update_gizmos(); + force_change = false; + } break; } } @@ -71,8 +76,21 @@ void Camera3D::_validate_property(PropertyInfo &p_property) const { if (mode != PROJECTION_FRUSTUM) { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } + } else if (p_property.name == "custom_projection") { + if (mode != PROJECTION_CUSTOM) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; + } + } else if (p_property.name == "near") { + if (mode == PROJECTION_CUSTOM) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; + } + } else if (p_property.name == "far") { + if (mode == PROJECTION_CUSTOM) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; + } } + if (attributes.is_valid()) { const CameraAttributesPhysical *physical_attributes = Object::cast_to(attributes.ptr()); if (physical_attributes) { @@ -309,6 +327,9 @@ Projection Camera3D::_get_camera_projection(real_t p_near) const { case PROJECTION_FRUSTUM: { cm.set_frustum(size, viewport_size.aspect(), frustum_offset, p_near, _far); } break; + case PROJECTION_CUSTOM: { + cm = c_proj; + } break; } return cm; @@ -368,7 +389,9 @@ void Camera3D::set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, rea } void Camera3D::set_projection(ProjectionType p_mode) { - if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM) { + if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) + c_proj = get_camera_projection(); + if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM || p_mode == PROJECTION_CUSTOM) { mode = p_mode; _update_camera_mode(); notify_property_list_changed(); @@ -650,6 +673,7 @@ void Camera3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_perspective", "fov", "z_near", "z_far"), &Camera3D::set_perspective); ClassDB::bind_method(D_METHOD("set_orthogonal", "size", "z_near", "z_far"), &Camera3D::set_orthogonal); ClassDB::bind_method(D_METHOD("set_frustum", "size", "offset", "z_near", "z_far"), &Camera3D::set_frustum); + ClassDB::bind_method(D_METHOD("set_custom_projection", "p_proj"), &Camera3D::set_custom_projection); ClassDB::bind_method(D_METHOD("make_current"), &Camera3D::make_current); ClassDB::bind_method(D_METHOD("clear_current", "enable_next"), &Camera3D::clear_current, DEFVAL(true)); ClassDB::bind_method(D_METHOD("set_current", "enabled"), &Camera3D::set_current); @@ -660,6 +684,7 @@ void Camera3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_frustum_offset"), &Camera3D::get_frustum_offset); ClassDB::bind_method(D_METHOD("get_size"), &Camera3D::get_size); ClassDB::bind_method(D_METHOD("get_far"), &Camera3D::get_far); + ClassDB::bind_method(D_METHOD("get_custom_projection"), &Camera3D::get_custom_projection); ClassDB::bind_method(D_METHOD("get_near"), &Camera3D::get_near); ClassDB::bind_method(D_METHOD("set_fov", "fov"), &Camera3D::set_fov); ClassDB::bind_method(D_METHOD("set_frustum_offset", "offset"), &Camera3D::set_frustum_offset); @@ -702,17 +727,19 @@ void Camera3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_v_offset", "get_v_offset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum,Custom"), "set_projection", "get_projection"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1,degrees"), "set_fov", "get_fov"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater,suffix:m"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_frustum_offset", "get_frustum_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater,exp,suffix:m"), "set_near", "get_near"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_RANGE, "0.01,4000,0.01,or_greater,exp,suffix:m"), "set_far", "get_far"); + ADD_PROPERTY(PropertyInfo(Variant::PROJECTION, "custom_projection"), "set_custom_projection", "get_custom_projection"); BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE); BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL); BIND_ENUM_CONSTANT(PROJECTION_FRUSTUM); + BIND_ENUM_CONSTANT(PROJECTION_CUSTOM); BIND_ENUM_CONSTANT(KEEP_WIDTH); BIND_ENUM_CONSTANT(KEEP_HEIGHT); @@ -742,6 +769,10 @@ real_t Camera3D::get_far() const { return _far; } +Projection Camera3D::get_custom_projection() const { + return c_proj; +} + Camera3D::ProjectionType Camera3D::get_projection() const { return mode; } @@ -773,6 +804,11 @@ void Camera3D::set_far(real_t p_far) { _update_camera_mode(); } +void Camera3D::set_custom_projection(Projection p_proj) { + c_proj = p_proj; + _update_camera_mode(); +} + void Camera3D::set_cull_mask(uint32_t p_layers) { layers = p_layers; RenderingServer::get_singleton()->camera_set_cull_mask(camera, layers); diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h index 3e9f940ad64..8574cb5eecb 100644 --- a/scene/3d/camera_3d.h +++ b/scene/3d/camera_3d.h @@ -44,7 +44,8 @@ class Camera3D : public Node3D { enum ProjectionType { PROJECTION_PERSPECTIVE, PROJECTION_ORTHOGONAL, - PROJECTION_FRUSTUM + PROJECTION_FRUSTUM, + PROJECTION_CUSTOM }; enum KeepAspect { @@ -74,6 +75,7 @@ class Camera3D : public Node3D { real_t v_offset = 0.0; real_t h_offset = 0.0; KeepAspect keep_aspect = KEEP_HEIGHT; + Projection c_proj; RID camera; RID scenario_id; @@ -152,6 +154,7 @@ class Camera3D : public Node3D { void set_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far); void set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, real_t p_z_far); void set_projection(Camera3D::ProjectionType p_mode); + void set_custom_projection(Projection p_proj); void make_current(); void clear_current(bool p_enable_next = true); @@ -163,6 +166,7 @@ class Camera3D : public Node3D { real_t get_fov() const; real_t get_size() const; real_t get_far() const; + Projection get_custom_projection() const; real_t get_near() const; Vector2 get_frustum_offset() const; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 43abb22e3d8..c0b3dc99eb5 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -110,6 +110,13 @@ void RendererSceneCull::camera_set_frustum(RID p_camera, float p_size, Vector2 p camera->zfar = p_z_far; } +void RendererSceneCull::camera_set_custom(RID p_camera, Projection p_proj) { + Camera *camera = camera_owner.get_or_null(p_camera); + ERR_FAIL_NULL(camera); + camera->type = Camera::CUSTOM; + camera->c_proj = p_proj; +} + void RendererSceneCull::camera_set_transform(RID p_camera, const Transform3D &p_transform) { Camera *camera = camera_owner.get_or_null(p_camera); ERR_FAIL_NULL(camera); @@ -2755,6 +2762,9 @@ void RendererSceneCull::render_camera(const Ref &p_render_bu camera->zfar, camera->vaspect); } break; + case Camera::CUSTOM: { + projection = camera->c_proj; + } break; } camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter, taa_frame_count, camera->visible_layers); diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 972f66d325f..7b2eca1aa8f 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -78,7 +78,8 @@ class RendererSceneCull : public RenderingMethod { enum Type { PERSPECTIVE, ORTHOGONAL, - FRUSTUM + FRUSTUM, + CUSTOM, }; Type type; float fov; @@ -91,6 +92,7 @@ class RendererSceneCull : public RenderingMethod { RID attributes; RID compositor; + Projection c_proj; Transform3D transform; Camera() { @@ -113,6 +115,7 @@ class RendererSceneCull : public RenderingMethod { virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far); virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far); + virtual void camera_set_custom(RID p_camera, Projection p_proj); virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform); virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers); virtual void camera_set_environment(RID p_camera, RID p_env); diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h index f6212faf085..137098f273c 100644 --- a/servers/rendering/rendering_method.h +++ b/servers/rendering/rendering_method.h @@ -50,6 +50,7 @@ class RenderingMethod { virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0; virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0; virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0; + virtual void camera_set_custom(RID p_camera, Projection p_proj) = 0; virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform) = 0; virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0; virtual void camera_set_environment(RID p_camera, RID p_env) = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 2dcdc3f2543..c07cd3ce12a 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -605,6 +605,7 @@ class RenderingServerDefault : public RenderingServer { FUNC4(camera_set_perspective, RID, float, float, float) FUNC4(camera_set_orthogonal, RID, float, float, float) FUNC5(camera_set_frustum, RID, float, Vector2, float, float) + FUNC2(camera_set_custom, RID, Projection) FUNC2(camera_set_transform, RID, const Transform3D &) FUNC2(camera_set_cull_mask, RID, uint32_t) FUNC2(camera_set_environment, RID, RID) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 5c850802981..575cf507297 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2771,6 +2771,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("camera_set_perspective", "camera", "fovy_degrees", "z_near", "z_far"), &RenderingServer::camera_set_perspective); ClassDB::bind_method(D_METHOD("camera_set_orthogonal", "camera", "size", "z_near", "z_far"), &RenderingServer::camera_set_orthogonal); ClassDB::bind_method(D_METHOD("camera_set_frustum", "camera", "size", "offset", "z_near", "z_far"), &RenderingServer::camera_set_frustum); + ClassDB::bind_method(D_METHOD("camera_set_custom", "camera", "p_proj"), &RenderingServer::camera_set_custom); ClassDB::bind_method(D_METHOD("camera_set_transform", "camera", "transform"), &RenderingServer::camera_set_transform); ClassDB::bind_method(D_METHOD("camera_set_cull_mask", "camera", "layers"), &RenderingServer::camera_set_cull_mask); ClassDB::bind_method(D_METHOD("camera_set_environment", "camera", "env"), &RenderingServer::camera_set_environment); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 878b02eaf13..1bbf5613817 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -855,6 +855,7 @@ class RenderingServer : public Object { virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0; virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0; virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0; + virtual void camera_set_custom(RID p_camera, Projection p_proj) = 0; virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform) = 0; virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0; virtual void camera_set_environment(RID p_camera, RID p_env) = 0; From 61a2fedecf24ef21af52e1cc940862910589da25 Mon Sep 17 00:00:00 2001 From: Mohammedi Mohammed Djawad <137767403+DxUr@users.noreply.github.com> Date: Sat, 4 Nov 2023 19:21:56 +0100 Subject: [PATCH 02/17] Update scene/3d/camera_3d.cpp Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> --- scene/3d/camera_3d.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 6089fb1aa2c..0283f6905e4 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -90,7 +90,6 @@ void Camera3D::_validate_property(PropertyInfo &p_property) const { } } - if (attributes.is_valid()) { const CameraAttributesPhysical *physical_attributes = Object::cast_to(attributes.ptr()); if (physical_attributes) { From 2f754c4e10dcd65ec8e889d4d970de62d3172c17 Mon Sep 17 00:00:00 2001 From: Mohammedi Mohammed Djawad <137767403+DxUr@users.noreply.github.com> Date: Sat, 4 Nov 2023 19:22:02 +0100 Subject: [PATCH 03/17] Update scene/3d/camera_3d.cpp Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> --- scene/3d/camera_3d.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 0283f6905e4..d5c31baaf71 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -390,6 +390,7 @@ void Camera3D::set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, rea void Camera3D::set_projection(ProjectionType p_mode) { if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) c_proj = get_camera_projection(); + } if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM || p_mode == PROJECTION_CUSTOM) { mode = p_mode; _update_camera_mode(); From ec907ecab5142c3cd788421460f388d30a309c2d Mon Sep 17 00:00:00 2001 From: Mohammedi Mohammed Djawad <137767403+DxUr@users.noreply.github.com> Date: Sat, 4 Nov 2023 19:22:07 +0100 Subject: [PATCH 04/17] Update editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> --- editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp index f9eb8a95fd6..ea84bb498b3 100644 --- a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp @@ -267,7 +267,7 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { case Camera3D::PROJECTION_CUSTOM: { // Show Nothing - } + } break; } #undef ADD_TRIANGLE From d321ef21ff08fda31783bbd9c21bc0a7c97275f1 Mon Sep 17 00:00:00 2001 From: DxUr Date: Sat, 4 Nov 2023 19:30:14 +0100 Subject: [PATCH 05/17] Update camera_3d.cpp --- scene/3d/camera_3d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index d5c31baaf71..f45ac0ef3d5 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -388,7 +388,7 @@ void Camera3D::set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, rea } void Camera3D::set_projection(ProjectionType p_mode) { - if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) + if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) { c_proj = get_camera_projection(); } if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM || p_mode == PROJECTION_CUSTOM) { From ddbd139450478d87c838e99d0b9a4ccec8ed866d Mon Sep 17 00:00:00 2001 From: DxUr Date: Sat, 4 Nov 2023 19:33:16 +0100 Subject: [PATCH 06/17] Update camera_3d.cpp --- scene/3d/camera_3d.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index f45ac0ef3d5..0283f6905e4 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -388,9 +388,8 @@ void Camera3D::set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, rea } void Camera3D::set_projection(ProjectionType p_mode) { - if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) { + if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) c_proj = get_camera_projection(); - } if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM || p_mode == PROJECTION_CUSTOM) { mode = p_mode; _update_camera_mode(); From a0cd1f29e0a105126a7ba389e01dc55d280042fd Mon Sep 17 00:00:00 2001 From: DxUr Date: Sat, 4 Nov 2023 19:35:04 +0100 Subject: [PATCH 07/17] Update camera_3d.cpp --- scene/3d/camera_3d.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 0283f6905e4..7788e1565e7 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -388,8 +388,10 @@ void Camera3D::set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, rea } void Camera3D::set_projection(ProjectionType p_mode) { - if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) + if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) { c_proj = get_camera_projection(); + } + if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM || p_mode == PROJECTION_CUSTOM) { mode = p_mode; _update_camera_mode(); From 26c421597bcd2042f93bef3ff072b92032b20b49 Mon Sep 17 00:00:00 2001 From: DxUr Date: Sat, 4 Nov 2023 21:08:27 +0100 Subject: [PATCH 08/17] Update camera_3d.cpp --- scene/3d/camera_3d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 7788e1565e7..a116ca58346 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -391,7 +391,7 @@ void Camera3D::set_projection(ProjectionType p_mode) { if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) { c_proj = get_camera_projection(); } - + if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM || p_mode == PROJECTION_CUSTOM) { mode = p_mode; _update_camera_mode(); From fc2acc1712bb0149f622a68d73e4cc65ff01e775 Mon Sep 17 00:00:00 2001 From: DxUr Date: Sat, 4 Nov 2023 22:11:56 +0100 Subject: [PATCH 09/17] Update Camera3D.xml --- doc/classes/Camera3D.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml index f10fa88c2f0..8b1830e5584 100644 --- a/doc/classes/Camera3D.xml +++ b/doc/classes/Camera3D.xml @@ -172,7 +172,7 @@ If [code]true[/code], the ancestor [Viewport] is currently using this camera. If multiple cameras are in the scene, one will always be made current. For example, if two [Camera3D] nodes are present in the scene and only one is current, setting one camera's [member current] to [code]false[/code] will cause the other camera to be made current. - + The camera's [Projection]. This can be changed from the default to apply custom projection matrix. [b]Note:[/b] Only effective if [member projection] is [constant PROJECTION_CUSTOM]. From 80f92c2e9beaba890e4ec530b808ff555d846e7a Mon Sep 17 00:00:00 2001 From: DxUr Date: Sat, 4 Nov 2023 22:30:58 +0100 Subject: [PATCH 10/17] Update RenderingServer.xml --- doc/classes/RenderingServer.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 91af70b565f..8574332902e 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -134,6 +134,14 @@ Sets the cull mask associated with this camera. The cull mask describes which 3D layers are rendered by this camera. Equivalent to [member Camera3D.cull_mask]. + + + + + + Sets camera to use custom projection. + + From 0f55ec2657bb2d54470b851d6c4d88feee8fe8e7 Mon Sep 17 00:00:00 2001 From: Xavier Loh Date: Fri, 8 Mar 2024 21:17:19 +0800 Subject: [PATCH 11/17] Extract switch-case case PROJECTION_CUSTOM _update_camera_mode to its own function for standardization --- scene/3d/camera_3d.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index a116ca58346..996d68fa9e1 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -47,7 +47,6 @@ void Camera3D::_update_camera_mode() { switch (mode) { case PROJECTION_PERSPECTIVE: { set_perspective(fov, _near, _far); - } break; case PROJECTION_ORTHOGONAL: { set_orthogonal(size, _near, _far); @@ -56,9 +55,7 @@ void Camera3D::_update_camera_mode() { set_frustum(size, frustum_offset, _near, _far); } break; case PROJECTION_CUSTOM: { - RenderingServer::get_singleton()->camera_set_custom(camera, c_proj); - update_gizmos(); - force_change = false; + set_custom(c_proj); } break; } } @@ -387,6 +384,19 @@ void Camera3D::set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, rea update_gizmos(); } +void Camera3D::set_custom(Projection p_proj) { + if (!force_change && c_proj == p_proj) { + return; + } + + c_proj = p_proj; + mode = PROJECTION_CUSTOM; + force_change = false; + + RenderingServer::get_singleton()->camera_set_custom(camera, c_proj); + update_gizmos(); +} + void Camera3D::set_projection(ProjectionType p_mode) { if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) { c_proj = get_camera_projection(); From 63e41569fbf731113ec23f9a16172660b8c001ef Mon Sep 17 00:00:00 2001 From: Xavier Loh Date: Fri, 8 Mar 2024 21:17:54 +0800 Subject: [PATCH 12/17] Fix Camera3D custom projection which are orthogonal not setting is_orthogonal --- servers/rendering/renderer_scene_cull.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index c0b3dc99eb5..518e955285f 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -2764,6 +2764,7 @@ void RendererSceneCull::render_camera(const Ref &p_render_bu } break; case Camera::CUSTOM: { projection = camera->c_proj; + is_orthogonal = projection.is_orthogonal(); } break; } From e0ed75db198779143e2867db7b83cc9838e97f96 Mon Sep 17 00:00:00 2001 From: Xavier Loh Date: Fri, 8 Mar 2024 22:02:06 +0800 Subject: [PATCH 13/17] Add missing function declaration in camera_3d.h --- scene/3d/camera_3d.h | 1 + 1 file changed, 1 insertion(+) diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h index 8574cb5eecb..dcd16377c9a 100644 --- a/scene/3d/camera_3d.h +++ b/scene/3d/camera_3d.h @@ -153,6 +153,7 @@ class Camera3D : public Node3D { void set_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far); void set_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far); void set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, real_t p_z_far); + void set_custom(Projection p_proj); void set_projection(Camera3D::ProjectionType p_mode); void set_custom_projection(Projection p_proj); From f13ff293973c0a8d055ac157eb99cc3e1dd385f0 Mon Sep 17 00:00:00 2001 From: Xavier Loh Date: Fri, 8 Mar 2024 22:10:51 +0800 Subject: [PATCH 14/17] Fix camera is not inside the scene tree error when initializing camera_3d with custom projection --- scene/3d/camera_3d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 996d68fa9e1..024100b4e50 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -398,7 +398,7 @@ void Camera3D::set_custom(Projection p_proj) { } void Camera3D::set_projection(ProjectionType p_mode) { - if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM) { + if (p_mode == PROJECTION_CUSTOM && mode != PROJECTION_CUSTOM && is_inside_tree()) { c_proj = get_camera_projection(); } From bf860044a62d5a3ea6789b61414c848e54a71f89 Mon Sep 17 00:00:00 2001 From: Xavier Loh Date: Fri, 8 Mar 2024 23:35:25 +0800 Subject: [PATCH 15/17] Fix SDFGI/Directional Lights spamming errors when unable to get endpoints. --- scene/3d/camera_3d.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 024100b4e50..97fbf1e1fe5 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -393,6 +393,26 @@ void Camera3D::set_custom(Projection p_proj) { mode = PROJECTION_CUSTOM; force_change = false; + Vector planes = c_proj.get_projection_planes(Transform3D()); + const Projection::Planes intersections[8][3] = { + { Projection::PLANE_FAR, Projection::PLANE_LEFT, Projection::PLANE_TOP }, + { Projection::PLANE_FAR, Projection::PLANE_LEFT, Projection::PLANE_BOTTOM }, + { Projection::PLANE_FAR, Projection::PLANE_RIGHT, Projection::PLANE_TOP }, + { Projection::PLANE_FAR, Projection::PLANE_RIGHT, Projection::PLANE_BOTTOM }, + { Projection::PLANE_NEAR, Projection::PLANE_LEFT, Projection::PLANE_TOP }, + { Projection::PLANE_NEAR, Projection::PLANE_LEFT, Projection::PLANE_BOTTOM }, + { Projection::PLANE_NEAR, Projection::PLANE_RIGHT, Projection::PLANE_TOP }, + { Projection::PLANE_NEAR, Projection::PLANE_RIGHT, Projection::PLANE_BOTTOM }, + }; + + for (int i = 0; i < 8; i++) { + Vector3 point; + Plane a = planes[intersections[i][0]]; + Plane b = planes[intersections[i][1]]; + Plane c = planes[intersections[i][2]]; + ERR_FAIL_COND_MSG(!a.intersect_3(b, c), "Camera3D custom projection has non-intersecting planes; skipping update."); + } + RenderingServer::get_singleton()->camera_set_custom(camera, c_proj); update_gizmos(); } From 5d7fed56d66b24f58ba52fc5f11ba37d7a5eadde Mon Sep 17 00:00:00 2001 From: Xavier Loh Date: Sat, 23 Mar 2024 07:53:40 +0800 Subject: [PATCH 16/17] Add Camera3d custom projection gizmo. --- .../plugins/gizmos/camera_3d_gizmo_plugin.cpp | 18 +++++++++++++++++- scene/3d/camera_3d.cpp | 1 - 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp index ea84bb498b3..8d78dfa263a 100644 --- a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp @@ -266,7 +266,23 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } break; case Camera3D::PROJECTION_CUSTOM: { - // Show Nothing + // An inaccurate, but sufficient representation of the custom projection + Vector3 endpoints[8]; + Projection proj = camera->get_custom_projection(); + proj.get_endpoints( + Transform3D(Basis(Vector3(size_factor.x, 0, 0), Vector3(0, size_factor.y, 0), Vector3(0, 0, 1)) / proj.get_z_far()), + endpoints); + + ADD_QUAD(endpoints[0], endpoints[1], endpoints[5], endpoints[4]); + ADD_QUAD(endpoints[2], endpoints[3], endpoints[7], endpoints[6]); + ADD_QUAD(endpoints[0], endpoints[2], endpoints[6], endpoints[4]); + ADD_QUAD(endpoints[1], endpoints[3], endpoints[7], endpoints[5]); + + Vector3 top_left_to_top_right = endpoints[2] - endpoints[0]; + Vector3 up = Vector3(0, 0, 0.2).cross(top_left_to_top_right); + ADD_TRIANGLE(endpoints[0] + top_left_to_top_right * 0.4, + endpoints[0] + top_left_to_top_right * 0.6, + endpoints[0] + top_left_to_top_right * 0.5 + up); } break; } diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 97fbf1e1fe5..203c25345b5 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -406,7 +406,6 @@ void Camera3D::set_custom(Projection p_proj) { }; for (int i = 0; i < 8; i++) { - Vector3 point; Plane a = planes[intersections[i][0]]; Plane b = planes[intersections[i][1]]; Plane c = planes[intersections[i][2]]; From 191720fa3d69a9d59865f2d41cce76c7a24a97ce Mon Sep 17 00:00:00 2001 From: DxUr Date: Sat, 23 Mar 2024 11:12:09 +0100 Subject: [PATCH 17/17] A better gizmo --- .../plugins/gizmos/camera_3d_gizmo_plugin.cpp | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp index 8d78dfa263a..718b1462820 100644 --- a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp @@ -266,23 +266,33 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } break; case Camera3D::PROJECTION_CUSTOM: { - // An inaccurate, but sufficient representation of the custom projection - Vector3 endpoints[8]; - Projection proj = camera->get_custom_projection(); - proj.get_endpoints( - Transform3D(Basis(Vector3(size_factor.x, 0, 0), Vector3(0, size_factor.y, 0), Vector3(0, 0, 1)) / proj.get_z_far()), - endpoints); - - ADD_QUAD(endpoints[0], endpoints[1], endpoints[5], endpoints[4]); - ADD_QUAD(endpoints[2], endpoints[3], endpoints[7], endpoints[6]); - ADD_QUAD(endpoints[0], endpoints[2], endpoints[6], endpoints[4]); - ADD_QUAD(endpoints[1], endpoints[3], endpoints[7], endpoints[5]); - - Vector3 top_left_to_top_right = endpoints[2] - endpoints[0]; + Vector3 points[8] = { + Vector3(0.5f, 0.5f, 0.0f), + Vector3(0.5f, -0.5f, 0.0f), + Vector3(-0.5f, 0.5f, 0.0f), + Vector3(-0.5f, -0.5f, 0.0f), + Vector3(0.5f, 0.5f, -1.0f), + Vector3(0.5f, -0.5f, -1.0f), + Vector3(-0.5f, 0.5f, -1.0f), + Vector3(-0.5f, -0.5f, -1.0f) + }; + + Projection proj = camera->get_camera_projection(); + + for (int i = 0; i < 8; i++) { + points[i] = proj.xform(points[i]); + } + + ADD_QUAD(points[0], points[1], points[5], points[4]); + ADD_QUAD(points[2], points[3], points[7], points[6]); + ADD_QUAD(points[0], points[2], points[6], points[4]); + ADD_QUAD(points[1], points[3], points[7], points[5]); + + Vector3 top_left_to_top_right = points[0] - points[2]; Vector3 up = Vector3(0, 0, 0.2).cross(top_left_to_top_right); - ADD_TRIANGLE(endpoints[0] + top_left_to_top_right * 0.4, - endpoints[0] + top_left_to_top_right * 0.6, - endpoints[0] + top_left_to_top_right * 0.5 + up); + ADD_TRIANGLE(points[2] + top_left_to_top_right * 0.4, + points[2] + top_left_to_top_right * 0.6, + points[2] + top_left_to_top_right * 0.5 + up); } break; }