Skip to content

Commit

Permalink
feat(pyraydeon): expose render settings through python
Browse files Browse the repository at this point in the history
  • Loading branch information
cbgbt committed Nov 27, 2024
1 parent a27899f commit 995f5d2
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 196 deletions.
12 changes: 11 additions & 1 deletion pyraydeon/examples/py_sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
PointLight,
Plane,
LineSegment3D,
CameraOptions,
)


Expand Down Expand Up @@ -107,7 +108,16 @@ def paths(self, cam):
znear = 0.1
zfar = 100.0

cam = Camera().look_at(eye, focus, up).perspective(fovy, width, height, znear, zfar)
render_opts = CameraOptions(pen_px_size=4.0)

assert render_opts.hatch_slice_forgiveness == 1

cam = (
Camera()
.look_at(eye, focus, up)
.perspective(fovy, width, height, znear, zfar)
.render_options(render_opts)
)

paths = scene.render_with_lighting(cam, seed=5)

Expand Down
10 changes: 8 additions & 2 deletions pyraydeon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use pyo3::prelude::*;

macro_rules! pywrap {
($name:ident, $wraps:ty) => {
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
#[pyclass(frozen)]
pub(crate) struct $name(pub(crate) $wraps);

Expand All @@ -22,6 +22,7 @@ macro_rules! pywrap {
};
}

mod camera;
mod light;
mod linear;
mod material;
Expand All @@ -33,10 +34,15 @@ mod shapes;
#[pymodule]
fn pyraydeon(m: &Bound<'_, PyModule>) -> PyResult<()> {
crate::linear::register(m)?;
crate::shapes::register(m)?;

crate::camera::register(m)?;
crate::scene::register(m)?;

crate::ray::register(m)?;

crate::shapes::register(m)?;
crate::material::register(m)?;
crate::light::register(m)?;

Ok(())
}
115 changes: 8 additions & 107 deletions pyraydeon/src/scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,108 +4,12 @@ use numpy::{Ix1, PyArray, PyReadonlyArray1};
use pyo3::prelude::*;
use raydeon::SceneLighting;

use crate::camera::Camera;
use crate::light::PointLight;
use crate::linear::{ArbitrarySpace, Point2, Point3, Vec3};
use crate::linear::{ArbitrarySpace, Point2, Point3};
use crate::material::Material;
use crate::shapes::Geometry;

#[derive(Debug, Clone)]
#[pyclass(frozen)]
pub(crate) struct Camera(pub(crate) raydeon::Camera);

impl ::std::ops::Deref for Camera {
type Target = raydeon::Camera;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl From<raydeon::Camera> for Camera {
fn from(value: raydeon::Camera) -> Self {
Self(value)
}
}

#[pymethods]
impl Camera {
#[new]
fn new() -> Self {
raydeon::Camera::default().into()
}

fn look_at(
&self,
eye: &Bound<'_, PyAny>,
center: &Bound<'_, PyAny>,
up: &Bound<'_, PyAny>,
) -> PyResult<Camera> {
let eye = Point3::try_from(eye)?;
let center = Vec3::try_from(center)?;
let up = Vec3::try_from(up)?;
let mut ncam = self.0.clone();
ncam.observation =
raydeon::Camera::look_at(eye.cast_unit(), center.cast_unit(), up.cast_unit());
Ok(ncam.into())
}

fn perspective(&self, fovy: f64, width: usize, height: usize, znear: f64, zfar: f64) -> Camera {
let mut ncam = self.0.clone();
ncam.perspective = raydeon::Camera::perspective(fovy, width, height, znear, zfar);
ncam.into()
}

#[getter]
fn eye<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray<f64, Ix1>> {
PyArray::from_slice_bound(py, &self.0.observation.eye.to_array())
}

#[getter]
fn focus<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray<f64, Ix1>> {
PyArray::from_slice_bound(py, &self.0.observation.center.to_array())
}

#[getter]
fn up<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray<f64, Ix1>> {
PyArray::from_slice_bound(py, &self.0.observation.up.to_array())
}

#[getter]
fn fovy(&self) -> f64 {
self.0.perspective.fovy
}

#[getter]
fn width(&self) -> usize {
self.0.perspective.width
}

#[getter]
fn height(&self) -> usize {
self.0.perspective.height
}

#[getter]
fn aspect(&self) -> f64 {
self.0.perspective.aspect
}

#[getter]
fn znear(&self) -> f64 {
self.0.perspective.znear
}

#[getter]
fn zfar(&self) -> f64 {
self.0.perspective.zfar
}

fn __repr__(slf: &Bound<'_, Self>) -> PyResult<String> {
let class_name = slf.get_type().qualname()?;
Ok(format!("{}<{:?}>", class_name, slf.borrow().0))
}
}

#[pyclass(frozen)]
pub(crate) struct Scene {
scene: Arc<raydeon::Scene>,
Expand Down Expand Up @@ -228,14 +132,12 @@ impl LineSegment3D {
) -> PyResult<Self> {
let p1 = Point3::try_from(p1)?;
let p2 = Point3::try_from(p2)?;
Ok(
raydeon::path::LineSegment3D::new(
p1.cast_unit(),
p2.cast_unit(),
material.map(|i| i.0),
)
.into(),
)
Ok(raydeon::path::LineSegment3D::new()
.p1(p1.cast_unit())
.p2(p2.cast_unit())
.maybe_material(material.map(|i| i.0))
.build()
.into())
}

#[getter]
Expand All @@ -255,7 +157,6 @@ impl LineSegment3D {
}

pub(crate) fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<Camera>()?;
m.add_class::<Scene>()?;
m.add_class::<LineSegment2D>()?;
m.add_class::<LineSegment3D>()?;
Expand Down
3 changes: 2 additions & 1 deletion pyraydeon/src/shapes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ mod primitive;

pub(crate) use primitive::{AxisAlignedCuboid, Tri};

use crate::camera::Camera;
use crate::material::Material;
use crate::ray::{HitData, Ray, AABB3};
use crate::scene::{Camera, LineSegment3D};
use crate::scene::LineSegment3D;

#[derive(Debug)]
enum InnerGeometry {
Expand Down
2 changes: 1 addition & 1 deletion raydeon/examples/cube.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn main() {
let camera = Camera::configure()
.observation(Camera::look_at(eye, focus, up))
.perspective(Camera::perspective(fovy, width, height, znear, zfar))
.render_options(CameraOptions::defaults_for_pen_px_size(4.0))
.render_options(CameraOptions::configure().pen_px_size(4.0).build())
.build();

let paths = scene.attach_camera(camera).render();
Expand Down
29 changes: 15 additions & 14 deletions raydeon/src/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ use path::SlicedSegment3D;
use self::view_matrix_settings::*;
use crate::*;

pub const DEFAULT_PEN_PX_SIZE: f64 = 4.0;
pub const DEFAULT_HATCH_PIXEL_SPACING_FACTOR: f64 = 2.0;
pub const DEFAULT_HATCH_PIXEL_CHOP_QUOTIENT: f64 = 3.0;
pub const DEFAULT_HATCH_SLICE_FORGIVENESS: usize = 1;
pub const DEFAULT_VERT_HATCH_BRIGHTNESS_SCALING: f64 = 0.8;
pub const DEFAULT_DIAG_HATCH_BRIGHTNESS_SCALING: f64 = 0.46;

#[derive(Debug, Clone, Builder, Default)]
#[builder(start_fn(name = configure))]
pub struct Camera {
Expand All @@ -15,31 +22,25 @@ pub struct Camera {
}

#[derive(Debug, Clone, Builder)]
#[builder(start_fn(name = configure))]
pub struct CameraOptions {
#[builder(default = DEFAULT_PEN_PX_SIZE)]
pub pen_px_size: f64,
#[builder(default = pen_px_size * DEFAULT_HATCH_PIXEL_SPACING_FACTOR)]
pub hatch_pixel_spacing: f64,
#[builder(default = pen_px_size / DEFAULT_HATCH_PIXEL_CHOP_QUOTIENT)]
pub hatch_pixel_chop_factor: f64,
#[builder(default = DEFAULT_HATCH_SLICE_FORGIVENESS)]
pub hatch_slice_forgiveness: usize,
#[builder(default = DEFAULT_VERT_HATCH_BRIGHTNESS_SCALING)]
pub vert_hatch_brightness_scaling: f64,
#[builder(default = DEFAULT_DIAG_HATCH_BRIGHTNESS_SCALING)]
pub diag_hatch_brightness_scaling: f64,
}

impl Default for CameraOptions {
fn default() -> Self {
Self::defaults_for_pen_px_size(4.0)
}
}

impl CameraOptions {
pub fn defaults_for_pen_px_size(px_size: f64) -> Self {
Self {
pen_px_size: px_size,
hatch_pixel_spacing: px_size * 2.0,
hatch_pixel_chop_factor: px_size / 3.0,
hatch_slice_forgiveness: 1,
vert_hatch_brightness_scaling: 0.8,
diag_hatch_brightness_scaling: 0.46,
}
Self::configure().build()
}
}

Expand Down
Loading

0 comments on commit 995f5d2

Please sign in to comment.