Skip to content

Commit

Permalink
play with Fornjot models in TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
ahdinosaur committed Mar 25, 2023
1 parent 7a0f3e5 commit 54cc260
Show file tree
Hide file tree
Showing 11 changed files with 1,078 additions and 778 deletions.
1,240 changes: 657 additions & 583 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "mycelia"
name = "sandkit"
version = "0.1.0"
edition = "2021"

Expand All @@ -10,6 +10,9 @@ anyhow = "1.0.70"
async-fs = "1.6.0"
deno_ast = { version = "0.25.0", features = ["transpiling"] }
deno_core = "0.175.0"
fj = { version = "0.41.0", features = ["serde"] }
fj-interop = "0.41.0"
fj-operations = "0.41.0"
futures-lite = "1.12.0"
nannou = "0.18.1"
kiss3d = "0.35.0"
serde = "1.0.158"
23 changes: 20 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
# mycelia
# sandkit

## run
A functional CAD playground to create and compose products.

_At the moment only a proof-of-concept for using [Fornjot](https://fornjot.app) in TypeScript_

Mad science for and by [Village Kit](https://villagekit.com).

## demo

```shell
cargo run --release
git clone https://github.com/villagekit/sandkit
cd sandkit
```

See model in [`./models/demo.ts`](./models/demo.ts).

```shell
cargo run
```

## license

Apache-2.0
67 changes: 67 additions & 0 deletions models/demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
export const params = [
{
name: 'outer',
type: 'number',
default: 1.0,
min: ({ inner }) => inner * 1.01,
},
{
name: 'inner',
type: 'number',
default: 0.5,
max: ({ outer }) => outer * 0.99,
},
{
name: 'height',
type: 'number',
default: 1.0,
},
]
export function shape(params: ParamValues) {
const { outer, inner, height } = params

const outerEdge = Sketch.fromCircle(Circle.fromRadius(outer))
const innerEdge = Sketch.fromCircle(Circle.fromRadius(inner))

const footprint = Difference2d.fromShapes(outerEdge, innerEdge)
const spacer = Sweep.fromPath(footprint, [0, 0, height])

console.log('JavaScript shape:', spacer)

return spacer
}

/* type helpers */

// TODO derive from param definition
interface ParamValues {
outer: number
inner: number
height: number
}

declare global {
export class Circle {
static fromRadius: (radius: number) => Circle
}
export class Sketch {
static fromCircle: (circle: Circle) => Sketch
}
interface Difference2dFromShapes {
(a: Sketch, b: Sketch): Difference2d
(a: Difference2d, b: Sketch): Difference2d
(a: Sketch, b: Difference2d): Difference2d
(a: Difference2d, b: Difference2d): Difference2d
}
export class Difference2d {
static fromShapes: Difference2dFromShapes
}
interface SweepFromPath {
(shape: Sketch, path: Array<number>): Sweep
(shape: Difference2d, path: Array<number>): Sweep
}
export class Sweep {
static fromPath: SweepFromPath
}
}

19 changes: 0 additions & 19 deletions sketches/demo.ts

This file was deleted.

95 changes: 0 additions & 95 deletions src/engine.rs

This file was deleted.

86 changes: 18 additions & 68 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,81 +1,31 @@
use anyhow::Error;
use deno_core::resolve_path;
use fj_operations::shape_processor::ShapeProcessor;
use futures_lite::future;
use nannou::draw::Draw;
use nannou::prelude::*;

mod engine;
mod loader;
mod model;
mod module;
mod viewer;

use crate::engine::Engine;

struct Model {
engine: Engine,
draw: Draw,
fps: Option<f32>,
}

fn main() {
nannou::app(model)
.event(event)
.update(update)
.simple_window(view)
.run();
}

fn model(app: &App) -> Model {
let draw = app.draw();
let mut engine = Engine::new(draw.clone());
use crate::model::ModelLoader;
use crate::viewer::Viewer;

fn main() -> Result<(), Error> {
let mut loader = ModelLoader::new();
let current_dir = std::env::current_dir().expect("Unable to get CWD");
let sketch_path = resolve_path("./sketches/demo.ts", &current_dir).unwrap();

future::block_on(engine.compile(sketch_path)).unwrap();

Model {
engine,
draw: draw.clone(),
fps: None,
}
}
let model_path = resolve_path("./models/demo.ts", &current_dir)?;

fn update(app: &App, model: &mut Model, _update: Update) {
let draw = &model.draw;
future::block_on(loader.load(model_path))?;

draw.reset();
draw.background().color(BLUE);
let shape = future::block_on(loader.get_shape())?;
let shape_processor = ShapeProcessor { tolerance: None };
let processed_shape = shape_processor.process(&shape)?;

future::block_on(model.engine.run(app.time)).unwrap();
let mut viewer = Viewer::new(processed_shape)?;

/*
let n = 5000;
let t = app.time * 0.1;
for i in 0..n {
let a = i as f32 / n as f32;
let b = (a + t) % 1.0;
let x = (b * PI * 16.0).sin() * 500.0 * a;
let y = (b * PI * 16.0).cos() * 500.0 * a;
draw.rect().x_y(x, y).w_h(4.0, 4.0).color(PLUM);
while viewer.render() {
viewer.step()
}
*/

match model.fps {
Some(fps) => model.fps = Some((app.fps() + fps) / 2.0),
None => model.fps = Some(app.fps()),
}
}

fn event(_app: &App, _model: &mut Model, _event: Event) {}

fn view(app: &App, model: &Model, frame: Frame) {
let draw = &model.draw;

let fps = model.fps.unwrap_or(0.0).round();

let win = app.window_rect();
let win_p = win.pad(25.0);

let rect = Rect::from_w_h(0.0, 0.0).top_left_of(win_p);
draw.text(&fps.to_string()).xy(rect.xy()).font_size(20);

draw.to_frame(app, &frame).unwrap();
Ok(())
}
Loading

0 comments on commit 54cc260

Please sign in to comment.