deadsy / sdfx

A simple CAD package using signed distance functions
MIT License
518 stars 52 forks source link

New development renderer (UI) for SDF2 and SDF3 #45

Closed Yeicor closed 2 years ago

Yeicor commented 2 years ago

This merge creates a new package capable of rendering any SDF2 or SDF3 to a window with control over the camera and other settings, and updating the surface automatically when the new code is saved. While writing this package I realized that I only use the public API of SDFX; so maybe it should be committed to its own repository (sdfx-ui) which can then become a full editor if there is enough interest. What do you think @deadsy?

I provide a more detailed explanation below. TL;DR: See demo at the end.

Renderer is a SDF2/SDF3 renderer intended for fast development iterations that renders directly to a window. The first time, it starts the renderer process. It also starts listening for code changes. When a code change is detected, the app is recompiled (taking advantage of go's fast compilation times) by the renderer and communicates directly to the renderer, providing the new surface data to the previous window.

It allows very fast SDF updates (saving camera position, etc.) whenever the code changes, speeding up the modelling process. The renderer is mainly CPU-based (with a resolution parameter to control speed vs quality), as SDFX is also CPU-based. The scene is only rendered when something changes, as rendering SDFs with good quality is fast but not real-time.

The SDF2 renderer is based on the PNG renderer, showing the image directly on screen (without creating the PNG file). The camera can be moved and scaled (using the mouse), rendering only the interesting part of the SDF.

SDF3s are raycasted from a perspective arc-ball camera that can be rotated around a pivot point, move its pivot and move closer or farther away from the pivot (using Blender-like mouse controls). Note that only the shown surface is actually rendered thanks to raycasting from the camera. This also means that the resulting surface can be much more detailed (depending on chosen resolution) than the triangle meshes generated by standard renderers.

It uses ebiten for rendering, which is cross-platform, so it could also be used to showcase a surface (without automatic updates) creating an application for desktop, web or mobile.

Demo

Configuring the Renderer is as simple as:

dev.NewRenderer(anySDF).Run()

The package will handle rendering, recompilation, IPC, etc. NewDevRenderer also accepts several optional configuration parameters to customize the behavior (dev.Opt*).

https://user-images.githubusercontent.com/4929005/148616538-1251b1ed-0ae4-40a2-bbf0-c1b930580882.mp4

Browser and mobile

Note that mobile only works with mouse and keyboard for now (otherwise the user can only view a static render of the surface).

Screenshot_20220107_234547 Screenshot_20220107-234815220

Note: the .wasm file takes 13.5MiB (no compression) and android's APK takes 48MiB.

gedw99 commented 2 years ago

Using ebiten is a great idea. I was just thinking about how to build a GUI client too.

Will pull and try this out.

gedw99 commented 2 years ago

@Yeicor Cant see a main.go that wires the render/dev up. Can you let me know so i can test this...

Yeicor commented 2 years ago

@Yeicor Cant see a main.go that wires the render/dev up. Can you let me know so i can test this...

It works by designing your SDFX in your own main.go and then calling dev.NewRenderer(anySDF).Run().

The example at examples/spiral/main.go already does this if you set the environment variable SDFX_TEST_DEV_RENDERER_2D=true

gedw99 commented 2 years ago

thanks @Yeicor Almost got a modified makefile working on spiral.

just hitting a go module bug... will let you know how i go...

gedw99 commented 2 years ago

I got the WASM gui working by not using github.com/hajimehoshi/wasmserve, and instead using caddy.

all good :)

Screenshot 2022-01-08 at 11 51 25

gedw99 commented 2 years ago

Tried tinygo ( version: 0.21.0 ) but no luck, due to reflect not being supported by tinygo.

tinygo build -o /Users/apple/workspace/go/src/github.com/gedw99/fhir-tools/gui/deadsy__sdfx/Yeicor___render-dev/sdfx/examples/spiral/bin/web/wasm/wasm.wasm -target wasm ./main.go

/usr/local/opt/go/libexec/src/encoding/xml/typeinfo.go:114:29: f.Index undefined (type *reflect.StructField has no field or method Index)
/usr/local/opt/go/libexec/src/encoding/xml/typeinfo.go:318:14: typ.FieldByIndex undefined (type reflect.Type has no field or method FieldByIndex)
/usr/local/opt/go/libexec/src/encoding/xml/typeinfo.go:319:14: typ.FieldByIndex undefined (type reflect.Type has no field or method FieldByIndex)
deadsy commented 2 years ago

maybe committed to its own repository (sdfx-ui) which can then become a full editor if there is enough interest.

I like the idea of clean partitioning between the UI(s) and the sdfx library. UI code can be big and full of dependecies and I wouldn't want to burden a CLI based usage of the library with having to pull down UI packages.

As it is, I've tried to be modular within the library. ie- code that builds SDFs and code that renders SDFs.

I like anything that reduces the cycle time of iterative development so in that case having an editor open and an updating a preview window beats a manual build/run/preview cycle.

Editor/IDE choice tends to be a personal matter - one of the things I don't like about openscad is the IDE they have for it. I'd rather see a model where you pick your favorite editor, make changes, send a change update to a UI application that then re-renders and displays.

Yeicor commented 2 years ago

Editor/IDE choice tends to be a personal matter - one of the things I don't like about openscad is the IDE they have for it. I'd rather see a model where you pick your favorite editor, make changes, send a change update to a UI application that then re-renders and displays.

That was exactly my objective with this UI: it is simply a renderer that listens for code changes and displays the new surface as fast as possible with as much detail as possible. Trying to create a code editor would be reinventing the wheel and it require too much effort to get it right, with little to no advantage over IDEs.

I understand why you wouldn't want to include this code in the code library, so I will create a new repository for the UI. This pull request will only include some small improvements I made to the PNG renderer (and announce the new UI in the README).

Yeicor commented 2 years ago

Ready for merge @deadsy :wink: