Declarative 3D form evolution through tree-based transformations.
This project is part of the thi.ng collection of Clojure & Clojurescript libraries and is written in a literate programming style. Building on top of its companion, the thi.ng/geom library, morphogen provides a set of extensible building blocks to generate complex 3d structures in a completely data driven, declarative style.
Morphogensis, as one of the fundamental processes in developmental biology, is used as the guiding metaphor for the design approach and the tools defined in this library: A purposely small number of spatial transformers (currently only: subdivision, reflection, extrusion) can be encoded as a (potentially) deeply nested tree, which is then recursively applied to a single, basic 3d seed form (e.g. a cube) to evolve it. This tree of operators fulfills a similar role as DNA does in nature, but can also be understood as the AST of a program. The operators themselves are context free, i.e. they have no direct relationship to the geometric elements they operate on, nor do they need to be aware of their position in the tree. In fact, the tree of operators is entirely distinct from any geometries. When the tree is walked & applied to the seed form, a second tree of mesh elements is being constructed reflecting the transformation results. Technically, the operators are pure functions, simply producing a sequence of new geometry nodes. This combination enables the declarative approach to tree building and the independent formulation, extraction and injection of sub-trees and therefore the definition of a re-usable vocabulary of higher order operators. The intention is to include some of them in the core library as development progresses.
A more detailed description of all elements and their implementation can be found in the core namespace of this library.
ALPHA quality, work in progress. This project is actively being worked on and is likely to receive daily updates over the next couple of months.
Again, since operators are only depending on the basic topology (but not the position, size or orientation) of the seed form, even this small number of operators can already produce a vast number of outcomes. The repo contains a file with documented examples which can be run from the REPL and export meshes in Stanford PLY format.
0.2.0-SNAPSHOT
[org.clojure/clojure "1.9.0"]
[org.clojure/clojurescript "1.10.238"]
[thi.ng/geom "1.0.0-RC3"]
[thi.ng/luxor "0.3.0" :exclusions [thi.ng/common thi.ng/geom]]
[criterium "0.4.3"]
[com.cemerick/clojurescript.test "0.3.3"]
[lein-cljsbuild "1.1.7"]
[thi.ng/morphogen "0.2.0-SNAPSHOT"]
This project is written in a literate programming format and requires
Emacs & Org-mode to generate usable source code. Assuming both tools
are installed, the easiest way to generate a working project is via
command line (make sure emacs
is on your path or else edit its path
in tangle.sh
):
git clone https://github.com/thi-ng/morphogen.git
cd morphogen
./tangle.sh src/*.org test/*.org
Tangling is the process of extracting & combining source blocks from
.org
files into an actual working project/source tree. Once tangling
is complete, you can cd
into the generated project directory
(babel
) and then use lein repl
as usual.
The project.clj
file defines an alias to trigger a complete build &
tests for both CLJ & CLJS versions.
cd babel
lein cleantest
To build the Clojurescript version simply run lein cljsbuild test
from the same directory. A small HTML harness for the resulting JS
file is also located in that folder (babel/index.html
), allowing for
further experimentation in the browser.
Editing code blocks or files in Org-mode, then re-loading & testing
changes is quite trivial. Simply launch a REPL (via lein
or Emacs)
as usual. Everytime you’ve made changes to an .org
file, re-tangle
it from Emacs (C-c C-v t
) or tangle.sh
, then reload the namespace
in the REPL via (require 'thi.ng.morphogen... :reload)
or similar.
(defproject thi.ng/morphogen "<<version>>"
:description "3d form evolution through tree-based transformations"
:url "<<project-url>>"
:license {:name "Apache Software License 2.0"
:url "http://www.apache.org/licenses/LICENSE-2.0"
:distribution :repo}
:scm {:name "git"
:url "[email protected]:thi-ng/morphogen.git"}
:min-lein-vesion "2.4.0"
:dependencies [<<dep-clj>>
<<dep-geom>>]
:profiles {:dev {:dependencies [<<dep-luxor>>
<<dep-cljs>>
<<dep-criterium>>]
:plugins [<<dep-cljsbuild>>
<<dep-cljs-test>>]
:global-vars {*warn-on-reflection* true}
:jvm-opts ^:replace []
:aliases {"cleantest" ["do" "clean" "test" "cljsbuild" "test"]}}}
:cljsbuild {:builds [{:source-paths ["src" "test"]
:id "simple"
:compiler {:output-to "<<cljs-artefact-path>>"
:optimizations :whitespace
:pretty-print true}}]
:test-commands {"unit-tests" ["phantomjs" :runner "<<cljs-artefact-path>>"]}}
:pom-addition [:developers [:developer
[:name "Karsten Schmidt"]
[:url "http://postspectacular.com"]
[:timezone "0"]]])
<!DOCTYPE html>
<html lang="en">
<head>
<title><<lein-coords>> test</title>
</head>
<body>
<script type="text/javascript" src="<<cljs-artefact-path>>"></script>
</body>
</html>
The autogenerated namespace thi.ng.morphogen.version
contains a single
symbol version
holding the version string defined above:
(use '[thi.ng.morphogen.version])
(prn version)
; "<<version>>"
Version | Released | Description | Lein coordinates | Tagged Github URL |
---|---|---|---|---|
0.1.1 | 2015-02-27 | bugfix dependencies | [thi.ng/morphogen "0.1.1"] | 0.1.1 |
0.1.0 | 2015-02-25 | 1st public release | [thi.ng/morphogen "0.1.0"] | 0.1.0 |
Name | Role | Website |
---|---|---|
Karsten Schmidt | initiator & principal developer | http://postspectacular.com |
http://thi.ng |
This project is open source and licensed under the Apache Software License 2.0.