1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
from typing import Optional
import glm
class Projection3D:
"""3D Projection"""
def __init__(
self, aspect_ratio: float = 16 / 9, fov: float = 75.0, near: float = 1.0, far: float = 100.0
):
"""Create a 3D projection
Keyword Args:
aspect_ratio (float): Aspect ratio
fov (float): Field of view
near (float): Near plane value
far (float): Far plane value
"""
self._aspect_ratio = aspect_ratio
self._fov = fov
self._near = near
self._far = far
self._matrix = glm.mat4(0)
self._matrix_bytes = bytes(0)
self.update()
@property
def aspect_ratio(self) -> float:
"""float: The projection's aspect ratio"""
return self._aspect_ratio
@property
def fov(self) -> float:
"""float: Current field of view"""
return self._fov
@property
def near(self) -> float:
"""float: Current near plane value"""
return self._near
@property
def far(self) -> float:
"""float : Current far plane value"""
return self._far
@property
def matrix(self) -> glm.mat4:
"""glm.mat4x4: Current projection matrix"""
return self._matrix
def update(
self,
aspect_ratio: Optional[float] = None,
fov: Optional[float] = None,
near: Optional[float] = None,
far: Optional[float] = None,
) -> None:
"""Update the projection matrix
Keyword Args:
aspect_ratio (float): Aspect ratio
fov (float): Field of view
near (float): Near plane value
far (float): Far plane value
"""
if aspect_ratio is not None:
self._aspect_ratio = aspect_ratio
if fov is not None:
self._fov = fov
if near is not None:
self._near = near
if far is not None:
self._far = far
self._matrix = glm.perspective(
glm.radians(self._fov), self._aspect_ratio, self._near, self._far
)
self._matrix_bytes = self._matrix.to_bytes()
def tobytes(self) -> bytes:
"""Get the byte representation of the projection matrix
Returns:
bytes: byte representation of the projection matrix
"""
return self._matrix_bytes
@property
def projection_constants(self) -> tuple[float, float]:
"""
(x, y) projection constants for the current projection.
This is for example useful when reconstructing a view position
of a fragment from a linearized depth value.
"""
return (
self._far / (self._far - self._near),
(self._far * self._near) / (self._near - self._far),
)
|