Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions crates/processing_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,64 @@ pub unsafe extern "C" fn processing_image_readback(
Ok(())
});
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_mode_3d(window_id: u64) {
error::clear_error();
let window_entity = Entity::from_bits(window_id);
error::check(|| graphics_mode_3d(window_entity));
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_mode_2d(window_id: u64) {
error::clear_error();
let window_entity = Entity::from_bits(window_id);
error::check(|| graphics_mode_2d(window_entity));
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_camera_position(window_id: u64, x: f32, y: f32, z: f32) {
error::clear_error();
let window_entity = Entity::from_bits(window_id);
error::check(|| graphics_camera_position(window_entity, x, y, z));
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_camera_look_at(
window_id: u64,
target_x: f32,
target_y: f32,
target_z: f32,
) {
error::clear_error();
let window_entity = Entity::from_bits(window_id);
error::check(|| graphics_camera_look_at(window_entity, target_x, target_y, target_z));
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_perspective(
window_id: u64,
fov: f32,
aspect: f32,
near: f32,
far: f32,
) {
error::clear_error();
let window_entity = Entity::from_bits(window_id);
error::check(|| graphics_perspective(window_entity, fov, aspect, near, far));
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_ortho(
window_id: u64,
left: f32,
right: f32,
bottom: f32,
top: f32,
near: f32,
far: f32,
) {
error::clear_error();
let window_entity = Entity::from_bits(window_id);
error::check(|| graphics_ortho(window_entity, left, right, bottom, top, near, far));
}
37 changes: 37 additions & 0 deletions crates/processing_pyo3/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,43 @@ impl Graphics {
pub fn end_draw(&self) -> PyResult<()> {
graphics_end_draw(self.entity).map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn mode_3d(&self) -> PyResult<()> {
graphics_mode_3d(self.entity).map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn mode_2d(&self) -> PyResult<()> {
graphics_mode_2d(self.entity).map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn camera_position(&self, x: f32, y: f32, z: f32) -> PyResult<()> {
graphics_camera_position(self.entity, x, y, z)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn camera_look_at(&self, target_x: f32, target_y: f32, target_z: f32) -> PyResult<()> {
graphics_camera_look_at(self.entity, target_x, target_y, target_z)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn perspective(&self, fov: f32, aspect: f32, near: f32, far: f32) -> PyResult<()> {
graphics_perspective(self.entity, fov, aspect, near, far)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

#[allow(clippy::too_many_arguments)]
pub fn ortho(
&self,
left: f32,
right: f32,
bottom: f32,
top: f32,
near: f32,
far: f32,
) -> PyResult<()> {
graphics_ortho(self.entity, left, right, bottom, top, near, far)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}
}

// TODO: a real color type. or color parser? idk. color is confusing. let's think
Expand Down
163 changes: 163 additions & 0 deletions crates/processing_render/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,169 @@ pub fn resize(
}
}

pub fn mode_3d(
In(entity): In<Entity>,
mut projections: Query<&mut Projection>,
mut transforms: Query<&mut Transform>,
sizes: Query<&SurfaceSize>,
) -> Result<()> {
let SurfaceSize(width, height) = sizes
.get(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;

let width = *width as f32;
let height = *height as f32;

let fov = std::f32::consts::PI / 3.0; // 60 degrees
let aspect = width / height;
let camera_z = (height / 2.0) / (fov / 2.0).tan();
let near = camera_z / 10.0;
let far = camera_z * 10.0;

let mut projection = projections
.get_mut(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;

*projection = Projection::Perspective(PerspectiveProjection {
fov,
aspect_ratio: aspect,
near,
far,
});

let mut transform = transforms
.get_mut(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;

*transform = Transform::from_xyz(0.0, 0.0, camera_z).looking_at(Vec3::ZERO, Vec3::Y);

Ok(())
}

pub fn mode_2d(
In(entity): In<Entity>,
mut projections: Query<&mut Projection>,
mut transforms: Query<&mut Transform>,
sizes: Query<&SurfaceSize>,
) -> Result<()> {
let SurfaceSize(width, height) = sizes
.get(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;

let mut projection = projections
.get_mut(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;

*projection = Projection::custom(ProcessingProjection {
width: *width as f32,
height: *height as f32,
near: 0.0,
far: 1000.0,
});

let mut transform = transforms
.get_mut(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;

*transform = Transform::from_xyz(0.0, 0.0, 999.9);

Ok(())
}

pub fn camera_position(
In((entity, x, y, z)): In<(Entity, f32, f32, f32)>,
mut transforms: Query<&mut Transform>,
) -> Result<()> {
let mut transform = transforms
.get_mut(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;

transform.translation = Vec3::new(x, y, z);

Ok(())
}

pub fn camera_look_at(
In((entity, target_x, target_y, target_z)): In<(Entity, f32, f32, f32)>,
mut transforms: Query<&mut Transform>,
) -> Result<()> {
let mut transform = transforms
.get_mut(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;

// TODO: allow specifying up vector?
// does anyone actually use anything other than Vec3::Y here?
let target = Vec3::new(target_x, target_y, target_z);
transform.look_at(target, Vec3::Y);

Ok(())
}

pub fn perspective(
In((
entity,
PerspectiveProjection {
fov,
aspect_ratio,
near,
far,
},
)): In<(Entity, PerspectiveProjection)>,
mut projections: Query<&mut Projection>,
) -> Result<()> {
let mut projection = projections
.get_mut(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;

*projection = Projection::Perspective(PerspectiveProjection {
fov,
aspect_ratio,
near,
far,
});

Ok(())
}

pub struct OrthoArgs {
pub left: f32,
pub right: f32,
pub bottom: f32,
pub top: f32,
pub near: f32,
pub far: f32,
}

pub fn ortho(
In((
entity,
OrthoArgs {
left,
right,
bottom,
top,
near,
far,
},
)): In<(Entity, OrthoArgs)>,
mut projections: Query<&mut Projection>,
) -> Result<()> {
let mut projection = projections
.get_mut(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;

// we need a custom projection to support processing's coordinate system
// but this is in effect an orthographic projection with the given bounds
*projection = Projection::custom(ProcessingProjection {
width: right - left,
height: top - bottom,
near,
far,
});

Ok(())
}

pub fn destroy(
In(entity): In<Entity>,
mut commands: Commands,
Expand Down
107 changes: 107 additions & 0 deletions crates/processing_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use bevy::{
use render::{activate_cameras, clear_transient_meshes, flush_draw_commands};
use tracing::debug;

use crate::graphics::flush;
use crate::{
graphics::GraphicsPlugin, image::ImagePlugin, render::command::DrawCommand,
surface::SurfacePlugin,
Expand Down Expand Up @@ -445,6 +446,112 @@ pub fn graphics_record_command(graphics_entity: Entity, cmd: DrawCommand) -> err
})
}

pub fn graphics_mode_3d(graphics_entity: Entity) -> error::Result<()> {
app_mut(|app| {
flush(app, graphics_entity)?;
app.world_mut()
.run_system_cached_with(graphics::mode_3d, graphics_entity)
.unwrap()
})
}

pub fn graphics_mode_2d(graphics_entity: Entity) -> error::Result<()> {
app_mut(|app| {
flush(app, graphics_entity)?;
app.world_mut()
.run_system_cached_with(graphics::mode_2d, graphics_entity)
.unwrap()
})
}

pub fn graphics_camera_position(
graphics_entity: Entity,
x: f32,
y: f32,
z: f32,
) -> error::Result<()> {
app_mut(|app| {
flush(app, graphics_entity)?;
app.world_mut()
.run_system_cached_with(graphics::camera_position, (graphics_entity, x, y, z))
.unwrap()
})
}

pub fn graphics_camera_look_at(
graphics_entity: Entity,
target_x: f32,
target_y: f32,
target_z: f32,
) -> error::Result<()> {
app_mut(|app| {
flush(app, graphics_entity)?;
app.world_mut()
.run_system_cached_with(
graphics::camera_look_at,
(graphics_entity, target_x, target_y, target_z),
)
.unwrap()
})
}

pub fn graphics_perspective(
graphics_entity: Entity,
fov: f32,
aspect_ratio: f32,
near: f32,
far: f32,
) -> error::Result<()> {
app_mut(|app| {
flush(app, graphics_entity)?;
app.world_mut()
.run_system_cached_with(
graphics::perspective,
(
graphics_entity,
PerspectiveProjection {
fov,
aspect_ratio,
near,
far,
},
),
)
.unwrap()
})
}

#[allow(clippy::too_many_arguments)]
pub fn graphics_ortho(
graphics_entity: Entity,
left: f32,
right: f32,
bottom: f32,
top: f32,
near: f32,
far: f32,
) -> error::Result<()> {
app_mut(|app| {
flush(app, graphics_entity)?;
app.world_mut()
.run_system_cached_with(
graphics::ortho,
(
graphics_entity,
graphics::OrthoArgs {
left,
right,
bottom,
top,
near,
far,
},
),
)
.unwrap()
})
}

/// Create a new image with given size and data.
pub fn image_create(
size: Extent3d,
Expand Down