2014-02-10 09:10:30 +08:00
|
|
|
/*************************************************************************/
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
/* projection.cpp */
|
2014-02-10 09:10:30 +08:00
|
|
|
/*************************************************************************/
|
|
|
|
/* This file is part of: */
|
|
|
|
/* GODOT ENGINE */
|
2017-08-27 20:16:55 +08:00
|
|
|
/* https://godotengine.org */
|
2014-02-10 09:10:30 +08:00
|
|
|
/*************************************************************************/
|
2022-01-04 04:27:34 +08:00
|
|
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
|
|
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
2014-02-10 09:10:30 +08:00
|
|
|
/* */
|
|
|
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
|
|
/* a copy of this software and associated documentation files (the */
|
|
|
|
/* "Software"), to deal in the Software without restriction, including */
|
|
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
|
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
|
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
|
|
/* the following conditions: */
|
|
|
|
/* */
|
|
|
|
/* The above copyright notice and this permission notice shall be */
|
|
|
|
/* included in all copies or substantial portions of the Software. */
|
|
|
|
/* */
|
|
|
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
|
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
|
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
|
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
|
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
|
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
|
|
/*************************************************************************/
|
2018-01-05 07:50:27 +08:00
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
#include "projection.h"
|
2018-09-12 00:13:45 +08:00
|
|
|
|
2022-02-04 20:28:02 +08:00
|
|
|
#include "core/math/aabb.h"
|
2018-09-12 00:13:45 +08:00
|
|
|
#include "core/math/math_funcs.h"
|
2022-02-04 20:28:02 +08:00
|
|
|
#include "core/math/plane.h"
|
|
|
|
#include "core/math/rect2.h"
|
|
|
|
#include "core/math/transform_3d.h"
|
2020-11-08 06:33:38 +08:00
|
|
|
#include "core/string/print_string.h"
|
2014-02-10 09:10:30 +08:00
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
float Projection::determinant() const {
|
2020-05-01 20:34:23 +08:00
|
|
|
return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0] - matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0] -
|
2021-10-28 21:19:35 +08:00
|
|
|
matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0] + matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0] +
|
|
|
|
matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0] - matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0] -
|
|
|
|
matrix[0][3] * matrix[1][2] * matrix[2][0] * matrix[3][1] + matrix[0][2] * matrix[1][3] * matrix[2][0] * matrix[3][1] +
|
|
|
|
matrix[0][3] * matrix[1][0] * matrix[2][2] * matrix[3][1] - matrix[0][0] * matrix[1][3] * matrix[2][2] * matrix[3][1] -
|
|
|
|
matrix[0][2] * matrix[1][0] * matrix[2][3] * matrix[3][1] + matrix[0][0] * matrix[1][2] * matrix[2][3] * matrix[3][1] +
|
|
|
|
matrix[0][3] * matrix[1][1] * matrix[2][0] * matrix[3][2] - matrix[0][1] * matrix[1][3] * matrix[2][0] * matrix[3][2] -
|
|
|
|
matrix[0][3] * matrix[1][0] * matrix[2][1] * matrix[3][2] + matrix[0][0] * matrix[1][3] * matrix[2][1] * matrix[3][2] +
|
|
|
|
matrix[0][1] * matrix[1][0] * matrix[2][3] * matrix[3][2] - matrix[0][0] * matrix[1][1] * matrix[2][3] * matrix[3][2] -
|
|
|
|
matrix[0][2] * matrix[1][1] * matrix[2][0] * matrix[3][3] + matrix[0][1] * matrix[1][2] * matrix[2][0] * matrix[3][3] +
|
|
|
|
matrix[0][2] * matrix[1][0] * matrix[2][1] * matrix[3][3] - matrix[0][0] * matrix[1][2] * matrix[2][1] * matrix[3][3] -
|
|
|
|
matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3] + matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3];
|
2020-05-01 20:34:23 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_identity() {
|
2014-02-10 09:10:30 +08:00
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
|
|
matrix[i][j] = (i == j) ? 1 : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_zero() {
|
2014-02-10 09:10:30 +08:00
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
|
|
matrix[i][j] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Plane Projection::xform4(const Plane &p_vec4) const {
|
2014-02-10 09:10:30 +08:00
|
|
|
Plane ret;
|
|
|
|
|
2020-05-10 22:47:11 +08:00
|
|
|
ret.normal.x = matrix[0][0] * p_vec4.normal.x + matrix[1][0] * p_vec4.normal.y + matrix[2][0] * p_vec4.normal.z + matrix[3][0] * p_vec4.d;
|
|
|
|
ret.normal.y = matrix[0][1] * p_vec4.normal.x + matrix[1][1] * p_vec4.normal.y + matrix[2][1] * p_vec4.normal.z + matrix[3][1] * p_vec4.d;
|
|
|
|
ret.normal.z = matrix[0][2] * p_vec4.normal.x + matrix[1][2] * p_vec4.normal.y + matrix[2][2] * p_vec4.normal.z + matrix[3][2] * p_vec4.d;
|
|
|
|
ret.d = matrix[0][3] * p_vec4.normal.x + matrix[1][3] * p_vec4.normal.y + matrix[2][3] * p_vec4.normal.z + matrix[3][3] * p_vec4.d;
|
2014-02-10 09:10:30 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Vector4 Projection::xform(const Vector4 &p_vec4) const {
|
|
|
|
return Vector4(
|
|
|
|
matrix[0][0] * p_vec4.x + matrix[1][0] * p_vec4.y + matrix[2][0] * p_vec4.z + matrix[3][0] * p_vec4.w,
|
|
|
|
matrix[0][1] * p_vec4.x + matrix[1][1] * p_vec4.y + matrix[2][1] * p_vec4.z + matrix[3][1] * p_vec4.w,
|
|
|
|
matrix[0][2] * p_vec4.x + matrix[1][2] * p_vec4.y + matrix[2][2] * p_vec4.z + matrix[3][2] * p_vec4.w,
|
|
|
|
matrix[0][3] * p_vec4.x + matrix[1][3] * p_vec4.y + matrix[2][3] * p_vec4.z + matrix[3][3] * p_vec4.w);
|
|
|
|
}
|
|
|
|
Vector4 Projection::xform_inv(const Vector4 &p_vec4) const {
|
|
|
|
return Vector4(
|
|
|
|
matrix[0][0] * p_vec4.x + matrix[0][1] * p_vec4.y + matrix[0][2] * p_vec4.z + matrix[0][3] * p_vec4.w,
|
|
|
|
matrix[1][0] * p_vec4.x + matrix[1][1] * p_vec4.y + matrix[1][2] * p_vec4.z + matrix[1][3] * p_vec4.w,
|
|
|
|
matrix[2][0] * p_vec4.x + matrix[2][1] * p_vec4.y + matrix[2][2] * p_vec4.z + matrix[2][3] * p_vec4.w,
|
|
|
|
matrix[3][0] * p_vec4.x + matrix[3][1] * p_vec4.y + matrix[3][2] * p_vec4.z + matrix[3][3] * p_vec4.w);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Projection::adjust_perspective_znear(real_t p_new_znear) {
|
2021-01-18 00:25:38 +08:00
|
|
|
real_t zfar = get_z_far();
|
|
|
|
real_t znear = p_new_znear;
|
|
|
|
|
|
|
|
real_t deltaZ = zfar - znear;
|
|
|
|
matrix[2][2] = -(zfar + znear) / deltaZ;
|
|
|
|
matrix[3][2] = -2 * znear * zfar / deltaZ;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Projection Projection::create_depth_correction(bool p_flip_y) {
|
|
|
|
Projection proj;
|
|
|
|
proj.set_depth_correction(p_flip_y);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::create_light_atlas_rect(const Rect2 &p_rect) {
|
|
|
|
Projection proj;
|
|
|
|
proj.set_light_atlas_rect(p_rect);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::create_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
|
|
|
|
Projection proj;
|
|
|
|
proj.set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::create_perspective_hmd(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
|
|
|
|
Projection proj;
|
|
|
|
proj.set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov, p_eye, p_intraocular_dist, p_convergence_dist);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::create_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
|
|
|
|
Projection proj;
|
|
|
|
proj.set_for_hmd(p_eye, p_aspect, p_intraocular_dist, p_display_width, p_display_to_lens, p_oversample, p_z_near, p_z_far);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
|
|
|
|
Projection proj;
|
|
|
|
proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_zfar, p_zfar);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::create_orthogonal_aspect(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
|
|
|
|
Projection proj;
|
|
|
|
proj.set_orthogonal(p_size, p_aspect, p_znear, p_zfar, p_flip_fov);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::create_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
|
|
|
|
Projection proj;
|
|
|
|
proj.set_frustum(p_left, p_right, p_bottom, p_top, p_near, p_far);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::create_frustum_aspect(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
|
|
|
|
Projection proj;
|
|
|
|
proj.set_frustum(p_size, p_aspect, p_offset, p_near, p_far, p_flip_fov);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::create_fit_aabb(const AABB &p_aabb) {
|
|
|
|
Projection proj;
|
|
|
|
proj.scale_translate_to_fit(p_aabb);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::perspective_znear_adjusted(real_t p_new_znear) const {
|
|
|
|
Projection proj = *this;
|
|
|
|
proj.adjust_perspective_znear(p_new_znear);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Plane Projection::get_projection_plane(Planes p_plane) const {
|
|
|
|
const real_t *matrix = (const real_t *)this->matrix;
|
|
|
|
|
|
|
|
switch (p_plane) {
|
|
|
|
case PLANE_NEAR: {
|
|
|
|
Plane new_plane = Plane(matrix[3] + matrix[2],
|
|
|
|
matrix[7] + matrix[6],
|
|
|
|
matrix[11] + matrix[10],
|
|
|
|
matrix[15] + matrix[14]);
|
|
|
|
|
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
return new_plane;
|
|
|
|
} break;
|
|
|
|
case PLANE_FAR: {
|
|
|
|
Plane new_plane = Plane(matrix[3] - matrix[2],
|
|
|
|
matrix[7] - matrix[6],
|
|
|
|
matrix[11] - matrix[10],
|
|
|
|
matrix[15] - matrix[14]);
|
|
|
|
|
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
return new_plane;
|
|
|
|
} break;
|
|
|
|
case PLANE_LEFT: {
|
|
|
|
Plane new_plane = Plane(matrix[3] + matrix[0],
|
|
|
|
matrix[7] + matrix[4],
|
|
|
|
matrix[11] + matrix[8],
|
|
|
|
matrix[15] + matrix[12]);
|
|
|
|
|
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
return new_plane;
|
|
|
|
} break;
|
|
|
|
case PLANE_TOP: {
|
|
|
|
Plane new_plane = Plane(matrix[3] - matrix[1],
|
|
|
|
matrix[7] - matrix[5],
|
|
|
|
matrix[11] - matrix[9],
|
|
|
|
matrix[15] - matrix[13]);
|
|
|
|
|
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
return new_plane;
|
|
|
|
} break;
|
|
|
|
case PLANE_RIGHT: {
|
|
|
|
Plane new_plane = Plane(matrix[3] - matrix[0],
|
|
|
|
matrix[7] - matrix[4],
|
|
|
|
matrix[11] - matrix[8],
|
|
|
|
matrix[15] - matrix[12]);
|
|
|
|
|
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
return new_plane;
|
|
|
|
} break;
|
|
|
|
case PLANE_BOTTOM: {
|
|
|
|
Plane new_plane = Plane(matrix[3] + matrix[1],
|
|
|
|
matrix[7] + matrix[5],
|
|
|
|
matrix[11] + matrix[9],
|
|
|
|
matrix[15] + matrix[13]);
|
|
|
|
|
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
return new_plane;
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Plane();
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection::flipped_y() const {
|
|
|
|
Projection proj = *this;
|
|
|
|
proj.flip_y();
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Projection Projection ::jitter_offseted(const Vector2 &p_offset) const {
|
|
|
|
Projection proj = *this;
|
|
|
|
proj.add_jitter_offset(p_offset);
|
|
|
|
return proj;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
|
2014-09-16 07:06:37 +08:00
|
|
|
if (p_flip_fov) {
|
|
|
|
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
|
|
|
|
}
|
2014-02-10 09:10:30 +08:00
|
|
|
|
2017-01-15 04:35:39 +08:00
|
|
|
real_t sine, cotangent, deltaZ;
|
2022-08-13 23:45:42 +08:00
|
|
|
real_t radians = Math::deg_to_rad(p_fovy_degrees / 2.0);
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
deltaZ = p_z_far - p_z_near;
|
|
|
|
sine = Math::sin(radians);
|
|
|
|
|
|
|
|
if ((deltaZ == 0) || (sine == 0) || (p_aspect == 0)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cotangent = Math::cos(radians) / sine;
|
|
|
|
|
|
|
|
set_identity();
|
|
|
|
|
|
|
|
matrix[0][0] = cotangent / p_aspect;
|
|
|
|
matrix[1][1] = cotangent;
|
|
|
|
matrix[2][2] = -(p_z_far + p_z_near) / deltaZ;
|
|
|
|
matrix[2][3] = -1;
|
|
|
|
matrix[3][2] = -2 * p_z_near * p_z_far / deltaZ;
|
2016-03-09 07:00:52 +08:00
|
|
|
matrix[3][3] = 0;
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
|
2017-04-23 20:10:41 +08:00
|
|
|
if (p_flip_fov) {
|
|
|
|
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
|
|
|
|
}
|
|
|
|
|
|
|
|
real_t left, right, modeltranslation, ymax, xmax, frustumshift;
|
|
|
|
|
2022-08-13 23:45:42 +08:00
|
|
|
ymax = p_z_near * tan(Math::deg_to_rad(p_fovy_degrees / 2.0));
|
2017-04-23 20:10:41 +08:00
|
|
|
xmax = ymax * p_aspect;
|
|
|
|
frustumshift = (p_intraocular_dist / 2.0) * p_z_near / p_convergence_dist;
|
|
|
|
|
|
|
|
switch (p_eye) {
|
|
|
|
case 1: { // left eye
|
|
|
|
left = -xmax + frustumshift;
|
|
|
|
right = xmax + frustumshift;
|
|
|
|
modeltranslation = p_intraocular_dist / 2.0;
|
2020-05-19 21:46:49 +08:00
|
|
|
} break;
|
2017-04-23 20:10:41 +08:00
|
|
|
case 2: { // right eye
|
|
|
|
left = -xmax - frustumshift;
|
|
|
|
right = xmax - frustumshift;
|
|
|
|
modeltranslation = -p_intraocular_dist / 2.0;
|
2020-05-19 21:46:49 +08:00
|
|
|
} break;
|
2017-04-23 20:10:41 +08:00
|
|
|
default: { // mono, should give the same result as set_perspective(p_fovy_degrees,p_aspect,p_z_near,p_z_far,p_flip_fov)
|
|
|
|
left = -xmax;
|
|
|
|
right = xmax;
|
|
|
|
modeltranslation = 0.0;
|
2020-05-19 21:46:49 +08:00
|
|
|
} break;
|
|
|
|
}
|
2017-04-23 20:10:41 +08:00
|
|
|
|
|
|
|
set_frustum(left, right, -ymax, ymax, p_z_near, p_z_far);
|
|
|
|
|
|
|
|
// translate matrix by (modeltranslation, 0.0, 0.0)
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Projection cm;
|
2017-04-23 20:10:41 +08:00
|
|
|
cm.set_identity();
|
|
|
|
cm.matrix[3][0] = modeltranslation;
|
|
|
|
*this = *this * cm;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
|
2017-04-23 20:10:41 +08:00
|
|
|
// we first calculate our base frustum on our values without taking our lens magnification into account.
|
|
|
|
real_t f1 = (p_intraocular_dist * 0.5) / p_display_to_lens;
|
|
|
|
real_t f2 = ((p_display_width - p_intraocular_dist) * 0.5) / p_display_to_lens;
|
|
|
|
real_t f3 = (p_display_width / 4.0) / p_display_to_lens;
|
|
|
|
|
|
|
|
// now we apply our oversample factor to increase our FOV. how much we oversample is always a balance we strike between performance and how much
|
|
|
|
// we're willing to sacrifice in FOV.
|
|
|
|
real_t add = ((f1 + f2) * (p_oversample - 1.0)) / 2.0;
|
|
|
|
f1 += add;
|
|
|
|
f2 += add;
|
2017-12-03 19:32:42 +08:00
|
|
|
f3 *= p_oversample;
|
2017-04-23 20:10:41 +08:00
|
|
|
|
|
|
|
// always apply KEEP_WIDTH aspect ratio
|
2020-04-05 14:56:43 +08:00
|
|
|
f3 /= p_aspect;
|
2017-04-23 20:10:41 +08:00
|
|
|
|
|
|
|
switch (p_eye) {
|
|
|
|
case 1: { // left eye
|
|
|
|
set_frustum(-f2 * p_z_near, f1 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
|
2020-05-19 21:46:49 +08:00
|
|
|
} break;
|
2017-04-23 20:10:41 +08:00
|
|
|
case 2: { // right eye
|
|
|
|
set_frustum(-f1 * p_z_near, f2 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
|
2020-05-19 21:46:49 +08:00
|
|
|
} break;
|
2017-04-23 20:10:41 +08:00
|
|
|
default: { // mono, does not apply here!
|
2020-05-19 21:46:49 +08:00
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
2017-04-23 20:10:41 +08:00
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
|
2014-02-10 09:10:30 +08:00
|
|
|
set_identity();
|
|
|
|
|
|
|
|
matrix[0][0] = 2.0 / (p_right - p_left);
|
|
|
|
matrix[3][0] = -((p_right + p_left) / (p_right - p_left));
|
|
|
|
matrix[1][1] = 2.0 / (p_top - p_bottom);
|
|
|
|
matrix[3][1] = -((p_top + p_bottom) / (p_top - p_bottom));
|
|
|
|
matrix[2][2] = -2.0 / (p_zfar - p_znear);
|
|
|
|
matrix[3][2] = -((p_zfar + p_znear) / (p_zfar - p_znear));
|
|
|
|
matrix[3][3] = 1.0;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
|
2014-09-16 07:06:37 +08:00
|
|
|
if (!p_flip_fov) {
|
2014-02-10 09:10:30 +08:00
|
|
|
p_size *= p_aspect;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_orthogonal(-p_size / 2, +p_size / 2, -p_size / p_aspect / 2, +p_size / p_aspect / 2, p_znear, p_zfar);
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
|
2019-11-20 23:22:16 +08:00
|
|
|
ERR_FAIL_COND(p_right <= p_left);
|
|
|
|
ERR_FAIL_COND(p_top <= p_bottom);
|
|
|
|
ERR_FAIL_COND(p_far <= p_near);
|
|
|
|
|
2017-01-15 04:35:39 +08:00
|
|
|
real_t *te = &matrix[0][0];
|
|
|
|
real_t x = 2 * p_near / (p_right - p_left);
|
|
|
|
real_t y = 2 * p_near / (p_top - p_bottom);
|
2015-03-02 11:54:10 +08:00
|
|
|
|
2017-01-15 04:35:39 +08:00
|
|
|
real_t a = (p_right + p_left) / (p_right - p_left);
|
|
|
|
real_t b = (p_top + p_bottom) / (p_top - p_bottom);
|
|
|
|
real_t c = -(p_far + p_near) / (p_far - p_near);
|
|
|
|
real_t d = -2 * p_far * p_near / (p_far - p_near);
|
2015-03-02 11:54:10 +08:00
|
|
|
|
2017-01-16 05:15:47 +08:00
|
|
|
te[0] = x;
|
|
|
|
te[1] = 0;
|
|
|
|
te[2] = 0;
|
|
|
|
te[3] = 0;
|
|
|
|
te[4] = 0;
|
|
|
|
te[5] = y;
|
|
|
|
te[6] = 0;
|
|
|
|
te[7] = 0;
|
|
|
|
te[8] = a;
|
|
|
|
te[9] = b;
|
|
|
|
te[10] = c;
|
|
|
|
te[11] = -1;
|
|
|
|
te[12] = 0;
|
|
|
|
te[13] = 0;
|
|
|
|
te[14] = d;
|
|
|
|
te[15] = 0;
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
|
2019-02-20 00:17:02 +08:00
|
|
|
if (!p_flip_fov) {
|
|
|
|
p_size *= p_aspect;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_frustum(-p_size / 2 + p_offset.x, +p_size / 2 + p_offset.x, -p_size / p_aspect / 2 + p_offset.y, +p_size / p_aspect / 2 + p_offset.y, p_near, p_far);
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
real_t Projection::get_z_far() const {
|
2017-01-15 04:35:39 +08:00
|
|
|
const real_t *matrix = (const real_t *)this->matrix;
|
2014-02-10 09:10:30 +08:00
|
|
|
Plane new_plane = Plane(matrix[3] - matrix[2],
|
|
|
|
matrix[7] - matrix[6],
|
|
|
|
matrix[11] - matrix[10],
|
|
|
|
matrix[15] - matrix[14]);
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2020-05-10 22:47:11 +08:00
|
|
|
return new_plane.d;
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
2020-05-14 20:29:06 +08:00
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
real_t Projection::get_z_near() const {
|
2017-01-15 04:35:39 +08:00
|
|
|
const real_t *matrix = (const real_t *)this->matrix;
|
2014-02-10 09:10:30 +08:00
|
|
|
Plane new_plane = Plane(matrix[3] + matrix[2],
|
|
|
|
matrix[7] + matrix[6],
|
|
|
|
matrix[11] + matrix[10],
|
|
|
|
-matrix[15] - matrix[14]);
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
new_plane.normalize();
|
2020-05-10 22:47:11 +08:00
|
|
|
return new_plane.d;
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Vector2 Projection::get_viewport_half_extents() const {
|
2017-01-15 04:35:39 +08:00
|
|
|
const real_t *matrix = (const real_t *)this->matrix;
|
2014-02-10 09:10:30 +08:00
|
|
|
///////--- Near Plane ---///////
|
|
|
|
Plane near_plane = Plane(matrix[3] + matrix[2],
|
|
|
|
matrix[7] + matrix[6],
|
|
|
|
matrix[11] + matrix[10],
|
2017-01-16 17:32:44 +08:00
|
|
|
-matrix[15] - matrix[14]);
|
2017-01-16 05:15:47 +08:00
|
|
|
near_plane.normalize();
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
///////--- Right Plane ---///////
|
|
|
|
Plane right_plane = Plane(matrix[3] - matrix[0],
|
|
|
|
matrix[7] - matrix[4],
|
|
|
|
matrix[11] - matrix[8],
|
2017-01-16 17:32:44 +08:00
|
|
|
-matrix[15] + matrix[12]);
|
2017-01-16 05:15:47 +08:00
|
|
|
right_plane.normalize();
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
Plane top_plane = Plane(matrix[3] - matrix[1],
|
|
|
|
matrix[7] - matrix[5],
|
|
|
|
matrix[11] - matrix[9],
|
2017-01-16 17:32:44 +08:00
|
|
|
-matrix[15] + matrix[13]);
|
2017-01-16 05:15:47 +08:00
|
|
|
top_plane.normalize();
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
Vector3 res;
|
|
|
|
near_plane.intersect_3(right_plane, top_plane, &res);
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2020-01-22 02:39:16 +08:00
|
|
|
return Vector2(res.x, res.y);
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Vector2 Projection::get_far_plane_half_extents() const {
|
2020-01-22 01:24:22 +08:00
|
|
|
const real_t *matrix = (const real_t *)this->matrix;
|
|
|
|
///////--- Far Plane ---///////
|
|
|
|
Plane far_plane = Plane(matrix[3] - matrix[2],
|
|
|
|
matrix[7] - matrix[6],
|
|
|
|
matrix[11] - matrix[10],
|
|
|
|
-matrix[15] + matrix[14]);
|
|
|
|
far_plane.normalize();
|
|
|
|
|
|
|
|
///////--- Right Plane ---///////
|
|
|
|
Plane right_plane = Plane(matrix[3] - matrix[0],
|
|
|
|
matrix[7] - matrix[4],
|
|
|
|
matrix[11] - matrix[8],
|
|
|
|
-matrix[15] + matrix[12]);
|
|
|
|
right_plane.normalize();
|
|
|
|
|
|
|
|
Plane top_plane = Plane(matrix[3] - matrix[1],
|
|
|
|
matrix[7] - matrix[5],
|
|
|
|
matrix[11] - matrix[9],
|
|
|
|
-matrix[15] + matrix[13]);
|
|
|
|
top_plane.normalize();
|
|
|
|
|
|
|
|
Vector3 res;
|
|
|
|
far_plane.intersect_3(right_plane, top_plane, &res);
|
|
|
|
|
2020-08-13 09:21:01 +08:00
|
|
|
return Vector2(res.x, res.y);
|
2020-01-22 01:24:22 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
bool Projection::get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const {
|
2020-10-17 13:08:21 +08:00
|
|
|
Vector<Plane> planes = get_projection_planes(Transform3D());
|
2017-09-03 04:32:31 +08:00
|
|
|
const Planes intersections[8][3] = {
|
|
|
|
{ PLANE_FAR, PLANE_LEFT, PLANE_TOP },
|
|
|
|
{ PLANE_FAR, PLANE_LEFT, PLANE_BOTTOM },
|
|
|
|
{ PLANE_FAR, PLANE_RIGHT, PLANE_TOP },
|
|
|
|
{ PLANE_FAR, PLANE_RIGHT, PLANE_BOTTOM },
|
|
|
|
{ PLANE_NEAR, PLANE_LEFT, PLANE_TOP },
|
|
|
|
{ PLANE_NEAR, PLANE_LEFT, PLANE_BOTTOM },
|
|
|
|
{ PLANE_NEAR, PLANE_RIGHT, PLANE_TOP },
|
|
|
|
{ PLANE_NEAR, PLANE_RIGHT, PLANE_BOTTOM },
|
2017-09-08 05:00:47 +08:00
|
|
|
};
|
2017-04-23 20:10:41 +08:00
|
|
|
|
2017-09-03 04:32:31 +08:00
|
|
|
for (int i = 0; i < 8; i++) {
|
2017-09-08 05:00:47 +08:00
|
|
|
Vector3 point;
|
2017-09-03 04:32:31 +08:00
|
|
|
bool res = planes[intersections[i][0]].intersect_3(planes[intersections[i][1]], planes[intersections[i][2]], &point);
|
2017-04-23 20:10:41 +08:00
|
|
|
ERR_FAIL_COND_V(!res, false);
|
2017-09-03 04:32:31 +08:00
|
|
|
p_8points[i] = p_transform.xform(point);
|
2017-04-23 20:10:41 +08:00
|
|
|
}
|
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Vector<Plane> Projection::get_projection_planes(const Transform3D &p_transform) const {
|
2014-02-10 09:10:30 +08:00
|
|
|
/** Fast Plane Extraction from combined modelview/projection matrices.
|
|
|
|
* References:
|
2021-08-22 09:56:25 +08:00
|
|
|
* https://web.archive.org/web/20011221205252/https://www.markmorley.com/opengl/frustumculling.html
|
|
|
|
* https://web.archive.org/web/20061020020112/https://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf
|
2014-02-10 09:10:30 +08:00
|
|
|
*/
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
Vector<Plane> planes;
|
2022-01-13 12:29:59 +08:00
|
|
|
planes.resize(6);
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2017-01-15 04:35:39 +08:00
|
|
|
const real_t *matrix = (const real_t *)this->matrix;
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
Plane new_plane;
|
|
|
|
|
|
|
|
///////--- Near Plane ---///////
|
|
|
|
new_plane = Plane(matrix[3] + matrix[2],
|
|
|
|
matrix[7] + matrix[6],
|
|
|
|
matrix[11] + matrix[10],
|
|
|
|
matrix[15] + matrix[14]);
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
|
2022-01-13 12:29:59 +08:00
|
|
|
planes.write[0] = p_transform.xform(new_plane);
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
///////--- Far Plane ---///////
|
|
|
|
new_plane = Plane(matrix[3] - matrix[2],
|
|
|
|
matrix[7] - matrix[6],
|
|
|
|
matrix[11] - matrix[10],
|
|
|
|
matrix[15] - matrix[14]);
|
|
|
|
|
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
|
2022-01-13 12:29:59 +08:00
|
|
|
planes.write[1] = p_transform.xform(new_plane);
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
///////--- Left Plane ---///////
|
|
|
|
new_plane = Plane(matrix[3] + matrix[0],
|
|
|
|
matrix[7] + matrix[4],
|
|
|
|
matrix[11] + matrix[8],
|
|
|
|
matrix[15] + matrix[12]);
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
|
2022-01-13 12:29:59 +08:00
|
|
|
planes.write[2] = p_transform.xform(new_plane);
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
///////--- Top Plane ---///////
|
|
|
|
new_plane = Plane(matrix[3] - matrix[1],
|
|
|
|
matrix[7] - matrix[5],
|
|
|
|
matrix[11] - matrix[9],
|
|
|
|
matrix[15] - matrix[13]);
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
|
2022-01-13 12:29:59 +08:00
|
|
|
planes.write[3] = p_transform.xform(new_plane);
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
///////--- Right Plane ---///////
|
|
|
|
new_plane = Plane(matrix[3] - matrix[0],
|
|
|
|
matrix[7] - matrix[4],
|
|
|
|
matrix[11] - matrix[8],
|
|
|
|
matrix[15] - matrix[12]);
|
|
|
|
|
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2022-01-13 12:29:59 +08:00
|
|
|
planes.write[4] = p_transform.xform(new_plane);
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
///////--- Bottom Plane ---///////
|
|
|
|
new_plane = Plane(matrix[3] + matrix[1],
|
|
|
|
matrix[7] + matrix[5],
|
|
|
|
matrix[11] + matrix[9],
|
|
|
|
matrix[15] + matrix[13]);
|
|
|
|
|
|
|
|
new_plane.normal = -new_plane.normal;
|
|
|
|
new_plane.normalize();
|
|
|
|
|
2022-01-13 12:29:59 +08:00
|
|
|
planes.write[5] = p_transform.xform(new_plane);
|
2016-03-09 07:00:52 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
return planes;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Projection Projection::inverse() const {
|
|
|
|
Projection cm = *this;
|
2014-02-10 09:10:30 +08:00
|
|
|
cm.invert();
|
|
|
|
return cm;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::invert() {
|
2014-02-10 09:10:30 +08:00
|
|
|
int i, j, k;
|
|
|
|
int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */
|
2017-01-15 04:35:39 +08:00
|
|
|
real_t pvt_val; /* Value of current pivot element */
|
|
|
|
real_t hold; /* Temporary storage */
|
2022-02-25 02:19:16 +08:00
|
|
|
real_t determinant = 1.0f;
|
2014-02-10 09:10:30 +08:00
|
|
|
for (k = 0; k < 4; k++) {
|
|
|
|
/** Locate k'th pivot element **/
|
|
|
|
pvt_val = matrix[k][k]; /** Initialize for search **/
|
|
|
|
pvt_i[k] = k;
|
|
|
|
pvt_j[k] = k;
|
|
|
|
for (i = k; i < 4; i++) {
|
|
|
|
for (j = k; j < 4; j++) {
|
2022-02-25 02:19:16 +08:00
|
|
|
if (Math::abs(matrix[i][j]) > Math::abs(pvt_val)) {
|
2014-02-10 09:10:30 +08:00
|
|
|
pvt_i[k] = i;
|
|
|
|
pvt_j[k] = j;
|
|
|
|
pvt_val = matrix[i][j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Product of pivots, gives determinant when finished **/
|
2022-02-25 02:19:16 +08:00
|
|
|
determinant *= pvt_val;
|
|
|
|
if (Math::is_zero_approx(determinant)) {
|
|
|
|
return; /** Matrix is singular (zero determinant). **/
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** "Interchange" rows (with sign change stuff) **/
|
|
|
|
i = pvt_i[k];
|
|
|
|
if (i != k) { /** If rows are different **/
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
hold = -matrix[k][j];
|
|
|
|
matrix[k][j] = matrix[i][j];
|
|
|
|
matrix[i][j] = hold;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** "Interchange" columns **/
|
|
|
|
j = pvt_j[k];
|
|
|
|
if (j != k) { /** If columns are different **/
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
hold = -matrix[i][k];
|
|
|
|
matrix[i][k] = matrix[i][j];
|
|
|
|
matrix[i][j] = hold;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Divide column by minus pivot value **/
|
|
|
|
for (i = 0; i < 4; i++) {
|
2020-05-14 22:41:43 +08:00
|
|
|
if (i != k) {
|
2014-02-10 09:10:30 +08:00
|
|
|
matrix[i][k] /= (-pvt_val);
|
2020-05-14 22:41:43 +08:00
|
|
|
}
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Reduce the matrix **/
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
hold = matrix[i][k];
|
|
|
|
for (j = 0; j < 4; j++) {
|
2020-05-14 22:41:43 +08:00
|
|
|
if (i != k && j != k) {
|
2014-02-10 09:10:30 +08:00
|
|
|
matrix[i][j] += hold * matrix[k][j];
|
2020-05-14 22:41:43 +08:00
|
|
|
}
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Divide row by pivot **/
|
|
|
|
for (j = 0; j < 4; j++) {
|
2020-05-14 22:41:43 +08:00
|
|
|
if (j != k) {
|
2014-02-10 09:10:30 +08:00
|
|
|
matrix[k][j] /= pvt_val;
|
2020-05-14 22:41:43 +08:00
|
|
|
}
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Replace pivot by reciprocal (at last we can touch it). **/
|
|
|
|
matrix[k][k] = 1.0 / pvt_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* That was most of the work, one final pass of row/column interchange */
|
|
|
|
/* to finish */
|
|
|
|
for (k = 4 - 2; k >= 0; k--) { /* Don't need to work with 1 by 1 corner*/
|
|
|
|
i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */
|
|
|
|
if (i != k) { /* If rows are different */
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
hold = matrix[k][j];
|
|
|
|
matrix[k][j] = -matrix[i][j];
|
|
|
|
matrix[i][j] = hold;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */
|
2020-05-14 22:41:43 +08:00
|
|
|
if (j != k) { /* If columns are different */
|
2014-02-10 09:10:30 +08:00
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
hold = matrix[i][k];
|
|
|
|
matrix[i][k] = -matrix[i][j];
|
|
|
|
matrix[i][j] = hold;
|
|
|
|
}
|
2020-05-14 22:41:43 +08:00
|
|
|
}
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::flip_y() {
|
2019-08-21 04:54:03 +08:00
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
matrix[1][i] = -matrix[1][i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Projection::Projection() {
|
2014-02-10 09:10:30 +08:00
|
|
|
set_identity();
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Projection Projection::operator*(const Projection &p_matrix) const {
|
|
|
|
Projection new_matrix;
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
real_t ab = 0;
|
2020-05-14 22:41:43 +08:00
|
|
|
for (int k = 0; k < 4; k++) {
|
2014-02-10 09:10:30 +08:00
|
|
|
ab += matrix[k][i] * p_matrix.matrix[j][k];
|
2020-05-14 22:41:43 +08:00
|
|
|
}
|
2014-02-10 09:10:30 +08:00
|
|
|
new_matrix.matrix[j][i] = ab;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return new_matrix;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_depth_correction(bool p_flip_y) {
|
2019-09-07 09:51:27 +08:00
|
|
|
real_t *m = &matrix[0][0];
|
|
|
|
|
|
|
|
m[0] = 1;
|
|
|
|
m[1] = 0.0;
|
|
|
|
m[2] = 0.0;
|
|
|
|
m[3] = 0.0;
|
|
|
|
m[4] = 0.0;
|
2019-09-10 04:50:51 +08:00
|
|
|
m[5] = p_flip_y ? -1 : 1;
|
2019-09-07 09:51:27 +08:00
|
|
|
m[6] = 0.0;
|
|
|
|
m[7] = 0.0;
|
|
|
|
m[8] = 0.0;
|
|
|
|
m[9] = 0.0;
|
|
|
|
m[10] = 0.5;
|
|
|
|
m[11] = 0.0;
|
|
|
|
m[12] = 0.0;
|
|
|
|
m[13] = 0.0;
|
|
|
|
m[14] = 0.5;
|
|
|
|
m[15] = 1.0;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_light_bias() {
|
2017-01-15 04:35:39 +08:00
|
|
|
real_t *m = &matrix[0][0];
|
2017-03-05 23:44:50 +08:00
|
|
|
|
2019-07-01 18:59:42 +08:00
|
|
|
m[0] = 0.5;
|
|
|
|
m[1] = 0.0;
|
|
|
|
m[2] = 0.0;
|
|
|
|
m[3] = 0.0;
|
|
|
|
m[4] = 0.0;
|
|
|
|
m[5] = 0.5;
|
|
|
|
m[6] = 0.0;
|
|
|
|
m[7] = 0.0;
|
|
|
|
m[8] = 0.0;
|
|
|
|
m[9] = 0.0;
|
|
|
|
m[10] = 0.5;
|
|
|
|
m[11] = 0.0;
|
|
|
|
m[12] = 0.5;
|
|
|
|
m[13] = 0.5;
|
|
|
|
m[14] = 0.5;
|
2016-03-09 07:00:52 +08:00
|
|
|
m[15] = 1.0;
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::set_light_atlas_rect(const Rect2 &p_rect) {
|
2017-01-15 04:35:39 +08:00
|
|
|
real_t *m = &matrix[0][0];
|
2017-03-05 23:44:50 +08:00
|
|
|
|
2019-07-01 18:59:42 +08:00
|
|
|
m[0] = p_rect.size.width;
|
|
|
|
m[1] = 0.0;
|
|
|
|
m[2] = 0.0;
|
|
|
|
m[3] = 0.0;
|
|
|
|
m[4] = 0.0;
|
|
|
|
m[5] = p_rect.size.height;
|
|
|
|
m[6] = 0.0;
|
|
|
|
m[7] = 0.0;
|
|
|
|
m[8] = 0.0;
|
|
|
|
m[9] = 0.0;
|
|
|
|
m[10] = 1.0;
|
|
|
|
m[11] = 0.0;
|
|
|
|
m[12] = p_rect.position.x;
|
|
|
|
m[13] = p_rect.position.y;
|
|
|
|
m[14] = 0.0;
|
2016-11-10 10:55:06 +08:00
|
|
|
m[15] = 1.0;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Projection::operator String() const {
|
2014-02-10 09:10:30 +08:00
|
|
|
String str;
|
2020-05-14 22:41:43 +08:00
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
for (int j = 0; j < 4; j++) {
|
2014-02-10 09:10:30 +08:00
|
|
|
str += String((j > 0) ? ", " : "\n") + rtos(matrix[i][j]);
|
2020-05-14 22:41:43 +08:00
|
|
|
}
|
|
|
|
}
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
real_t Projection::get_aspect() const {
|
2020-01-22 02:39:16 +08:00
|
|
|
Vector2 vp_he = get_viewport_half_extents();
|
|
|
|
return vp_he.x / vp_he.y;
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
int Projection::get_pixels_per_meter(int p_for_pixel_width) const {
|
2016-12-04 23:45:30 +08:00
|
|
|
Vector3 result = xform(Vector3(1, 0, -1));
|
|
|
|
|
|
|
|
return int((result.x * 0.5 + 0.5) * p_for_pixel_width);
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
bool Projection::is_orthogonal() const {
|
2017-09-03 04:32:31 +08:00
|
|
|
return matrix[3][3] == 1.0;
|
2017-09-08 05:00:47 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
real_t Projection::get_fov() const {
|
2017-01-15 04:35:39 +08:00
|
|
|
const real_t *matrix = (const real_t *)this->matrix;
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
Plane right_plane = Plane(matrix[3] - matrix[0],
|
|
|
|
matrix[7] - matrix[4],
|
|
|
|
matrix[11] - matrix[8],
|
2017-01-16 17:32:44 +08:00
|
|
|
-matrix[15] + matrix[12]);
|
2017-01-16 05:15:47 +08:00
|
|
|
right_plane.normalize();
|
2014-02-10 09:10:30 +08:00
|
|
|
|
2017-04-23 20:10:41 +08:00
|
|
|
if ((matrix[8] == 0) && (matrix[9] == 0)) {
|
2022-08-13 23:45:42 +08:00
|
|
|
return Math::rad_to_deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0;
|
2017-04-23 20:10:41 +08:00
|
|
|
} else {
|
2017-09-19 16:51:00 +08:00
|
|
|
// our frustum is asymmetrical need to calculate the left planes angle separately..
|
2017-04-23 20:10:41 +08:00
|
|
|
Plane left_plane = Plane(matrix[3] + matrix[0],
|
|
|
|
matrix[7] + matrix[4],
|
|
|
|
matrix[11] + matrix[8],
|
|
|
|
matrix[15] + matrix[12]);
|
|
|
|
left_plane.normalize();
|
|
|
|
|
2022-08-13 23:45:42 +08:00
|
|
|
return Math::rad_to_deg(Math::acos(Math::abs(left_plane.normal.x))) + Math::rad_to_deg(Math::acos(Math::abs(right_plane.normal.x)));
|
2017-04-23 20:10:41 +08:00
|
|
|
}
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
float Projection::get_lod_multiplier() const {
|
2020-12-18 02:56:59 +08:00
|
|
|
if (is_orthogonal()) {
|
|
|
|
return get_viewport_half_extents().x;
|
|
|
|
} else {
|
|
|
|
float zn = get_z_near();
|
|
|
|
float width = get_viewport_half_extents().x * 2.0;
|
|
|
|
return 1.0 / (zn / width);
|
|
|
|
}
|
|
|
|
|
|
|
|
//usage is lod_size / (lod_distance * multiplier) < threshold
|
|
|
|
}
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::make_scale(const Vector3 &p_scale) {
|
2014-02-10 09:10:30 +08:00
|
|
|
set_identity();
|
|
|
|
matrix[0][0] = p_scale.x;
|
|
|
|
matrix[1][1] = p_scale.y;
|
|
|
|
matrix[2][2] = p_scale.z;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::scale_translate_to_fit(const AABB &p_aabb) {
|
2017-06-07 02:33:51 +08:00
|
|
|
Vector3 min = p_aabb.position;
|
|
|
|
Vector3 max = p_aabb.position + p_aabb.size;
|
2017-03-05 23:44:50 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
matrix[0][0] = 2 / (max.x - min.x);
|
|
|
|
matrix[1][0] = 0;
|
|
|
|
matrix[2][0] = 0;
|
|
|
|
matrix[3][0] = -(max.x + min.x) / (max.x - min.x);
|
2017-03-05 23:44:50 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
matrix[0][1] = 0;
|
|
|
|
matrix[1][1] = 2 / (max.y - min.y);
|
|
|
|
matrix[2][1] = 0;
|
|
|
|
matrix[3][1] = -(max.y + min.y) / (max.y - min.y);
|
2017-03-05 23:44:50 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
matrix[0][2] = 0;
|
|
|
|
matrix[1][2] = 0;
|
|
|
|
matrix[2][2] = 2 / (max.z - min.z);
|
|
|
|
matrix[3][2] = -(max.z + min.z) / (max.z - min.z);
|
2017-03-05 23:44:50 +08:00
|
|
|
|
2014-02-10 09:10:30 +08:00
|
|
|
matrix[0][3] = 0;
|
|
|
|
matrix[1][3] = 0;
|
|
|
|
matrix[2][3] = 0;
|
|
|
|
matrix[3][3] = 1;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
void Projection::add_jitter_offset(const Vector2 &p_offset) {
|
2022-04-04 22:10:22 +08:00
|
|
|
matrix[3][0] += p_offset.x;
|
|
|
|
matrix[3][1] += p_offset.y;
|
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Projection::operator Transform3D() const {
|
2020-10-17 13:08:21 +08:00
|
|
|
Transform3D tr;
|
2017-01-15 04:35:39 +08:00
|
|
|
const real_t *m = &matrix[0][0];
|
2014-02-10 09:10:30 +08:00
|
|
|
|
2022-04-25 06:07:35 +08:00
|
|
|
tr.basis.rows[0][0] = m[0];
|
|
|
|
tr.basis.rows[1][0] = m[1];
|
|
|
|
tr.basis.rows[2][0] = m[2];
|
2014-02-10 09:10:30 +08:00
|
|
|
|
2022-04-25 06:07:35 +08:00
|
|
|
tr.basis.rows[0][1] = m[4];
|
|
|
|
tr.basis.rows[1][1] = m[5];
|
|
|
|
tr.basis.rows[2][1] = m[6];
|
2014-02-10 09:10:30 +08:00
|
|
|
|
2022-04-25 06:07:35 +08:00
|
|
|
tr.basis.rows[0][2] = m[8];
|
|
|
|
tr.basis.rows[1][2] = m[9];
|
|
|
|
tr.basis.rows[2][2] = m[10];
|
2014-02-10 09:10:30 +08:00
|
|
|
|
|
|
|
tr.origin.x = m[12];
|
|
|
|
tr.origin.y = m[13];
|
|
|
|
tr.origin.z = m[14];
|
|
|
|
|
|
|
|
return tr;
|
|
|
|
}
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Projection::Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w) {
|
|
|
|
matrix[0] = p_x;
|
|
|
|
matrix[1] = p_y;
|
|
|
|
matrix[2] = p_z;
|
|
|
|
matrix[3] = p_w;
|
|
|
|
}
|
|
|
|
Projection::Projection(const Transform3D &p_transform) {
|
2020-10-17 13:08:21 +08:00
|
|
|
const Transform3D &tr = p_transform;
|
2017-01-15 04:35:39 +08:00
|
|
|
real_t *m = &matrix[0][0];
|
2017-03-05 23:44:50 +08:00
|
|
|
|
2022-04-25 06:07:35 +08:00
|
|
|
m[0] = tr.basis.rows[0][0];
|
|
|
|
m[1] = tr.basis.rows[1][0];
|
|
|
|
m[2] = tr.basis.rows[2][0];
|
2014-02-10 09:10:30 +08:00
|
|
|
m[3] = 0.0;
|
2022-04-25 06:07:35 +08:00
|
|
|
m[4] = tr.basis.rows[0][1];
|
|
|
|
m[5] = tr.basis.rows[1][1];
|
|
|
|
m[6] = tr.basis.rows[2][1];
|
2014-02-10 09:10:30 +08:00
|
|
|
m[7] = 0.0;
|
2022-04-25 06:07:35 +08:00
|
|
|
m[8] = tr.basis.rows[0][2];
|
|
|
|
m[9] = tr.basis.rows[1][2];
|
|
|
|
m[10] = tr.basis.rows[2][2];
|
2014-02-10 09:10:30 +08:00
|
|
|
m[11] = 0.0;
|
|
|
|
m[12] = tr.origin.x;
|
|
|
|
m[13] = tr.origin.y;
|
|
|
|
m[14] = tr.origin.z;
|
2016-03-09 07:00:52 +08:00
|
|
|
m[15] = 1.0;
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 07:11:13 +08:00
|
|
|
Projection::~Projection() {
|
2014-02-10 09:10:30 +08:00
|
|
|
}
|