Some more rewording/writing in 2021-07-27-procedural-meshes.org
This commit is contained in:
parent
0ab0f9d0ec
commit
808e4df573
@ -31,7 +31,7 @@ that. Naturally, this led me to wonder how I might extend Context
|
|||||||
Free's model to work more generally with 3D geometry, and let me use
|
Free's model to work more generally with 3D geometry, and let me use
|
||||||
it to produce procedural geometry.
|
it to produce procedural geometry.
|
||||||
|
|
||||||
[[http://structuresynth.sourceforge.net/index.php][Structure Synth]] of course already exists as a straightforward
|
[[http://structuresynth.sourceforge.net/index.php][Structure Synth]] of course already exists, and is a straightforward
|
||||||
generalization of Context Free's model to 3D (thank you to Mikael
|
generalization of Context Free's model to 3D (thank you to Mikael
|
||||||
Hvidtfeldt Christensen's blog [[http://blog.hvidtfeldts.net/][Syntopia]], another of my favorite things
|
Hvidtfeldt Christensen's blog [[http://blog.hvidtfeldts.net/][Syntopia]], another of my favorite things
|
||||||
ever, for introducing me to it awhile ago). See also [[https://kronpano.github.io/BrowserSynth/][BrowserSynth]].
|
ever, for introducing me to it awhile ago). See also [[https://kronpano.github.io/BrowserSynth/][BrowserSynth]].
|
||||||
@ -47,9 +47,8 @@ Tools like [[https://openscad.org/][OpenSCAD]], based on [[https://www.cgal.org/
|
|||||||
suspect that [[https://www.opencascade.com/][Open CASCADE]] (thus [[https://www.freecadweb.org/][FreeCAD]]) also does. In CAD work, it's
|
suspect that [[https://www.opencascade.com/][Open CASCADE]] (thus [[https://www.freecadweb.org/][FreeCAD]]) also does. In CAD work, it's
|
||||||
crucial. I experimented with similar recursive systems with some of
|
crucial. I experimented with similar recursive systems with some of
|
||||||
these, but I quickly ran into a problem: they were made for actual
|
these, but I quickly ran into a problem: they were made for actual
|
||||||
practical applications in CAD, not for my nonsensical generative art,
|
practical applications in CAD, not so much for my generative art, and
|
||||||
and they scaled quite poorly with the sort of recursion I was asking
|
they scaled quite poorly with the sort of recursion I was asking for.
|
||||||
for.
|
|
||||||
|
|
||||||
Implicit surfaces (or one of the many
|
Implicit surfaces (or one of the many
|
||||||
equivalent-except-for-when-it's-not names for this, e.g. F-Reps or
|
equivalent-except-for-when-it's-not names for this, e.g. F-Reps or
|
||||||
@ -59,15 +58,15 @@ rendered directly on the GPU via shaders, operations like blending
|
|||||||
shapes or twisting them are easy... for more on this, see [[http://blog.hvidtfeldts.net/][Syntopia]]
|
shapes or twisting them are easy... for more on this, see [[http://blog.hvidtfeldts.net/][Syntopia]]
|
||||||
again, or nearly anything by [[https://iquilezles.org/][Inigo Quilez]], or look up raymarching and
|
again, or nearly anything by [[https://iquilezles.org/][Inigo Quilez]], or look up raymarching and
|
||||||
sphere tracing, or see [[https://ntopology.com/][nTopology]], or Matt Keeter's work with [[https://www.libfive.com/][libfive]]
|
sphere tracing, or see [[https://ntopology.com/][nTopology]], or Matt Keeter's work with [[https://www.libfive.com/][libfive]]
|
||||||
and [[https://www.mattkeeter.com/research/mpr/][MPR]]. They're pure magic and they're wonderfully elegant and I'll
|
and [[https://www.mattkeeter.com/research/mpr/][MPR]]. They're pure magic, they're wonderfully elegant, and I'll
|
||||||
probably have many other posts on them.
|
probably have many other posts on them.
|
||||||
|
|
||||||
However, there is one big issue: turning implicit surfaces to good
|
However, there is one big issue: turning implicit surfaces to good
|
||||||
meshes for rendering /is a huge pain/, and while many renderers can
|
meshes for rendering /is a huge pain/, and while many renderers can
|
||||||
handle implicit surfaces directly, Blender's renderers cannot. I have
|
handle implicit surfaces directly, Blender's renderers cannot. I will
|
||||||
other posts on this as well, but for now, take it on faith. This is
|
have other posts going into more detail on this subject, but for now,
|
||||||
why I did not try to use implicit surfaces for this project. (TODO:
|
take it on faith. This is why I did not try to use implicit surfaces
|
||||||
Make those posts.)
|
for this project. (TODO: Make those posts.)
|
||||||
|
|
||||||
With these limitations in mind, around 2018 June I had started jotting
|
With these limitations in mind, around 2018 June I had started jotting
|
||||||
some ideas down. The gist is that I wanted to create
|
some ideas down. The gist is that I wanted to create
|
||||||
@ -94,7 +93,8 @@ My meandering path to implementing it went something like this:
|
|||||||
- Write some very ad-hoc Python to generate a mesh of a parametric
|
- Write some very ad-hoc Python to generate a mesh of a parametric
|
||||||
conversion of my annoying spiral isosurface from 2005 by breaking it
|
conversion of my annoying spiral isosurface from 2005 by breaking it
|
||||||
into planar "slices" or "frames", which move along the geometry and
|
into planar "slices" or "frames", which move along the geometry and
|
||||||
then are connected together at corresponding vertices.
|
then are connected together at corresponding vertices. (TODO: Add
|
||||||
|
link to the automata_scratch repo, whatever it's renamed to)
|
||||||
- Explore [[https://github.com/thi-ng/geom][thi.ng/geom]] and pretty quickly give up - but in the process,
|
- Explore [[https://github.com/thi-ng/geom][thi.ng/geom]] and pretty quickly give up - but in the process,
|
||||||
discover [[https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.42.8103][Parallel Transport Approach to Curve Framing]].
|
discover [[https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.42.8103][Parallel Transport Approach to Curve Framing]].
|
||||||
- Implement that paper in Python, reusing the basic model from my
|
- Implement that paper in Python, reusing the basic model from my
|
||||||
@ -109,39 +109,58 @@ My meandering path to implementing it went something like this:
|
|||||||
- Realize that Rust is the wrong tool for the job, and rewrite *again*
|
- Realize that Rust is the wrong tool for the job, and rewrite *again*
|
||||||
in Python but with a rather different design and mindset.
|
in Python but with a rather different design and mindset.
|
||||||
|
|
||||||
(this is, of course, ignoring projects on various other tangents)
|
(this is, of course, ignoring many other tangents with things like
|
||||||
|
shaders)
|
||||||
|
|
||||||
(TODO: Maybe split these off into sections for each one?)
|
(TODO: Maybe split these off into sections for each one?)
|
||||||
|
|
||||||
Somewhere in here, I concluded that my fundamental idea was
|
I put some serious effort into [[https://github.com/Hodapp87/prosha][Prosha]] and was conflicted on shelving
|
||||||
half-broken. It half-worked: I was able to produce closed, manifold
|
the project, but the issues didn't look easily solvable. Part of
|
||||||
meshes this way, and it could be tedious, but not *that* difficult.
|
those issues were implementation issues with Rust - not that Rust
|
||||||
However, all of my attempts to also produce "good" meshes this way
|
could have really done anything "better" here, but that it just wasn't
|
||||||
failed miserably.
|
the right tool for what I was doing. In short, I had spent a lot of
|
||||||
|
time and effort trying to badly and unintentionally implement a Lisp
|
||||||
|
inside of Rust instead of just picking a Lispier language, or perhaps
|
||||||
|
using an embeddable Rust-based scripting language like [[https://github.com/koto-lang/koto][Koto]] or [[https://github.com/rhaiscript/rhai][Rhai]]. I
|
||||||
|
had ignored that many things that functional programming left me very
|
||||||
|
accustomed to - like first-class functions and closures - were
|
||||||
|
dependent on garbage collection. When I realized this and did a big
|
||||||
|
refactor to remove this entire layer of complexity, I was left with
|
||||||
|
very little "core" code - just a handful of library functions, and the
|
||||||
|
actual recursive rules for the geometry I was trying to generate.
|
||||||
|
That's good and bad: things were much simpler and vastly faster, but
|
||||||
|
also, it felt like I had wasted quite a lot of time and effort. I
|
||||||
|
have some more detailed notes on this in the Prosha repository.
|
||||||
|
|
||||||
|
Part of the issues also weren't Rust implementation issues - they were
|
||||||
|
deeper issues with my original "correct-by-construction" mesh idea
|
||||||
|
being half-broken. It half-worked: I was able to produce closed,
|
||||||
|
manifold meshes this way, and it could be tedious, but not *that*
|
||||||
|
difficult. However, all of my attempts to also produce "good" meshes
|
||||||
|
this way failed miserably.
|
||||||
|
|
||||||
(TODO: Can I find examples of this?)
|
(TODO: Can I find examples of this?)
|
||||||
|
|
||||||
A few of the same fundamental issues kept cropping up. One is that
|
The crux is that the recursive rules I used for generating geometry
|
||||||
the recursive rules I used for generating geometry (inspired heavily
|
(inspired heavily by those in Context Free) were inherently based
|
||||||
by those in Context Free) were inherently based around discrete steps,
|
around discrete steps, generating discrete entities, like vertices,
|
||||||
generating discrete entities, like vertices, edges, and face; it made
|
edges, and face, and it made no sense to "partially" apply a rule,
|
||||||
no sense to "partially" apply a rule, especially if that rule involved
|
especially if that rule involved some kind of branching - but I kept
|
||||||
some kind of branching. I kept trying to treat it as something
|
trying to treat it as something continuous for the sake of being able
|
||||||
continuous for the sake of being able to "refine" the mesh to as fine
|
to "refine" the mesh to as fine of detail as I wanted. Further, I was
|
||||||
of detail as I wanted. Further, I was almost never consistent with
|
almost never consistent with the nature of this continuity: sometimes
|
||||||
the nature of this continuity: sometimes I wanted to treat it like a
|
I wanted to treat it like a parametric curve (one continuous
|
||||||
parametric curve (one continuous parameter), sometimes I wanted to
|
parameter), sometimes I wanted to treat it like a parametric surface
|
||||||
treat it like a parametric surface (two continuous parameters),
|
(two continuous parameters), sometimes I wanted to treat it like an
|
||||||
sometimes I wanted to treat it like an implicit surface
|
implicit surface (with... theoretically two continuous parameters,
|
||||||
(with... theoretically two continuous parameters, just not explicit
|
just not explicit ones?). It was a mess, and it's part of why my
|
||||||
ones?). It was a mess, and it's part of why my Prosha repository is a
|
Prosha repository is a graveyard of branches.
|
||||||
graveyard of branches.
|
|
||||||
|
|
||||||
The recursive rules were still excellent at expressing arbitrarily
|
The recursive rules were still excellent at expressing arbitrarily
|
||||||
complex, branching geometry - and I really wanted to keep this basic
|
complex, branching geometry - and I really wanted to keep this basic
|
||||||
model around somehow. After some reflection, I believed that the only
|
model around somehow. After some reflection, I believed that the only
|
||||||
way to do this was to completely separate the process of
|
way to do this was to completely separate the process of meshing
|
||||||
meshing/refinement/subdivision from the recursive rules.
|
(refinement, subdivision, facetization...) from the recursive rules.
|
||||||
|
|
||||||
This would have been obvious if I read the guides from [[https://graphics.pixar.com/opensubdiv/overview.html][OpenSubdiv]]
|
This would have been obvious if I read the guides from [[https://graphics.pixar.com/opensubdiv/overview.html][OpenSubdiv]]
|
||||||
instead of reimplementing it badly. Their [[https://graphics.pixar.com/opensubdiv/docs/subdivision_surfaces.html][subdivision surface]]
|
instead of reimplementing it badly. Their [[https://graphics.pixar.com/opensubdiv/docs/subdivision_surfaces.html][subdivision surface]]
|
||||||
@ -151,7 +170,7 @@ made a lot of sense: I shouldn't be trying to generate the "final"
|
|||||||
mesh, I should be generating a mesh as the /control cage/, which
|
mesh, I should be generating a mesh as the /control cage/, which
|
||||||
guides the final mesh. Further, I didn't even need to bother with
|
guides the final mesh. Further, I didn't even need to bother with
|
||||||
OpenSubdiv's C++ API, I just needed to get the geometry into Blender,
|
OpenSubdiv's C++ API, I just needed to get the geometry into Blender,
|
||||||
and Blender would handle the subdivision via OpenSubdiv.
|
and Blender would handle the subdivision on-demand via OpenSubdiv.
|
||||||
|
|
||||||
One minor issue is that this control cage isn't just a triangle mesh,
|
One minor issue is that this control cage isn't just a triangle mesh,
|
||||||
but a triangle mesh plus edge creases. I needed a way to get this
|
but a triangle mesh plus edge creases. I needed a way to get this
|
||||||
@ -159,12 +178,26 @@ data into Blender. However, the only format Blender can read edge
|
|||||||
creases from is [[http://www.alembic.io/][Alembic]]. Annoyingly, its [[http://docs.alembic.io/reference/index.html#alembic-intro][documentation]] is almost
|
creases from is [[http://www.alembic.io/][Alembic]]. Annoyingly, its [[http://docs.alembic.io/reference/index.html#alembic-intro][documentation]] is almost
|
||||||
completely nonexistent, the [[https://alembic.github.io/cask/][Cask]] bindings still have spotty Python 3.x
|
completely nonexistent, the [[https://alembic.github.io/cask/][Cask]] bindings still have spotty Python 3.x
|
||||||
support, and when I tried to run their example code to produce some
|
support, and when I tried to run their example code to produce some
|
||||||
files, and Blender was crashing when importing them. Until I shave
|
files, and Blender was crashing when importing them.... and this is
|
||||||
that yak, I am instead generating the mesh data directly in Blender
|
all a yak to shave another day. I instead generated the mesh data
|
||||||
(via its Python interpreter), adding it to the scene, and then setting
|
directly in Blender (via its Python interpreter), added it to the
|
||||||
its creases via its Python API.
|
scene, and then set its creases via its Python API.
|
||||||
|
|
||||||
TODO while I'm not so tired:
|
After the aforementioned refactor in Prosha, I was able to quickly
|
||||||
|
translate the Rust code for most of my examples into Python code with
|
||||||
|
the help of some library code I'd accumulated from the past projects.
|
||||||
|
Debugging this mostly inside Blender also made the process vastly
|
||||||
|
faster. Further, because I was letting Blender handle all of the
|
||||||
|
heavy lifting with mesh processing (and it in turn was using things
|
||||||
|
like OpenSubdiv), the extra overhead of Python compared to Rust didn't
|
||||||
|
matter - I was handling so much less data when only producing the
|
||||||
|
control cage, not the full mesh.
|
||||||
|
|
||||||
What is the aim of this post? To explain Prosha? To explain current
|
I'm still a little stuck at how to build higher 'geometric'
|
||||||
work, including Prosha?
|
abstractions here and compose them. I have felt like most of the
|
||||||
|
model couples me tightly to low-level mesh constructs - while Context
|
||||||
|
Free and Structure Synth definitely don't have this problem. This is
|
||||||
|
particularly annoying because a lot of the power of these recursive
|
||||||
|
grammars comes from their ability to be abstracted away and composed.
|
||||||
|
|
||||||
|
(TODO: Show some examples)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user