Skip to content

Configuration

This page contains class defined in the hkw.setup module.

Config

Invocation-time renderer configuration and coordinate presets.

Config dataclass

Invocation-time renderer policy, separate from visualization intent.

A :class:~hakowan.grammar.figure.Figure stores portable camera, lighting, environment, and output intent. Passing an explicit Config to rendering selects operational backend settings and overrides the complete Figure-derived configuration rather than merging with it.

Attributes:

Name Type Description
sensor Sensor

Sensor settings.

film Film

Film settings.

sampler Sampler

Sampler settings.

emitters list[Emitter]

Emitter settings.

integrator Integrator

Integrator settings.

render_passes frozenset[str]

Set of active render passes. Recognised values:

  • "albedo" – diffuse color without shading.
  • "depth" – depth buffer.
  • "normal" – shading-normal pass.
  • "facet_id" – per-face index encoded as RGB (Blender only).

The convenience properties :attr:albedo, :attr:depth, :attr:normal, and :attr:facet_id are thin aliases that add or remove the corresponding string from this set. Assigning an unrecognised pass name raises :class:ValueError (validated against :data:hakowan.setup.render_pass.RENDER_PASSES).

Backend support varies: requesting a pass the chosen backend cannot honor logs a warning and is otherwise ignored. Each honored pass is written to a <stem>_<pass><ext> sidecar file (or exposed as a live viewer toggle for WebGL); see :class:hakowan.render.RenderResult for the per-render manifest.

environment_visible bool

Show an environment map to the camera when true.

background Literal['light', 'dark'] | None

Optional WebGL/raster light or dark background override.

Source code in hakowan/setup/config.py
@dataclass(kw_only=True, slots=True)
class Config:
    """Invocation-time renderer policy, separate from visualization intent.

    A :class:`~hakowan.grammar.figure.Figure` stores portable camera, lighting,
    environment, and output intent. Passing an explicit ``Config`` to rendering
    selects operational backend settings and overrides the complete
    Figure-derived configuration rather than merging with it.

    Attributes:
        sensor: Sensor settings.
        film: Film settings.
        sampler: Sampler settings.
        emitters: Emitter settings.
        integrator: Integrator settings.
        render_passes: Set of active render passes.  Recognised values:

            - ``"albedo"``    – diffuse color without shading.
            - ``"depth"``     – depth buffer.
            - ``"normal"``    – shading-normal pass.
            - ``"facet_id"``  – per-face index encoded as RGB (Blender only).

            The convenience properties :attr:`albedo`, :attr:`depth`,
            :attr:`normal`, and :attr:`facet_id` are thin aliases that add or
            remove the corresponding string from this set.  Assigning an
            unrecognised pass name raises :class:`ValueError` (validated against
            :data:`hakowan.setup.render_pass.RENDER_PASSES`).

            Backend support varies: requesting a pass the chosen backend cannot
            honor logs a warning and is otherwise ignored.  Each honored pass is
            written to a ``<stem>_<pass><ext>`` sidecar file (or exposed as a
            live viewer toggle for WebGL); see
            :class:`hakowan.render.RenderResult` for the per-render manifest.
        environment_visible: Show an environment map to the camera when true.
        background: Optional WebGL/raster light or dark background override.

    """

    sensor: Sensor = field(default_factory=Perspective)
    film: Film = field(default_factory=Film)
    sampler: Sampler = field(default_factory=Independent)
    emitters: list[Emitter] = field(default_factory=lambda: [Envmap()])
    integrator: Integrator = field(default_factory=Path)
    _render_passes: set[str] = field(default_factory=set)
    environment_visible: bool = False
    background: Literal["light", "dark"] | None = None

    def __setattr__(self, name, value):
        if name == "background" and value not in {None, "light", "dark"}:
            raise ValueError("Config.background must be 'light', 'dark', or None.")
        object.__setattr__(self, name, value)

    def z_up(self) -> None:
        """Update configuration for z-up coordinate system."""
        self.sensor.location = np.array([0, -5, 0])
        self.sensor.up = np.array([0, 0, 1])
        for emitter in self.emitters:
            if isinstance(emitter, Envmap):
                emitter.up = np.array([0, 0, 1])
                emitter.rotation = 180.0

    def z_down(self) -> None:
        """Update configuration for z-down coordinate system."""
        self.sensor.location = np.array([0, 5, 0])
        self.sensor.up = np.array([0, 0, -1])
        for emitter in self.emitters:
            if isinstance(emitter, Envmap):
                emitter.up = np.array([0, 0, -1])
                emitter.rotation = 180.0

    def y_up(self) -> None:
        """Update configuration for y-up coordinate system."""
        self.sensor.location = np.array([0, 0, 5])
        self.sensor.up = np.array([0, 1, 0])
        for emitter in self.emitters:
            if isinstance(emitter, Envmap):
                emitter.up = np.array([0, 1, 0])
                emitter.rotation = 180.0

    def y_down(self) -> None:
        """Update configuration for y-down coordinate system."""
        self.sensor.location = np.array([0, 0, -5])
        self.sensor.up = np.array([0, -1, 0])
        for emitter in self.emitters:
            if isinstance(emitter, Envmap):
                emitter.up = np.array([0, -1, 0])
                emitter.rotation = 180.0

    # ------------------------------------------------------------------ #
    # render_passes – primary interface                                    #
    # ------------------------------------------------------------------ #

    @property
    def render_passes(self) -> frozenset[str]:
        """Immutable set of requested semantic render passes.

        Valid pass names are ``"albedo"``, ``"depth"``, ``"normal"``, and
        ``"facet_id"``. Assign a collection to replace the requests. Backends
        derive their native pass configuration at render time, keeping this set
        as the single source of truth.

        Example::

            config.render_passes = {"albedo", "depth"}
        """
        return frozenset(self._render_passes)

    @render_passes.setter
    def render_passes(self, value: set[str] | list[str] | frozenset[str]) -> None:
        """Replace the requested render passes after validating every name."""
        names = set(value)
        for name in names:
            get_render_pass(name)  # type: ignore[arg-type]
        self._render_passes = names

    # ------------------------------------------------------------------ #
    # Convenience boolean aliases                                          #
    # ------------------------------------------------------------------ #

    @property
    def albedo(self) -> bool:
        """Whether the albedo pass is active.  Alias for ``"albedo" in render_passes``."""
        return "albedo" in self._render_passes

    @albedo.setter
    def albedo(self, value: bool) -> None:
        """Add or remove the albedo pass request."""
        if value:
            self._render_passes.add("albedo")
        else:
            self._render_passes.discard("albedo")

    @property
    def depth(self) -> bool:
        """Whether the depth pass is active.  Alias for ``"depth" in render_passes``."""
        return "depth" in self._render_passes

    @depth.setter
    def depth(self, value: bool) -> None:
        """Add or remove the depth pass request."""
        if value:
            self._render_passes.add("depth")
        else:
            self._render_passes.discard("depth")

    @property
    def normal(self) -> bool:
        """Whether the shading-normal pass is active.  Alias for ``"normal" in render_passes``."""
        return "normal" in self._render_passes

    @normal.setter
    def normal(self, value: bool) -> None:
        """Add or remove the normal pass request."""
        if value:
            self._render_passes.add("normal")
        else:
            self._render_passes.discard("normal")

    @property
    def facet_id(self) -> bool:
        """Whether the facet-ID pass is active.  Alias for ``"facet_id" in render_passes``.

        When active the Blender backend performs a second render after the
        main one.  Every mesh face is colored with the RGB encoding of its
        zero-based index (R = high byte, G = mid byte, B = low byte) using a
        flat Emission shader so lighting has no effect.  The output is written
        to ``<stem>_facet_id<ext>`` with gamma correction, temporal blending,
        pixel filtering, and dithering all disabled so pixel values can be
        decoded directly::

            fid = (R << 16) | (G << 8) | B

        Background pixels have ``A = 0`` and can be masked out.  Supports up
        to 2**24 − 1 ≈ 16.7 M faces.
        """
        return "facet_id" in self._render_passes

    @facet_id.setter
    def facet_id(self, value: bool) -> None:
        """Add or remove the facet-ID pass."""
        if value:
            self._render_passes.add("facet_id")
        else:
            self._render_passes.discard("facet_id")

albedo property writable

Whether the albedo pass is active. Alias for "albedo" in render_passes.

depth property writable

Whether the depth pass is active. Alias for "depth" in render_passes.

facet_id property writable

Whether the facet-ID pass is active. Alias for "facet_id" in render_passes.

When active the Blender backend performs a second render after the main one. Every mesh face is colored with the RGB encoding of its zero-based index (R = high byte, G = mid byte, B = low byte) using a flat Emission shader so lighting has no effect. The output is written to <stem>_facet_id<ext> with gamma correction, temporal blending, pixel filtering, and dithering all disabled so pixel values can be decoded directly::

fid = (R << 16) | (G << 8) | B

Background pixels have A = 0 and can be masked out. Supports up to 2**24 − 1 ≈ 16.7 M faces.

normal property writable

Whether the shading-normal pass is active. Alias for "normal" in render_passes.

render_passes property writable

Immutable set of requested semantic render passes.

Valid pass names are "albedo", "depth", "normal", and "facet_id". Assign a collection to replace the requests. Backends derive their native pass configuration at render time, keeping this set as the single source of truth.

Example::

config.render_passes = {"albedo", "depth"}

y_down()

Update configuration for y-down coordinate system.

Source code in hakowan/setup/config.py
def y_down(self) -> None:
    """Update configuration for y-down coordinate system."""
    self.sensor.location = np.array([0, 0, -5])
    self.sensor.up = np.array([0, -1, 0])
    for emitter in self.emitters:
        if isinstance(emitter, Envmap):
            emitter.up = np.array([0, -1, 0])
            emitter.rotation = 180.0

y_up()

Update configuration for y-up coordinate system.

Source code in hakowan/setup/config.py
def y_up(self) -> None:
    """Update configuration for y-up coordinate system."""
    self.sensor.location = np.array([0, 0, 5])
    self.sensor.up = np.array([0, 1, 0])
    for emitter in self.emitters:
        if isinstance(emitter, Envmap):
            emitter.up = np.array([0, 1, 0])
            emitter.rotation = 180.0

z_down()

Update configuration for z-down coordinate system.

Source code in hakowan/setup/config.py
def z_down(self) -> None:
    """Update configuration for z-down coordinate system."""
    self.sensor.location = np.array([0, 5, 0])
    self.sensor.up = np.array([0, 0, -1])
    for emitter in self.emitters:
        if isinstance(emitter, Envmap):
            emitter.up = np.array([0, 0, -1])
            emitter.rotation = 180.0

z_up()

Update configuration for z-up coordinate system.

Source code in hakowan/setup/config.py
def z_up(self) -> None:
    """Update configuration for z-up coordinate system."""
    self.sensor.location = np.array([0, -5, 0])
    self.sensor.up = np.array([0, 0, 1])
    for emitter in self.emitters:
        if isinstance(emitter, Envmap):
            emitter.up = np.array([0, 0, 1])
            emitter.rotation = 180.0

Emitter

Point, directional, and environment emitter settings.

Directional dataclass

Bases: Emitter

Directional light with rays traveling along direction.

