Skip to content

Commit 0eb3f7a

Browse files
authored
Merge pull request #529 from Lemiczek/projection_addition_aabb_fovy
Implementation of additional `Projection` methods
2 parents 9920e2b + 1b45761 commit 0eb3f7a

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

godot-core/src/builtin/projection.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::builtin::{real, Plane, RMat4, RealConv, Transform3D, Vector2, Vector4
1515
use std::ops::Mul;
1616

1717
use super::meta::impl_godot_as_self;
18+
use super::{Aabb, Rect2, Vector3};
1819

1920
/// A 4x4 matrix used for 3D projective transformations. It can represent
2021
/// transformations such as translation, rotation, scaling, shearing, and
@@ -85,6 +86,24 @@ impl Projection {
8586
)
8687
}
8788

89+
/// Creates a new Projection that scales a given projection to fit around
90+
/// a given AABB in projection space.
91+
///
92+
/// _Godot equivalent: Projection.create_fit_aabb()_
93+
pub fn create_fit_aabb(aabb: Aabb) -> Self {
94+
let translate_unscaled = -2.0 * aabb.position - aabb.size; // -(start+end)
95+
96+
let scale = Vector3::splat(2.0) / aabb.size;
97+
let translate = translate_unscaled / aabb.size;
98+
99+
Self::from_cols(
100+
Vector4::new(scale.x, 0.0, 0.0, 0.0),
101+
Vector4::new(0.0, scale.y, 0.0, 0.0),
102+
Vector4::new(0.0, 0.0, scale.z, 0.0),
103+
Vector4::new(translate.x, translate.y, translate.z, 1.0),
104+
)
105+
}
106+
88107
/// Creates a new Projection for projecting positions onto a head-mounted
89108
/// display with the given X:Y aspect ratio, distance between eyes, display
90109
/// width, distance to lens, oversampling factor, and depth clipping planes.
@@ -183,6 +202,18 @@ impl Projection {
183202
)
184203
}
185204

205+
/// Creates a new Projection that projects positions into the given Rect2.
206+
///
207+
/// _Godot equivalent: Projection.create_light_atlas_rect()_
208+
pub fn create_light_atlas_rect(rect: Rect2) -> Self {
209+
Self::from_cols(
210+
Vector4::new(rect.size.x, 0.0, 0.0, 0.0),
211+
Vector4::new(0.0, rect.size.y, 0.0, 0.0),
212+
Vector4::new(0.0, 0.0, 1.0, 0.0),
213+
Vector4::new(rect.position.x, rect.position.y, 0.0, 1.0),
214+
)
215+
}
216+
186217
/// Creates a new Projection that projects positions using an orthogonal
187218
/// projection with the given clipping planes.
188219
///
@@ -337,8 +368,13 @@ impl Projection {
337368
/// has the given horizontal field of view (in degrees) and aspect ratio.
338369
///
339370
/// _Godot equivalent: Projection.get_fovy()_
340-
pub fn fovy_of(fov_x: real, aspect: real) -> real {
341-
real::from_f64(InnerProjection::get_fovy(fov_x.as_f64(), aspect.as_f64()))
371+
#[doc(alias = "get_fovy")]
372+
pub fn create_fovy(fov_x: real, aspect: real) -> real {
373+
let half_angle_fov_x = f64::to_radians(fov_x.as_f64() * 0.5);
374+
let vertical_transform = f64::atan(aspect.as_f64() * f64::tan(half_angle_fov_x));
375+
let full_angle_fov_y = f64::to_degrees(vertical_transform * 2.0);
376+
377+
real::from_f64(full_angle_fov_y)
342378
}
343379

344380
/// Returns the factor by which the visible level of detail is scaled by

itest/rust/src/builtin_tests/geometry/projection_test.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::framework::itest;
1111

1212
use godot::builtin::inner::InnerProjection;
1313
use godot::builtin::math::assert_eq_approx;
14-
use godot::builtin::{real, Projection, RealConv, Vector2};
14+
use godot::builtin::{real, Aabb, Projection, RealConv, Rect2, Vector2, Vector3};
1515

1616
#[itest]
1717
fn test_create_orthogonal() {
@@ -43,6 +43,37 @@ fn test_create_orthogonal() {
4343
}
4444
}
4545

46+
#[itest]
47+
fn test_create_fit_aabb() {
48+
let aabb = Aabb::new(Vector3::new(1., 1., 1.), Vector3::new(3., 3., 3.));
49+
50+
assert_eq_approx!(
51+
Projection::create_fit_aabb(aabb),
52+
InnerProjection::create_fit_aabb(aabb)
53+
)
54+
}
55+
56+
#[itest]
57+
fn test_fovy() {
58+
let fov_x: real = 80.0;
59+
let aspect: real = 2.0;
60+
61+
assert_eq_approx!(
62+
Projection::create_fovy(fov_x, aspect).as_f64(),
63+
InnerProjection::get_fovy(fov_x.as_f64(), aspect.as_f64()),
64+
);
65+
}
66+
67+
#[itest]
68+
fn test_create_light_atlas_rect() {
69+
let rect: Rect2 = Rect2::new(Vector2::new(10.0, 10.0), Vector2::new(15.0, 15.0));
70+
71+
assert_eq_approx!(
72+
Projection::create_light_atlas_rect(rect),
73+
InnerProjection::create_light_atlas_rect(rect),
74+
);
75+
}
76+
4677
#[itest]
4778
fn test_create_orthogonal_aspect() {
4879
const TEST_DATA: [(real, real, real, real, bool); 6] = [

0 commit comments

Comments
 (0)