{"slug": "halfspace-is-an-ide-for-solid-modeling-with-distance-fields", "title": "Halfspace is an IDE for solid modeling with distance fields", "summary": "Matt Keeter released Halfspace, an experimental IDE for solid modeling with distance fields, as a showcase app for the Fidget kernel used for rasterization and meshing. Halfspace rasterizes images in real(ish)-time and exports models as images or triangle meshes, and Keeter said he has worked on it since April 2025 without using LLM-generated code, with Fidget dating back to 2022. The IDE combines a small standard library of shapes and transformations with incremental model building, splitting complex models into parameterized, individually visualized pieces.", "body_md": "## Introduction\n\n[Halfspace](https://github.com/mkeeter/halfspace) is an experimental IDE for\nsolid modeling with distance fields.\n\n(The demo is best experienced on a computer; mobile Safari has some WebGPU issues, and pan / tilt / zoom interactions are not yet designed for multitouch)\n\nHalfspace is a showcase app for the [Fidget kernel](../fidget), which is used\nfor rasterization and meshing.  Within the GUI, images are rasterized in\nreal(ish)-time; models can be exported as either images or triangle meshes:\n\nSince it's 2026, let me note at the outset that this is **not vibe-coded**.\nI've been working on it since\n[April 2025](https://github.com/mkeeter/halfspace/commit/317ddc435dcdef74bcfdb03a42c414182268005d#diff-b1a35a68f14e696205874893c07fd24fdb88882b47c23cc0e0c80a30c7d53759)\nand am writing the code using my human brain, for\n[various reasons](https://github.com/mkeeter/halfspace#llm-usage)\n(and Fidget dates back to\n[2022](https://github.com/mkeeter/fidget/commit/f44c0489af34b0d8052c9a11e3f593b731c4784f)).\n\nNow, the rest of this writeup assumes *some* knowledge of implicit surfaces;\nplease [see](../libfive) [many](../fidget) [previous](../ao)\n[writeups](../antimony) [for](../kokopelli) [details](../solver) for more\nbackground info (or just keep reading, you'll be fine).\n\n### Why?\n\nI've spent a bunch of time writing implicit kernels, slightly less time writing GUIs on those kernels, and even less time actually modeling with those tools.\n\nIn practice, I don't actually need to do much solid modeling in my daily life, so most of the stuff that I create is a demo or an example of how to use a particular kernel.\n\nStill, I've noticed a particular tension when working with implicit surfaces.\nWorking with low-level implicit surfaces is a bit like writing assembly: it's\nlow-level, powerful, and annoying.  If all you're given is `x`, `y`, `z`\nvariables – and it's your responsibility to combine them into all the shapes of\nyour dreams – that can be a painful experience.\n\nWhen faced with the pain of writing assembly, most people build abstractions on\ntop of it: high-level languages and libraries that compile down to a low-level\nrepresentation.  The equivalent here is a standard library of shapes and\ntransformations: `sphere`, `box`, `translate`, `scale`, etc.\n\nThere's also a less common approach to the pain of assembly: *making assembly\nitself less painful to write*.\n\nMy favorite project along those lines is\n[Kartik Agaram's Mu](https://akkartik.name/akkartik-convivial-20200315.pdf),\nwhich wraps emulation, tracing, and time-travel debugging around a subset of x86\nassembly language.\n\nHalfspace takes both paths.  It includes a (small but growing) standard library,\nbut also makes it easy to build up models **incrementally**: a complex model can\nbe split into smaller pieces, which can be parameterized and visualized\nindividually.\n\nGiven that justification, let's unpack the description a bit farther.\n\n## Solid modeling\n\nFirst off, \"solid modeling\" means that we're focusing on objects with a definitive inside and outside; you should be able to pick any point in space and say whether it's inside or outside the model.\n\nThis seems obvious, but there's plenty of modeling that doesn't care about that\nproperty: pull up any\n[video game model viewer](<https://noclip.website/#mkwii/rainbow_course;ShareData=Au:Um=fYwiWaO1)=rkL%5BgL>)\nand you'll see plenty of infinitely-thin textured walls, built from a single\nfan of triangles.\nSince my background is in\n[CAD/CAM software](https://en.wikipedia.org/wiki/CAD/CAM)\n(with an emphasis on 3D printing), I want models that can be physically\nrealized.\n\nThere are a bunch of ways to do solid modeling.  In most CAD software, a\n[boundary-representation](https://en.wikipedia.org/wiki/Boundary_representation)\n[geometry kernel](https://en.wikipedia.org/wiki/Geometric_modeling_kernel)\nis responsible for stitching a bunch of individual surfaces together into a\nsolid body.  This is a tremendously hard problem – for example, the intersection\nof two [NURBS](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline)\nsurfaces may not have a closed-form solution!\n\nDating back to my Master's thesis, I've been working on geometry kernels based on implicit surfaces. These have the advantage that they can conceivably be written and fully understood by a single person or small team, so they're a good fit for personal-scale fabrication software.\n\nThis continues in Halfspace: it's a GUI wrapped around the\n[Fidget](https://www.mattkeeter.com/projects/fidget) geometry kernel.  Models can be designed using some\ncombination of pre-defined primitives and hand-written scripts, and exported as\neither images or triangle meshes.\n\n## An IDE for distance fields\n\nWe could use the Fidget kernel *purely* at the constructive solid geometry (CSG)\nlayer, building shapes (spheres, cubes, cylinders, etc) and combining them with\nlogical operations (union, intersection, difference).  Halfspace instead make\nthe decision to put the underlying distance fields in the foreground.\n\nLet me give you an example of why this matters. Here are two distance fields for a sawtooth wave, which have the same signs at every point in space, but different values:\n\nIn this visualization, the sign (which defines *inside* versus *outside*) is\nshown by color (blue versus orange), with the boundary of the shape shown in\nwhite (corresponding to a value of 0). The field **values** are shown by the\nfainter lines, which are spaced at regular intervals (like a topographic map).\n\nDespite having identical signs everywhere, the first field is very poorly behaved. Look at the vertical edge of the sawtooth: there's a transition from inside (blue) to outside (orange) without a crossing through zero.\n\nThis is a C0 or\n[\"jump\" discontinuity](https://en.wikipedia.org/wiki/Classification_of_discontinuities#Jump_discontinuity),\nand it's bad news!  Fidget uses automatic differentiation to compute normals, so\nthe normals across this boundary don't point in the correct direction (compare\nthe field lines between top and bottom images). In 3D, where we use normals for\nshading, this produces incorrect shading in the cabin's shingles:\n\n(If this looks familiar, it's because it's extracted from\n[an earlier blog post](https://www.mattkeeter.com/blog/2025-04-12-continuity/))\n\nPutting distance fields front-and-center makes it easy to diagnose these kind of issues. In fact, it suggests a further improvement on the sawtooth field: we can tweak the gradient so that it's 1 everywhere, instead of being bunched up on the diagonals. Here's a before / after comparison:\n\nHaving uniform gradients makes various algorithms better-behaved; Fidget doesn't require it for correctness, but it may (for example) improve mesh quality.\n\n## Halfspace is experimental and cross-platform\n\nRight now, it would be a **very bold** decision to use Halfspace in any\nload-bearing capacity.  In the [Fidget writeup](https://www.mattkeeter.com/projects/fidget), here's one of\nthe project goals:\n\nFinding the \"right\" APIs for implicit kernels, with the possibility of making substantial compatibility breaks\n\nHalfspace is similar; it doesn't present APIs to end-users, but I'm flexing my software architecture skills by building a substantial cross-platform application, and I'm willing to aggresively iterate and break things as we go.\n\nSpeaking of cross-platform, I'm making my life harder by targeting both the web and native platforms. In the era of supply-chain attacks, being able to share a web link – instead of asking someone to compile and run your code – is great for onboarding and casual usage.\n\nTo that end, I've been collecting the \"Halfspace stack\": a set of libraries and patterns which let me ship a combined native + web application with a minimum of pain. Right now, here are the core pieces:\n\n- Rust for the application (and all dependencies)\n- [`egui`](https://github.com/emilk/egui) for the GUI\n  - [`egui_dock`](https://docs.rs/egui_dock/latest/egui_dock/) for the core\nwindow-and-tab abstraction\n- [`wgpu`](https://wgpu.rs/) for both rendering the UI**and** GPU compute (!)\n- [Rhai](https://rhai.rs) for scripting\n- [Rayon](https://docs.rs/rayon/) and[`wasm-bindgen-rayon`](https://docs.rs/wasm-bindgen-rayon/latest/wasm_bindgen_rayon/) ,\nused for two purposes:\n  - Speeding up parallel algorithms by distributing work over many workers; this is a \"typical\" usage of the library\n  - A thread pool for short-lived background tasks; this is a more unusual usage, but we can't spawn threads on the web.\n- ...and a long tail of other libraries and shenanigans\n  - [`web-time`](https://docs.rs/web-time/latest/web_time/) for cross-platform\ntime support\n  - A [homebrew worker pool](https://github.com/mkeeter/halfspace/blob/3fe871ed94e8e46645af3ed363439e0eeea51a74/src/platform/web.rs#L500-L563) for off-thread (`async` ) GPU rendering\n\nThis all deserves a dedicated writeup, and I have complaints about every single layer of the stack, but overall, it's incredible that everything Just Works™.\n\n## Driving Fidget improvements\n\nAnother goal of Halfspace is to drive improvements in the Fidget kernel, by using it in a non-trivial application.\n\nThe biggest victory on this front has been ongoing work on\n[`fidget-wgpu`](https://docs.rs/fidget-wgpu/latest/fidget_wgpu/).  This was\nmotivated by performance on the web: the native build was pleasantly fast, but\ndoing rasterization on the CPU was awfully slow (\"non-interactive speeds\") when\nrunning through a layer of WebAssembly.\n\nAfter a lot of work on the Fidget side, both rasterization **and**\npost-processing (e.g. shading) can be run purely on the GPU, without any\nroundtrips to the CPU.\n\nThis was both a performance and architectural win:\n\n- We now have native rendering speed on both native and web targets\n- Rendering logic is no longer spread between Fidget (on the CPU) and Halfspace\n(with a mix of CPU and GPU code):\n  - Fidget implements the canonical rendering logic\n  - Halfspace has thin shaders which draw an RGBA texture\n\n(The 2D rendering pipeline is also now fully GPU-accelerated, although it has\nslightly fancier shaders in Halfspace, for *reasons*)\n\n## Wrapping up\n\nHalfspace is a thing that exists!\n\nYou should try it out, and should probably not use it for critical applications! If you encounter problems, please file an issue or open a discussion on Github.\n\nLike most of my work, I plan to keep working on it until I have run out of\nthings to learn from the project.\nAlso like most of my work, it's\n[open-source](https://github.com/mkeeter/halfspace/)\nunder [the MPLv2 license](https://github.com/mkeeter/halfspace/blob/main/LICENSE.txt).", "url": "https://wpnews.pro/news/halfspace-is-an-ide-for-solid-modeling-with-distance-fields", "canonical_source": "https://www.mattkeeter.com/projects/halfspace/", "published_at": "2026-09-28 18:00:55+00:00", "updated_at": "2026-09-28 18:20:20.410634+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Halfspace", "Fidget", "Matt Keeter", "Kartik Agaram", "Mu"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/halfspace-is-an-ide-for-solid-modeling-with-distance-fields", "markdown": "https://wpnews.pro/news/halfspace-is-an-ide-for-solid-modeling-with-distance-fields.md", "text": "https://wpnews.pro/news/halfspace-is-an-ide-for-solid-modeling-with-distance-fields.txt", "jsonld": "https://wpnews.pro/news/halfspace-is-an-ide-for-solid-modeling-with-distance-fields.jsonld"}}