0.5.0 • Published 2 years ago

differential-growth-rs-wasm v0.5.0

Weekly downloads
-
License
MIT OR Apache-2.0
Repository
github
Last release
2 years ago

Differential Line Growth with Rust WASM

A WebAssembly wrapper around a Rust implementation of the differential growth algorithm.

example gif

As you can see its blazingly fast.

Example

A full example available online here(and its repo) and is provided in the source code's /www directory. Run it using:

cd www && npm init && npm start

You can play around with the input variables using dat.gui and export the result to SVG.

Usage

The package is build using wasm-pack build --target web so it can be used with native javascript modules instead of needing a bundler. More info in the wasm-bindgen docs here and here, and in the wasm-pack docs here. This is done in order to enable development using Vite.

At the time of development WASM and Javascript can only communicate using basic types. The array of point coordinates is represented as a flattened array of numbers when it is returned or passed as a function argument. Manual conversion to and from an array of points is necessary.

// Since we use `--target web`, manual initialisation of the WebAssembly module is required.
import init, {
  DifferentialGrowthWasm,
  generate_points_on_circle,
} from "differential-growth-rs-wasm";

// Initialise WASM
await init();

// Using the included helper function to generate point on a circle.
let starting_points = generate_points_on_circle(
        200, // origin_x
        200, // origin_y
        10.0, // radius
        10 // amount of points
      );

// Instatiate differential growth object
let rustDifferentialGrowth = new DifferentialGrowthWasm(
    starting_points,
    1,5, // maxForce
    1.0, // maxSpeed
    14, // desiredSeparation
    1.1, // separationCohesionRatio
    5.0 // maxEdgeLength
);

// Advance the algorithm by a single iteration.
rustDifferentialGrowth.tick();

// Either let WASM render the result to a canvas.
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext('2d');
rustDifferentialGrowth.render(
    ctx,
    canvas.width,
    canvas.height,
);

// or get the array of coordinates and render yourself.
// don't forget to convert array of numbers to array of vectors.
let points = rustDifferentialGrowth.export_as_slice();      

The choice of algorithm parameters is a very important factor to achieving a desirable result.

Developing

Compile rust (execute manually after file changes):

In the project root:

wasm-pack build --target web

Run development server

In the /www folder:

npm init
npm start

References

Notes

failed optimisations:

  • Letting Javascript access wasm's linear memory for the point's coordinates actually decreases perfomance. That is why I pass a boxed slice.
  • Moving requestAnimationFrame to wasm does not improve performance.