Releases: mkeeter/fidget
v0.4.0
Splitting into multiple crates
The focus of this release is splitting fidget into a set of smaller crates, for improved compile times and modularity. This brings a clean build of fidget (time cargo build --release -pfidget) down from 60 to 45 seconds on my laptop, a significant improvement!
For the most part, this should be transparent: each smaller crate is re-exported by the fidget root crate. However, a few things got moved around to improve modularity:
- Image (bitmap and heightmap) rendering is moved from
fidget::renderto a separatefidget::rastermodule. Anything which was used by both image and mesh rendering remains infidget::render. View2andView3have moved tofidget::gui
The helper crates can be enabled with fine-grained features on the root fidget crate, for use cases where a smaller fidget is helpful.
Other changes
- Return
DoubleEndedIteratorfromRegTape::iter()andSsaTape::iter(), making it easier to iterate in reverse order. - Tighter interval bounds on
sinandcos(thanks @alexneufeld)
v0.3.9
This release fixes a bunch of small issues encountered while building a design tool on top of the Fidget kernel.
- Fix panic in tape construction if a multi-output expression has a constant as an output.
- Add
Function::can_simplifyto check whether aFunctioncan ever be simplified (if not, then interval evaluation isn't as useful). - Fix invalid access when doing bulk evaluation on a
Functionwith more than one output. This caused a panic using the VM evaluator, and a segfault (typically) using the JIT evaluator. - Make
PartialEqforTreeobjects do deep comparisons, instead of shallow (pointer) equality- This is more expensive, but matches typical data structures in Rust
Tree::ptr_eqcan be used to perform shallow equality checks
- Changed 3D image rendering to saturate when voxels are touching the camera. Saturated voxels snap to the image's depth and have a normal of
[0, 0, 1]. - Replaced
viewinImageRenderConfig,VoxelRenderConfig, andmesh::Settingswith a genericworld_to_modelmatrix, for more flexibility when rendering. - Add mathematical constants for Rhai scripts (
PI,E,TAU...) - Add
std::ops::Negimplementation forVec2,3,4types, in both Rust and Rhai. - Remove
Shape::apply_transform; there were too many ways to apply transforms to shapes, and having mutable operations on a handle passed byCloneopens up possibilities for confusion. Here's the new plan:- When using high-level algorithms (e.g. meshing and rendering), the world-to-model transform is now only set by the
world_to_modelmatrix in the config or settings object (ImageRenderConfig,VoxelRenderConfig,mesh::Settings) - When using a
Shapedirectly, a transform can be set withShape::with_transform. This returns a newShape<F, Transformed>, whereTransformedis a marker type indicating that the transform field isSome(..).Shape::with_transformis a one-way operation: it's only available onShape<F>(which is actually nowShape<F, ()>). Note that high-level operations require aShape<F, ()>, because they set the transform themselves!
- When using high-level algorithms (e.g. meshing and rendering), the world-to-model transform is now only set by the
- Add
vec2([..])andvec3([..])functions to Rhai environment - Fix
remap_affinecomposition; previously, it applied operations in the wrong order given multiple affine transformations. - New shapes:
Rectangle,Box,Rotate(X|Y|Z),Blend,Plane,ScaleUniform,RevolveY,ExtrudeZ,LoftZ - Added ordered constructors to Rhai bindings, e.g.
rectangle([0,0], [1,1]). These are only available if a previous constructor didn't use the same function prototype. - Added
cancel: CancelTokentofidget::mesh::SettingsOctree::buildnow returns anOption<..>, which isNoneif it was cancelled
- Removed
SettingsfromOctree::walk_dual, because we aren't actually doing any multithreading - Switched various mesh functions to take
Settingsby reference instead of by value, becauseCancelTokenis notCopy. - Make Rhai
vec2(..)andvec3(..)functions idempotent, i.e.vec2(vec2(..))now works. - Optimize
atan2interval evaluation
v0.3.8
This release focuses heavily on Rhai ergonomics, improving the standard library and making it easier to write scripts.
There are a bunch of other fixes and improvements as well; see the detailed log below or details!
- Bug fix:
Image::height()was returning width instead! - Add
#[derive(PartialEq)]toView2andView3 - Improve rendering at small images sizes
- Previously, we rendered at least one tile of size
cfg.tile_sizes[0] - Now, we pick the smallest possible tile size for the root tiles; if we're rendering a 32×32 image with tile sizes of
[128, 32, 8], then we'll render a single 32×32 tile (instead of 128×128) - As part of this change, a few functions were removed from the
TileSizespublic API; they're now attached to an internalstruct TileSizesRef.
- Previously, we rendered at least one tile of size
- Add a new
trait ShapeVisitorandpub fn visit_shapes(..)for introspection into shapes and transforms defined in theshapesmodule. This is expected to be useful for automatically generated scripted bindings (indeed,fidget::rhainow uses it). - Added more document to
fidget::shapes - Made
fidget::rhai::shapes::register_shapeprivate - Significant changes to 2D rendering API:
- Changed
fidget::render::render2dto always return anImage<DistancePixel>, which encodes either a distance sample or details on fill at that point. - Removed the
trait RenderMode, which was previously used to generate pixel samples from a distance field. - Added
ImageRenderConfig::pixel_perfect, which forces sampling down to individual pixels. - Added
fidget::render::effects::{to_rgba_bitmap, to_debug_bitmap, to_rgba_distance}to post-process anImage<DistancePixel>. These replace the previousRenderModeobjects for generating specific flavors of image. - Note that approximate SDFs are entirely removed; they were not substantially faster, added complexity, and looked bad.
- Changed
- Add
#[facet(default = ...)]annotations to relevant fields in
fidget::shapes.- These annotations are used in the Rhai bindings to build shapes without specifying every field, e.g.
circle(1)leaves the center as a default value.
- These annotations are used in the Rhai bindings to build shapes without specifying every field, e.g.
- Fix issue where
Shape::eval_*functions would return an empty slice if there were no active variables in the shape; it now returns a slice that's the correct size (i.e. matching the input slices). - In Rhai bindings,
FromDynamicnow takes the field's default value as a hint, which may be used when promoting other types. For example, if you pass avec2(instead of avec3) to bothMoveandScale, thezcomponent will be set to 0 forMoveand 1 forScale. - Add helper functions to destructure and rebuild
Canvas2,Canvas3,View2, andView3into their component values. - Rename
fidget::{shapes, rhai}::vectofidget::{shapes, rhai}::types - Add more common types used in shapes and Rhai bindings:
Axisis a unitVec3Planeis anAxisand offset
- Add
Reflectshape, as well asReflectX/Y/Z - Removed
fidget::rhai::Engineandfidget::rhai::Axes- Previously,
fidget::rhai::Enginewrapped a Rhai engine and Fidget-specific functionality - The internals of
Enginewere tightly coupled tofidget-viewer, in ways that weren't useful for other GUIs. - Now,
fidget::rhai::engine()returns arhai::Engineobject with Fidget types pre-installed, but without the wrapper type. - The Rhai
draw(..)anddraw_rgb(..)functions are moved intofidget-viewer, because they're specific to that one GUI (fidget-cliis also aware ofdraw, but now has its own simpler implementation).
- Previously,
- Move
Vec2/3/4,Axis,Planeintofidget::shapes::typesinstead of re-exporting them infidget::shapes. - Make
fidget::shapes::types::{Value, Type}public; these represent types which can be used in shapes (with ergonomic Rhai bindings). - Fix missing local optimizations in
Context::import(e.g.x * 0 => 0) - Rename
remap_xyz(..)to justremap(..)in Rhai bindings; add a two-argument version which leaveszunchanged
v0.3.7
- Small release to fix an issue with 0.3.6 being published with invalid local changes (I thought
cargoprevented this, dunno how it happened) - Mark functions on
IntervalandGradas#[inline], to improve performance when those types are used outside of the Fidget crate itself. - Make
fidget::rhaisubmodules visible (vec,shape,tree) for finer-grained usage outside of Fidget. - Update to Rust 2024 edition, set minimum
rustcversion to 1.87 - Update dependencies; remove some that have become unused
v0.3.6
- Change
Option<ThreadPool<'a>>toOption<&'a ThreadPool>throughout the codebase; moving the reference out of theThreadPooleliminates the need for a separaterayon::ThreadPoolobject on the stack. - Significant rewrite of meshing! It now uses the same
Option<&ThreadPool>type and is multithreaded using Rayon, meaning it can work in WebAssembly. - Changed 3D rendering and effects functions to use a new
GeometryBuffertype, which combines depth and normal data into a single image. - Add
fidget::guimodule, which definesCanvas2andCanvas3. The canvas types are stateful abstractions around a GUI canvas, with support for cursor interactions. - Change
ImageSize::transform_pointandVoxelSize::transform_pointto take a point withi32coordinates (instead off32). This helps us distinguish between screen (pixel) and world (floating-point) coordinates at the type level. - Add
Tree::remap_affine(andTreeOp::RemapAffine) to perform affine transformations on math expressions. These transformations are composable; two affine transforms will be combined into a single transform if stacked together. - Major updates to the Rhai standard library and default bindings:
- Add
vec2,vec3,vec4types - Shapes are now constructed with object maps
- Added documentation in
fidget::rhai::docsmodule
- Add
- Significant rewrite of meshing! It now uses the same
Option<&ThreadPool>type and is multithreaded using Rayon, meaning it can work in WebAssembly. - Changed 3D rendering and effects functions to use a new
GeometryBuffertype, which combines depth and normal data into a single image. - Add
fidget::guimodule, which definesCanvas2andCanvas3. The canvas types are stateful abstractions around a GUI canvas, with support for cursor interactions. - Change
ImageSize::transform_pointandVoxelSize::transform_pointto take a point withi32coordinates (instead off32). This helps us distinguish between screen (pixel) and world (floating-point) coordinates at the type level. - Add
Tree::remap_affine(andTreeOp::RemapAffine) to perform affine transformations on math expressions. These transformations are composable; two affine transforms will be combined into a single transform if stacked together. - Major updates to the Rhai standard library and default bindings:
- Add
vec2,vec3,vec4types - Shapes are now constructed with object maps
- Added documentation in
fidget::rhai::docsmodule
- Add
v0.3.5
- Added
#[derive(Serialize, Deserialize)]toView2andView3 - Make
TranslateHandletake aconst N: usizeparameter - Use
TranslateHandleinView2(previously, it was only used inView3) - Make
translateandrotatefunctions borrow their respective handle, instead of taking it by value. - Fix docstring for
AndRegImm,AndRegReg,OrRegImm, andOrRegReg - Add
cancel: CancelTokento 2D and 3D rendering configuration objects; this is a sharedArc<AtomicBool>which can be used to stop rendering. The returned type is now anOption<...>, whereNoneindicates that rendering was cancelled. - Fix inconsistency between JIT and VM evaluator when performing interval evaluation of
not([NAN, NAN]). - Propagate
NANvalues throughandandoroperations on intervals. - Add a new
Image<P>generic image type (wrapping aVec<P>,width, andheight).- Define
DepthImage,NormalImage, andColorImagespecializations - Use these types in 2D and 3D rendering
- Define
- Remove
Grad::to_rgbin favor of handling it at the image level - Add
fidget::render::effectsmodule for post-processing rendered images:- Combining depth and normal images into a shaded image
- Denoising normals to fix back-facing samples
- Computing and applying screen-space ambient occlusion
- Optimize implementation of interval
modulofor cases where the right-hand argument is a positive constant value (which is the most common when using it for domain repetition) - Update many dependencies to their latest versions
getrandom#504, crates which use Fidget as a library and compile to WebAssembly must select a getrandom backend.
This can be done either on the command line (RUSTFLAGS='--cfg getrandom_backend="wasm_js"') or in a .cargo/config.toml configuration file (e.g. this file in Fidget itself).
v0.3.4
- Add
GenericVmFunction::simplify_withto simultaneously simplify a function and pick a new register count for the resulting tape - Add bidirectional conversions between
JitFunctionandGenericVmFunction(exposing the inner data member) - Add a new
TileSizes(Vec<usize>)object representing tile sizes used during rendering. Unlike the previousVec<usize>, this data type checks our tile size invariants at construction. It is used in thestruct RenderConfig. - Rethink rendering and viewport configuration:
- Add a new
RegionSize<const N: usize>type (withImageSizeandVoxelSizealiases), representing a render region. This type is responsible for the screen-to-world transform - Add
View2andView3types, which stores the world-to-model transform (scaling, panning, etc) - Image rendering uses both
RegionSizeandViewX; this means that we can now render non-square images! - Meshing uses just a
View3, to position the model within the ±1 bounds - The previous
fidget::shape::Boundstype is removed - Remove
fidget::render::render2d/3dfrom the public API, as they're equivalent to the functions onImageRenderConfig/VoxelRenderConfig
- Add a new
- Move
RenderHintsintofidget::render - Remove fine-grained features from
fidgetcrate, because we aren't actually testing the power-set of feature combinations in CI (and some were breaking!). The only remaining features arerhai,jitandeval-tests. - Add new
ShapeVars<T>type, representing a map fromVarIndex -> T. This type is used for high-level rendering and meshing ofShapeobjects that include supplementary variables - Add
Octree::build_with_varsandImage/VoxelRenderConfig::run_with_varsfunctions for shapes with supplementary variables - Change
ShapeBulkEval::eval_vto take single variables (i.e.x,y,zvary but each variable has a constant value across the whole slice). AddShapeBulkEval::eval_vsifx,y,zand variables are all changing through the slices. - Add a new
GenericVmTape<N>type, and use it for VM evaluation. Previously, theGenericVmFunction<N>type implemented bothTapeandFunction. - Add
vars()toFunctiontrait, because there are cases where we want to get the variable map without building a tape (and it must always be the same). - Fix soundness bug in
Mmap(probably not user-visible) - Add
Send + Sync + Clonebounds to thetrait Tape, to make them easily shared between threads. Previously, we used anArc<Tape>to share tapes between threads, but tapes were already using anArc<..>under the hood. - Changed
Tape::recyclefrom returning aStorageto returning anOption<Storage>, as tapes may now be shared between threads. - Use Rayon for 2D and 3D rasterization
- The
threadsmember ofVoxelRenderConfigandImageRenderConfigis now aOption<ThreadPool>, which can beNone(use a single thread),Some(ThreadPool::Global)(use the global Rayon pool), orSome(ThreadPool::Custom(..))(use a user-provided pool) - This is a step towards WebAssembly multithreading, using
wasm-bindgen-rayon. ThreadCountis moved tofidget::mesh, because that's the only place it's now used- The plan is to switch to Rayon for meshing as well, eventually
- The
- Tweak
View2andView3APIs to make them more useful as camera types
v0.3.3
This release adds multiple outputs to the low-level math and function traits. The high-level Shape object has not changed, although internally it now checks that it's wrapping a single-output Function.
Functionand evaluator types now produce multiple outputsMathFunction::newnow takes a slice of nodes, instead of a single node- All of the intermediate tape formats (
SsaTape, etc) are aware of multiple output nodes - Evaluation now returns a slice of outputs, one for each root node (ordered based on order in the
&[Node]slice passed toMathFunction::new)
RegisterAllocatorno longer binds SSA register 0 to physical register 0 by default. If you don't know what this means, don't worry about it.
v0.3.2
This release adds symbolic differentiation, along with more ergonomic improvements.
- Added
impl IntoNode for Var, to make handlingVarvalues in a context easier. - Added
impl From<TreeOp> for Treefor convenience - Added
Context::export(&self, n: Node) -> Treeto make a freestandingTreegiven a context-specificNode. - Fix possible corruption of
x24during AArch64 float slice JIT evaluation, due to incorrect stack alignment. - Added
Context::derivandTree::derivto do symbolic differentiation of math expressions.
v0.3.1
The highlight of this release is the fidget::solver module, which implements the Levenberg-Marquardt algorithm to minimize a system of equations (represented as fidget::eval::Function objects). It's our first official case of using Fidget's types and traits for things other than pure implicit surfaces!
Detailed changelog below:
- Fixed a bug in the x86 JIT which could corrupt registers during gradient (
grad_slice) evaluation - Renamed
Context::const_valuetoContext::get_constand tweaked its return type to matchContext::get_var. - Added
impl From<i32> for Treeto make writing tree expressions easier - Removed
Error::ReservedNameandError::DuplicateName, which were unused - Add the
fidget::solvermodule, which contains a simple solver for systems of equations. The solver requires the equations to implement Fidget'sFunctiontrait. It uses both point-wise and gradient evaluation to solve for a set ofVarvalues, using the Levenberg-Marquardt algorithm. - Add
Tree::var()andimpl TryFrom<Tree> for Var