Source code in hakowan/setup/emitter.py
@dataclass(kw_only=True, slots=True)
class Directional(Emitter):
    """Directional light with rays traveling along ``direction``."""

    direction: list[float] = field(default_factory=lambda: [0.0, 0.0, -1.0])
    intensity: float = 1.0
    color: ColorLike = "white"

    def __post_init__(self) -> None:
        direction = np.asarray(self.direction, dtype=np.float64)
        if (
            direction.shape != (3,)
            or not np.all(np.isfinite(direction))
            or np.linalg.norm(direction) <= 1e-12
        ):
            raise ValueError("Directional direction must be a finite non-zero vector.")
        if not isinstance(self.intensity, Real):
            raise TypeError("Directional intensity must be numeric.")
        if not np.isfinite(float(self.intensity)) or float(self.intensity) < 0.0:
            raise ValueError("Directional intensity must be finite and non-negative.")
        to_color(self.color)

Emitter dataclass

Emitter dataclass contains lighting-related settings.

Source code in hakowan/setup/emitter.py
@dataclass(kw_only=True, slots=True)
class Emitter:
    """Emitter dataclass contains lighting-related settings."""

    pass

Envmap dataclass

Bases: Emitter

Environment light (i.e. image-based lighting).

Attributes:

Name Type Description
filename Path

Path to the environment light image file.

scale float

Scaling factor to be applied to the environment light.

up ArrayLike

Up vector of the environment light.

rotation float

Rotation angle of the environment light around the up direction.

Source code in hakowan/setup/emitter.py
@dataclass(kw_only=True, slots=True)
class Envmap(Emitter):
    """Environment light (i.e. image-based lighting).

    Attributes:
        filename: Path to the environment light image file.
        scale: Scaling factor to be applied to the environment light.
        up: Up vector of the environment light.
        rotation: Rotation angle of the environment light around the up direction.

    """

    filename: Path = field(
        default_factory=lambda: Path(__file__).parents[1] / "envmaps" / "museum.exr"
    )
    scale: float = 1.0
    up: npt.ArrayLike = field(default_factory=lambda: [0, 1, 0])
    rotation: float = 180.0

    def __post_init__(self) -> None:
        up = np.asarray(self.up, dtype=np.float64)
        if (
            up.shape != (3,)
            or not np.all(np.isfinite(up))
            or np.linalg.norm(up) <= 1e-12
        ):
            raise ValueError("Environment up must be a finite non-zero vector.")
        if not isinstance(self.scale, Real):
            raise TypeError("Environment scale must be numeric.")
        if not np.isfinite(float(self.scale)) or float(self.scale) < 0.0:
            raise ValueError("Environment scale must be finite and non-negative.")

Point dataclass

Bases: Emitter

Point light source.

Attributes:

Name Type Description
intensity ColorLike | float

Numeric strength, or a legacy color when color is unset.

position list[float]

Three finite world-space coordinates.

color ColorLike | None

Optional light color; requires numeric intensity.

Source code in hakowan/setup/emitter.py
@dataclass(kw_only=True, slots=True)
class Point(Emitter):
    """Point light source.

    Attributes:
        intensity: Numeric strength, or a legacy color when ``color`` is unset.
        position: Three finite world-space coordinates.
        color: Optional light color; requires numeric ``intensity``.

    """

    intensity: ColorLike | float = 1.0
    position: list[float] = field(default_factory=lambda: [0.0, 0.0, 1.0])
    color: ColorLike | None = None

    def __post_init__(self) -> None:
        position = np.asarray(self.position, dtype=np.float64)
        if position.shape != (3,) or not np.all(np.isfinite(position)):
            raise ValueError("Point position must contain three finite values.")
        if self.color is not None:
            to_color(self.color)
            if not isinstance(self.intensity, Real):
                raise TypeError("Point intensity must be numeric when color is set")
        elif not isinstance(self.intensity, Real):
            to_color(self.intensity)
        if isinstance(self.intensity, Real) and (
            not np.isfinite(float(self.intensity)) or float(self.intensity) < 0.0
        ):
            raise ValueError("Point intensity must be finite and non-negative.")

Film

Output image dimensions, crop, and pixel-format settings.

Film dataclass

Film dataclass stores specifications of the output image.

Attributes:

Name Type Description
width int

Width of the output image in pixels.

height int

Height of the output image in pixels.

file_format str

File format of the output image.

pixel_format str

Pixel format of the output image.

component_format str

Component format of the output image.

crop_offset NDArray | None

Offset of the crop window in pixels.

crop_size NDArray | None

Size of the crop window in pixels.

Together, width and height specify the output image resolution. crop_offset and crop_size defines a crop region. If either is None, no cropping is performed. file_format, pixel_format and component_format are for advanced user only. The default values should work in most cases.

Source code in hakowan/setup/film.py
@dataclass(kw_only=True, slots=True)
class Film:
    """Film dataclass stores specifications of the output image.

    Attributes:
        width: Width of the output image in pixels.
        height: Height of the output image in pixels.
        file_format: File format of the output image.
        pixel_format: Pixel format of the output image.
        component_format: Component format of the output image.
        crop_offset: Offset of the crop window in pixels.
        crop_size: Size of the crop window in pixels.

    Together, `width` and `height` specify the output image resolution.
    `crop_offset` and `crop_size` defines a crop region. If either is `None`, no cropping is performed.
    `file_format`, `pixel_format` and `component_format` are for advanced user only. The default
    values should work in most cases.

    """

    width: int = 1024
    height: int = 800
    file_format: str = "openexr"
    pixel_format: str = "rgba"
    component_format: str = "float16"
    crop_offset: npt.NDArray | None = None
    crop_size: npt.NDArray | None = None

Integrator

Path tracing, volumetric, and auxiliary-output integrator settings.

AOV dataclass

Bases: Integrator

Arbitrary output variable (AOV) integrator.

Attributes:

Name Type Description
aovs list[str]

List of AOVs to render.

integrator Integrator | None

Beauty integrator evaluated with the AOV channels. None selects a path tracer so the output remains an RGBA image.

Note

See Mitsuba doc for supported AOV types and other details.

Source code in hakowan/setup/integrator.py
@dataclass(kw_only=True, slots=True)
class AOV(Integrator):
    """Arbitrary output variable (AOV) integrator.

    Attributes:
        aovs: List of AOVs to render.
        integrator: Beauty integrator evaluated with the AOV channels. ``None``
            selects a path tracer so the output remains an RGBA image.

    Note:
        See
        [Mitsuba
        doc](https://mitsuba.readthedocs.io/en/stable/src/generated/plugins_integrators.html#arbitrary-output-variables-integrator-aov)
        for supported AOV types and other details.

    """

    aovs: list[str]
    integrator: Integrator | None = None

Direct dataclass

Bases: Integrator

Direct integrator.

Attributes:

Name Type Description
shading_samples int | None

Number of shading samples.

emitter_samples int | None

Number of emitter samples.

bsdf_samples int | None

Number of BSDF samples.

Note

See Mitsuba doc for more details.

Source code in hakowan/setup/integrator.py
@dataclass(kw_only=True, slots=True)
class Direct(Integrator):
    """Direct integrator.

    Attributes:
        shading_samples: Number of shading samples.
        emitter_samples: Number of emitter samples.
        bsdf_samples: Number of BSDF samples.

    Note:
        See
        [Mitsuba doc](https://mitsuba.readthedocs.io/en/stable/src/generated/plugins_integrators.html#direct-illumination-integrator-direct)
        for more details.

    """

    shading_samples: int | None = None
    emitter_samples: int | None = None
    bsdf_samples: int | None = None

Integrator dataclass

Integrator dataclass contains parameters of various rendering techniques.

Attributes:

Name Type Description
hide_emitters bool

Whether to hide emitters from the camera.

Source code in hakowan/setup/integrator.py
@dataclass(kw_only=True, slots=True)
class Integrator:
    """Integrator dataclass contains parameters of various rendering techniques.

    Attributes:
        hide_emitters: Whether to hide emitters from the camera.

    """

    hide_emitters: bool = True

Path dataclass

Bases: Integrator

Path integrator.

Attributes:

Name Type Description
max_depth int

Maximum path depth. (-1 for unlimited)

rr_depth int

Depth at which Russian roulette starts.

Note

This integrator should work well for most surface-based scenes. See Mitsuba doc for more details.

Source code in hakowan/setup/integrator.py
@dataclass(kw_only=True, slots=True)
class Path(Integrator):
    """Path integrator.

    Attributes:
        max_depth: Maximum path depth. (-1 for unlimited)
        rr_depth: Depth at which Russian roulette starts.

    Note:
        This integrator should work well for most surface-based scenes.
        See
        [Mitsuba
        doc](https://mitsuba.readthedocs.io/en/stable/src/generated/plugins_integrators.html#path-tracer-path)
        for more details.

    """

    max_depth: int = -1
    rr_depth: int = 5

VolPath dataclass

Bases: Integrator

Volumetric path integrator.

Attributes:

Name Type Description
max_depth int

Maximum path depth. (-1 for unlimited)

rr_depth int

Depth at which Russian roulette starts.

Note

This integrator should work well for most volume-based scenes. For example, if dielectric material is involved, VolPath integrator sometimes produces better results than Path integrator.

See Mitsuba doc for more details.

Source code in hakowan/setup/integrator.py
@dataclass(kw_only=True, slots=True)
class VolPath(Integrator):
    """Volumetric path integrator.

    Attributes:
        max_depth: Maximum path depth. (-1 for unlimited)
        rr_depth: Depth at which Russian roulette starts.

    Note:
        This integrator should work well for most volume-based scenes. For example, if dielectric
        material is involved, `VolPath` integrator sometimes produces better results than `Path`
        integrator.

        See
        [Mitsuba
        doc](https://mitsuba.readthedocs.io/en/stable/src/generated/plugins_integrators.html#volumetric-path-tracer-volpath)
        for more details.

    """

    max_depth: int = -1
    rr_depth: int = 5

VolPathMIS dataclass

Bases: Integrator

Volumetric path integrator with spectral MIS.

Attributes:

Name Type Description
max_depth int

Maximum path depth. (-1 for unlimited)

rr_depth int

Depth at which Russian roulette starts.

Note

See Mitsuba doc for more details.

Source code in hakowan/setup/integrator.py
@dataclass(kw_only=True, slots=True)
class VolPathMIS(Integrator):
    """Volumetric path integrator with spectral MIS.

    Attributes:
        max_depth: Maximum path depth. (-1 for unlimited)
        rr_depth: Depth at which Russian roulette starts.

    Note:
        See
        [Mitsuba
        doc](https://mitsuba.readthedocs.io/en/stable/src/generated/plugins_integrators.html#volumetric-path-tracer-with-spectral-mis-volpathmis)
        for more details.

    """

    max_depth: int = -1
    rr_depth: int = 5

Sampler

Independent and low-discrepancy sampler settings.

Independent dataclass

Bases: Sampler

Independent sampler.

Note

See Mitsuba doc for more details.

Source code in hakowan/setup/sampler.py
@dataclass(kw_only=True, slots=True)
class Independent(Sampler):
    """Independent sampler.

    Note:
        See
        [Mitsuba
        doc](https://mitsuba.readthedocs.io/en/stable/src/generated/plugins_samplers.html#independent-sampler-independent)
        for more details.

    """

    pass

Sampler dataclass

Sampler dataclass contains sampling-related settings.

Attributes:

Name Type Description
sample_count int

Number of samples per pixel.

seed int

Seed for random number generate.

Source code in hakowan/setup/sampler.py
@dataclass(kw_only=True, slots=True)
class Sampler:
    """Sampler dataclass contains sampling-related settings.

    Attributes:
        sample_count: Number of samples per pixel.
        seed: Seed for random number generate.

    """

    sample_count: int = 256  # Samples per pixel.
    seed: int = 0

Stratified dataclass

Bases: Sampler

Stratified sampler.

Attributes:

Name Type Description
jitter bool

Whether to jitter the samples.

Note

See Mitsuba doc for more details.

Source code in hakowan/setup/sampler.py
@dataclass(kw_only=True, slots=True)
class Stratified(Sampler):
    """Stratified sampler.

    Attributes:
        jitter: Whether to jitter the samples.

    Note:
        See [Mitsuba
        doc](https://mitsuba.readthedocs.io/en/stable/src/generated/plugins_samplers.html#stratified-sampler-stratified)
        for more details.

    """

    jitter: bool = True

Sensor

Perspective, orthographic, and thin-lens camera settings.

Orthographic dataclass

Bases: Sensor

Orthographic camera with a full vertical framing extent.

Source code in hakowan/setup/sensor.py
@dataclass(kw_only=True, slots=True)
class Orthographic(Sensor):
    """Orthographic camera with a full vertical framing extent."""

    scale: float = 2.0

Perspective dataclass

Bases: Sensor

Perspective camera dataclass.

Attributes:

Name Type Description
fov float

Field of view in degrees.

fov_axis Literal['x', 'y', 'diagonal', 'smaller', 'larger']

Axis to which fov is applied. "smaller" / "larger" refer to the shorter / longer image dimension, making the field-of-view resolution-independent.

Source code in hakowan/setup/sensor.py
@dataclass(kw_only=True, slots=True)
class Perspective(Sensor):
    """Perspective camera dataclass.

    Attributes:
        fov: Field of view in degrees.
        fov_axis (Literal["x", "y", "diagonal", "smaller", "larger"]): Axis to which fov
            is applied. ``"smaller"`` / ``"larger"`` refer to the shorter / longer image
            dimension, making the field-of-view resolution-independent.

    """

    fov: float = 28.8415  # degrees
    fov_axis: Literal["x", "y", "diagonal", "smaller", "larger"] = "smaller"

Sensor dataclass

Sensor dataclass contains camera-related settings.

Attributes:

Name Type Description
location ArrayLike

Camera location in world space.

target ArrayLike

Camera look-at location in world space.

up ArrayLike

Camera up vector in world space.

near_clip float

Near clipping plane distance.

far_clip float

Far clipping plane distance.

Source code in hakowan/setup/sensor.py
@dataclass(kw_only=True, slots=True)
class Sensor:
    """Sensor dataclass contains camera-related settings.

    Attributes:
        location: Camera location in world space.
        target: Camera look-at location in world space.
        up: Camera up vector in world space.
        near_clip: Near clipping plane distance.
        far_clip: Far clipping plane distance.

    """

    location: npt.ArrayLike = field(default_factory=lambda: [0, 0, 5])
    target: npt.ArrayLike = field(default_factory=lambda: [0, 0, 0])
    up: npt.ArrayLike = field(default_factory=lambda: [0, 1, 0])
    near_clip: float = 1e-2
    far_clip: float = 1e4

ThinLens dataclass

Bases: Perspective

Thin lens camera dataclass.

Attributes:

Name Type Description
aperture_radius float

Radius of the aperture in world space.

focus_distance float

Distance to the focal plane in world space.

Source code in hakowan/setup/sensor.py
@dataclass(kw_only=True, slots=True)
class ThinLens(Perspective):
    """Thin lens camera dataclass.

    Attributes:
        aperture_radius: Radius of the aperture in world space.
        focus_distance: Distance to the focal plane in world space.

    """

    aperture_radius: float = 0.1
    focus_distance: float = 0.0