# Introducing Pmetra: Parametric Modelling for Bevy with Truck CAD

A few weeks ago, I released "[Pmetra](https://github.com/nilaysavant/bevy_pmetra)" - a parametric modelling [*plugin*](https://docs.rs/bevy/latest/bevy/app/trait.Plugin.html) for the [Bevy Engine](https://bevyengine.org/) using the [Truck CAD kernel](https://github.com/ricosjp/truck).

> Pmetra allows developers to generate 3D models **parametrically** using Truck's CAD [APIs](https://ricos.gitlab.io/truck-tutorial/v0.1/modeling.html#cube). In short, you define a set of parameters (e.g., `side_length`, `array_count`), connect them with CAD logic (generating BREP [Shells](https://docs.rs/truck-topology/0.5.0/truck_topology/struct.Shell.html)), and Pmetra will generate the [meshes](https://docs.rs/bevy/latest/bevy/prelude/struct.Mesh.html#) for you in *real-time*! (Check out this 👉 [simple cube example](https://github.com/nilaysavant/bevy_pmetra?tab=readme-ov-file#create-simple-parametric-cube))
> 
> Additionally, you can set up "[sliders](https://github.com/nilaysavant/bevy_pmetra?tab=readme-ov-file#pmetrainteractions)" that let you manipulate the model in a ***smooth*** and ***continuous*** way. These sliders simply adjust the underlying parameters. They allow developers to experiment and also provide this feature to their users, unlocking different workflows or mechanics.

Building this was quite a journey! It all began with my desire to ship games with 3D models on the web. I realised that downloading 3D assets during page load would be too much for a reasonably sized game. Introduced to [procedural generation](https://en.wikipedia.org/wiki/Procedural_generation), I was inspired by games like "[Tiny Glade](https://store.steampowered.com/app/2198150/Tiny_Glade/)" (for the smooth interactions) and more recently "[Satisfactory](https://www.satisfactorygame.com/)" (which would be an ideal use case for this)! My obsession with building using pure code was longing for something like this. [`bevy_mesh_drawing`](https://github.com/nilaysavant/bevy_mesh_drawing) was my first attempt at it. I finally found Truck and it was a holy grail. An open source [CAD](https://en.wikipedia.org/wiki/Geometric_modeling_kernel) kernel?! This was it, time to build!

I started with a few goals in mind: *smooth* and *continuous* interactions, and automation with a few *parameters*. I began working on a proof of concept. The first version of "Parametric CAD Modelling", which I almost abandoned after a month of development, was *synchronous*, *blocking*, and *slow*, and **it would never scale**. From its ashes, rose a phoenix; an entirely rewritten, *smooth*, *asynchronous*, *non-blocking version* emerged: "Pmetra" that you see today!

The first proof-of-concept version of the plugin had the mesh generation written in a *single function call* at the top level. It would return the resulting **shells**, **meshes** and **sliders**. This setup was necessary to ensure *predictability* and *synchronicity*, allowing for smooth model manipulation and interactive sliders. Once it worked as expected, I decided to improve performance. I discovered that the biggest bottleneck was the [**tessellation**](https://en.wikipedia.org/wiki/Tessellation_(computer_graphics)) (algorithm/module that converts [BREP](https://en.wikipedia.org/wiki/Boundary_representation) Shells/Solids to triangle meshes). Since this process was happening synchronously, I began exploring ways to make it **run in the background**.

But this was not as easy as I had thought. Some of my previous decisions, like using **sliders**, relied on meshes being *generated beforehand* in a *predictable* way. I decided to change the architecture so that sliders were generated purely based on the BREP **shell** and **parameters**, with no dependency on meshes. This allowed them to be generated in *parallel* and in the *background* using an [Async Task Pool](https://docs.rs/bevy_async_task/latest/bevy_async_task/struct.AsyncTaskPool.html). This change *boosted* the overall FPS while manipulating meshes, **leaving it unaffected at times**! It was a key learning experience!

Now it all came down to my ability to demonstrate this. I created a few more [examples](https://github.com/nilaysavant/bevy_pmetra/tree/master/pmetra_demo/src/utils/cad_models), as you can see in the [demo](https://pmetra.nilay.cc/), and set up compiling to WASM for web deployment. A [readme](https://github.com/nilaysavant/bevy_pmetra/tree/master?tab=readme-ov-file#create-simple-parametric-cube) with a [simple example](https://github.com/nilaysavant/bevy_pmetra/blob/master/examples/simple_cube.rs) to get started, along with more sophisticated ones in the demo, was all that was needed for the first release. It was ready to go! 🚀

I finally open-sourced it after some initial testing and posted about it on [Twitter](https://twitter.com/nilay_savant/status/1787844960277934305). It turned out to be my most liked post ever! I received support from key players in the Bevy community and top folks in the 3D space, like [mrdoob](https://twitter.com/mrdoob), the creator of [ThreeJS](https://threejs.org/)!

A pet project has led people to me with ideas for building a **CAD software**/**parametric engine**! Big shoutout to **Truck** for becoming one of the underrated yet [upcoming](https://arc.net/l/quote/eicxwgpi) open-source CAD kernels!

I'm not an expert, and I'm sure mistakes have been made. I would love feedback and suggestions to improve this! Let's work together to make CAD accessible and building an even more exciting version of Satisfactory easier! 🍻

🌐 Pmetra live demo: [https://pmetra.nilay.cc/](https://pmetra.nilay.cc/)  
👉 Github: [https://github.com/nilaysavant/bevy\_pmetra](https://github.com/nilaysavant/bevy_pmetra)
