Skip to content

Conversation

@catilac
Copy link
Contributor

@catilac catilac commented Jan 9, 2026

This is one tiny attempt at a nicer API. It definitely needs flushing out, but I thought a bit about the example that @tychedelia had come up with in the discord Link

And created a little something that doesn't involve the user having to specify a Topology. This is just an idea, and needs some work.

That said, it's ready for review and can be merged in with approval.

box.rs and animated_mesh.rs have their counter python counterparts, so at least the bindings are in place.

@catilac catilac requested a review from tychedelia January 9, 2026 02:29
Comment on lines +40 to +44
global mesh
global grid_size
global offset
global spacing
global time
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't like that we have to keep doing this. i want to figure out a way to declare a variable in setup() and have it available in draw() automagically.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, i agree it's not the best. i think it would be nice if more things could be declared at module scope.

you could look at nannous api for one example, where we require the user to return an explicit state / model object from setup.

Comment on lines +15 to +36
for z in range(grid_size):
for x in range(grid_size):
px = x * spacing - offset
pz = z * spacing - offset
mesh.color(x/grid_size, 0.5, z/grid_size, 1.0)
mesh.normal(0.0, 1.0, 0.0)
mesh.vertex(px, 0.0, pz)

for z in range(grid_size-1):
for x in range(grid_size-1):
tl = z * grid_size + x
tr = tl + 1
bl = (z + 1) * grid_size + x
br = bl + 1

mesh.index(tl)
mesh.index(bl)
mesh.index(tr)

mesh.index(tr)
mesh.index(bl)
mesh.index(br)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically, i believe because of our awesome bevy system, this can all just go in draw() and it won't do more than it needs to. perhaps i'll move it back.

Comment on lines +46 to +51
pub fn new() -> PyResult<Self> {
let geometry = geometry_create(geometry::Topology::TriangleList)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
Ok(Self { entity: geometry })
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So...this is half baked. What happens when we want to pass in other topologies. Or do we create special classes for each geometry mesh type? hmm. this question shouldn't block us from a demo

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just us kwargs to overload the constructor? So by default you could do Mesh() or you could do Mesh(topology=TRIANGLE_STRIP). Something like that.

Copy link
Member

@tychedelia tychedelia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably also add the module-level beginGeometry API as well: https://p5js.org/reference/p5/beginGeometry/

But looks great otherwise!

global spacing
global time

camera_position(150.0, 150.0, 150.0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering that we might want camera to be it's own entity similar to p5: https://p5js.org/reference/p5/createCamera/

}

#[pyclass(unsendable)]
pub struct Mesh {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to call this Mesh but we should rename the object name in libprocessing core.

Comment on lines +46 to +51
pub fn new() -> PyResult<Self> {
let geometry = geometry_create(geometry::Topology::TriangleList)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
Ok(Self { entity: geometry })
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just us kwargs to overload the constructor? So by default you could do Mesh() or you could do Mesh(topology=TRIANGLE_STRIP). Something like that.

}

pub fn draw_box(&self, x: f32, y: f32, z: f32) -> PyResult<()> {
let box_geo = geometry_box(x, y, z).map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if we want the immediate mode 3d, we should probably just pre-cache the shapes in libprocessing render but this totally works for now.

.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn draw_mesh(&self, mesh: &Mesh) -> PyResult<()> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would like to bikeshed over this name a bit. p5.js calls this function model, which isn't the most intuitive name but is concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants