[ANN] thi.ng collection update (CLJ/CLJS)

286 views
Skip to first unread message

Karsten Schmidt

unread,
Feb 25, 2015, 12:07:01 AM2/25/15
to clo...@googlegroups.com, clojur...@googlegroups.com
Hi guys,

thi.ng is a collection of over a dozen largely x-platform Clojure &
Clojurescript libs for computational/generative design & data
visualization tasks.

I just wanted to give a little heads up that this project has recently
seen a number of releases and, as a whole, by now is generally quite
stable and usable (*is used*) for realworld projects (although most
libs remain in constant parallel development to make them more feature
complete). I've collated a number of images of projects and links to
the most important libs here:

http://thi.ng/

Most notably of those:

http://thi.ng/geom
By far the largest sub-project and backbone for most others: A 2D/3D
geometry package w/ comprehensive vector algebra, swizzling,
intersections, matrix types & helpers, quaternions, pure shape
primitives with ~50 protocols for polymorphic enquiry & manipulation,
meshes (incl. I/O), mesh subdivisions, CSG mesh ops, Verlet physics
engine (only particles, springs, behaviors)... Most of this lib is
pure geometry w/ no rendering specifics, although there're separate
modules for SVG rendering w/ shader support & decorators [1], WebGL
wrapper and converters from shapes/meshes to VBOs and various shader
presets/utils.

http://thi.ng/shadergraph
GLSL (WebGL) pure function library & dependency graph (based on
com.stuartsierra/dependency), GLSL minification during CLJS compile
time

http://thi.ng/color
RGB, HSV, CMYK, CSS conversions, color presets (incl. D3 category schemes)

http://thi.ng/luxor
Complete scene compiler DSL for http://luxrender.net, based around thi.ng/geom

http://thi.ng/morphogen
Declarative 3D form evolution through tree-based transformations,
basically an AST generator of geometric operations to transform a
single seed node into complex 3D objects

http://thi.ng/tweeny
Interpolation of nested (presumably animation related) data
structures. Allows tweening of deeply nested maps/vectors with
completely flexible tween fns/targets and hence easy definition of
complex timelines

http://thi.ng/validate
Purely functional, composable data validation & optional corrections
for nested data. Supports both maps & vectors, wildcards, comes with
many predefined validators, but extensible...

http://thi.ng/trio
A generic, non-RDF specific triple store API and feature rich
SPARQL-like query engine
(and my prime example of using the literate programming approach with
org-mode[2][3])

Last but not least: Super special thanks are due to the following people:

Rich, Alex + rest of clojure.core
David (+everyone else involved) for the immense effort on making CLJS
proper useful,
Chas, Kevin and anyone else working on CLJX...
none of this would have been possible without these amazing tools!

Best, K.

Ps. There're a number of other libs in this collection which are in
dire need of updating (last touched spring 2013) - these are related
to general OpenCL functionality and voxel rendering. Some of the
example images on the above site were created with these...

[1] https://github.com/thi-ng/geom/blob/master/geom-svg/src/examples.org
[2] https://github.com/thi-ng/trio/blob/master/src/query.org
[3] http://orgmode.org/

--
Karsten Schmidt
http://postspectacular.com | http://thi.ng/

Marc Fawzi

unread,
Feb 25, 2015, 6:53:12 AM2/25/15
to clojur...@googlegroups.com, clo...@googlegroups.com
looks stunning... 

literally stunning, thanks for sharing.

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.
To post to this group, send email to clojur...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.

Dylan Butman

unread,
Feb 25, 2015, 12:03:42 PM2/25/15
to clojur...@googlegroups.com, clo...@googlegroups.com, in...@toxi.co.uk
Hey Karsten,

Really glad to see you've been continuing the awesome work here! I used toxiclibs extensively when I first starting programming in processing and it was hugely influential for me! I've been drifting away from computational design since then but I'm hoping to get some serious time to play with your clojure work soon.

Best
Dylan

kovas boguta

unread,
Feb 25, 2015, 1:55:26 PM2/25/15
to clojur...@googlegroups.com
Congrats on getting to a stable release! This is an awesome project. 

Have you considered moving it away from the "literal programming" encoding?

For myself, and I suspect for many others, this encoding gets in the way of understanding what's available. 

For example, one doesn't get an accurate view of the documentation while browsing the project on github. Running tangle doesn't always work out of the box for everyone either. Given the size of the thing, this can add up to an overwhelming initial experience. 






Ivan L

unread,
Feb 25, 2015, 3:20:06 PM2/25/15
to clojur...@googlegroups.com
Hi Karsten, would you consider the thing libs as a good foundation for interactive graphics in clojurescript? Also, have you compared performance via straight js and quil? I have seen people struggle a bit to maintain similar performance to quil cljs for example.

Karsten Schmidt

unread,
Feb 25, 2015, 5:24:34 PM2/25/15
to clojur...@googlegroups.com
Hi all,

thanks for the kind words, it's very encouraging and I also hope to
provide more small examples soon to better document basic usage
patterns and help more people to get started...

Kovas, I understand the org-mode based approach isn't for everyone,
but this route was a long deliberated and conscious step for me to
better manage and split up the code, keep notes for development,
describe in advance what a thing needs to do and add illustrations of
some concepts. E.g. I honestly doubt I could have written the trio
query engine without it! Adopting the tool (org-mode) and its approach
was a thought transforming process for me, just like switching to
Clojure after over a decade of Java and switching to Java from
Assembly before that... This format was also especially helpful for
sections of large distinct code blocks differing between CLJ & CLJS
(e.g. the vector protocol impls). Allowing one to add wiki-style
links, tags & mult-level headings (sections) in org-mode, and
(un)folding them on demand has proven to be hugely helpful for
navigating the different projects and keeping an overview & task lists
in long namespaces (since I often work offline/outdoors, GH issue
tracking doesn't work for me so well). Even though GH's .org file
rendering has drastically improved in the past few months, it still is
nowhere near as good as in org-mode itself, but I also often use just
that to just quickly check & compare code. Admittedly, for many of
these libs I still haven't made full use of the literate approach,
often simply due to lack of time, but it's something I can and want to
prioritise more in the near future...

The other thing to bear in mind is that these libs have been pretty
much developed in a round-robin manner for over 2 years: a new feature
in one project triggers a cascade of work in one or two other projects
etc. Having all of them based on the same kind of template made this
all this much more efficient.

TL;DR - I agree that somewhat of a more overview document/global table
of contents or searchable sitemap is well needed and on the TODO list!
:) (Speaking of which, most namespaces in the geom, trio, shadergraph
projects now at least have their own TOC at the top of each file to
quickly jump to the right place and I will add this for other libs
too)

I'm surprised to hear that you were struggling with the tangling
process. All you need is emacs with org-mode installed (which can
easily be done via M-x package-install org), then launch the tangle.sh
from the command line... If that doesn't work, could you please file
an issue?

Re: performance

I actually went through a lot of effort and *many* iterations to make
most core types as fast as I could and generally speaking I think its
a very capable setup for interactive apps. E.g. Vectors & matrices are
lean deftypes and the former have recently been rewritten to use a
pretty intense macro code generation setup, are backed by a
double-array on Clojure and Float32Array in CLJS, generally resulting
in a 10x speed up for WebGL (since they can now be more
efficiently/directly transferred to GL attribute buffers). In many
places I eschewed "idiomatic" Clojure approaches and tried avoid
laziness wherever it wasn't really needed. I'm keenly awaiting the 1.7
release, though, to rewrite many lowlevel fns as transducers (which
I'm still having to wrap my head around in some cases).

Having said all this, I can't comment on cljs-quil at all, but am sure
there're use cases where vanilla JS will give you more performance,
simply due to the extra work needing to be done in CLJS for protocol
dispatch and multi-arity fns. However, having spent several years
working with and on Processing (committer from 2003-05), I came to
realize that I like my geometry not just as loose coordinates, but
deal with them as mathematical/abstract models/entities. Since 2006,
this first lead to 6 years of fulltime development of toxiclibs.org,
and once I discovered Clojure, eventually to thi.ng... So even though
the geom lib deals with some of the same aspects & use cases as
Processing/Quil, it is primarily *not* a graphics engine to throw
pixels on screen, but provides tools to solve geometrical
problems/tasks in a more natural/conceptual manner. The lib gives you
free choice as to how you actually visualize this data. On the other
hand, P5/Quil offers zero handholding for almost anything
non-graphical in this field - so I don't see them as competing at
all...

Last but not least, the bottleneck for most interactive graphics apps
these days is very often not CPU bound at all. Here I think the
shadergraph tools are something I'm very, very excited about, since
this allows us to provide re-usable GLSL functions and micro-libs in a
very easy to use manner (and also has no other dependency to anything
else in the thi.ng collection). I don't just think here about effect
composers and more eye candy, but also more GPGPU style apps... Again,
I have zero insight by now if/how this is addressed by cljs-quil...

I'm grateful for any ideas or proposals to improve any of that, so
let's please keep 'em coming! Thanks! :)

K.

On 25 February 2015 at 20:20, Ivan L <ivan.l...@gmail.com> wrote:
> Hi Karsten, would you consider the thing libs as a good foundation for interactive graphics in clojurescript? Also, have you compared performance via straight js and quil? I have seen people struggle a bit to maintain similar performance to quil cljs for example.
>
> --
> Note that posts from new members are moderated - please be patient with your first post.
> ---
> You received this message because you are subscribed to the Google Groups "ClojureScript" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.
> To post to this group, send email to clojur...@googlegroups.com.
> Visit this group at http://groups.google.com/group/clojurescript.



--
Karsten Schmidt
http://postspectacular.com | http://toxiclibs.org | http://toxi.co.uk

Bruce Durling

unread,
Feb 25, 2015, 5:34:50 PM2/25/15
to clojur...@googlegroups.com, clo...@googlegroups.com
Karsten,

Is there a reason why you went with a README.md and then an index.org
rather than a plain README.org?

(love all the rest of it and loved your use of it at The Barbican. I
need to get my head around it all. I'm wondering if I can use it for
some of the geographic and other charting things I do a lot of).

cheers,
Bruce

Karsten Schmidt

unread,
Feb 25, 2015, 6:13:24 PM2/25/15
to clojur...@googlegroups.com, clo...@googlegroups.com
That's a good point, Bruce! To be honest, I don't know anymore, but it
makes complete sense to change it. Consider it done! :)

As for your mapping question, yes, of course! I've done a few of them.
E.g. the first pic on the website [1] was a project for The ODI in
2013 and is a map of different council/borough stats of London (here
knife crime). The shape files were first retrieved & processed with
the thi.ng/trio lib directly from the UK statistics office's SPARQL
endpoint [2], then projected to Mercator, converted to 2d polygons,
smoothed them and then extruded as 3D walled meshes and exported as
STL files using geom. To create that rendered image, another function
then combined all borough meshes into a complete render scene for
Luxrender (using the luxor lib). Since this all was for a 60sec
animation, I also wrote the tweeny lib for that project to allow me to
define the timeline for the various camera, mesh, light & shader
changes. The whole bundle was then sent to EC2 and rendered on 340+
CPUs... basically, spawned a private render farm.

Alternatively with < 30 lines of code you could query any UK
constituency (or use similar endpoints for other countries), do those
initial shape transformations and send the resulting STL mesh file
straight to a 3D printer... For online use, of course the SVG or WebGL
modules would be more interesting, but these really would just deal
with that last transformation/visualization step, i.e. turning a
thi.ng.geom.Polygon2 into an SVG <polygon> node or tesselate it and
stuff it into WebGL buffer to display...

For more flexible mapping, it'd be great to port some/all of the
projections from [3] in its own clj lib for easier (and non-JS
related) access...

[1] http://thi.ng/img/04.jpg
[2] http://statistics.data.gov.uk/doc/statistical-geography
[3] https://github.com/d3/d3-geo-projection/

Hth!
http://postspectacular.com | http://toxiclibs.org | http://toxi.co.uk

Dylan Butman

unread,
Feb 25, 2015, 7:42:33 PM2/25/15
to clojur...@googlegroups.com, clo...@googlegroups.com
I totally thought that map was a photo of 3d printed shapes, but it makes sense that you're using luxrender now. Is there a video of the animation online somewhere?

>> To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscribe@googlegroups.com.

>> To post to this group, send email to clojur...@googlegroups.com.
>> Visit this group at http://groups.google.com/group/clojurescript.
>
> --
> Note that posts from new members are moderated - please be patient with your first post.
> ---
> You received this message because you are subscribed to the Google Groups "ClojureScript" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscribe@googlegroups.com.

> To post to this group, send email to clojur...@googlegroups.com.
> Visit this group at http://groups.google.com/group/clojurescript.



--
Karsten Schmidt
http://postspectacular.com | http://toxiclibs.org | http://toxi.co.uk

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/RlESPn4PHkM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescript+unsubscribe@googlegroups.com.

Karsten Schmidt

unread,
Feb 25, 2015, 7:57:46 PM2/25/15
to clojur...@googlegroups.com, clo...@googlegroups.com
This draft anim was created for The ODI and shows 2 years (summer
2011-2013) worth of London knife crime (based on open data ambulance &
A&E reports):

http://media.thi.ng/2013/odi/20131029-heatmap-draft-1280x960.mp4
>> >> an email to clojurescrip...@googlegroups.com.
>> >> To post to this group, send email to clojur...@googlegroups.com.
>> >> Visit this group at http://groups.google.com/group/clojurescript.
>> >
>> > --
>> > Note that posts from new members are moderated - please be patient with
>> > your first post.
>> > ---
>> > You received this message because you are subscribed to the Google
>> > Groups "ClojureScript" group.
>> > To unsubscribe from this group and stop receiving emails from it, send
>> > an email to clojurescrip...@googlegroups.com.
>> > To post to this group, send email to clojur...@googlegroups.com.
>> > Visit this group at http://groups.google.com/group/clojurescript.
>>
>>
>>
>> --
>> Karsten Schmidt
>> http://postspectacular.com | http://toxiclibs.org | http://toxi.co.uk
>>
>> --
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> ---
>> You received this message because you are subscribed to a topic in the
>> Google Groups "ClojureScript" group.
>> To unsubscribe from this topic, visit
>> https://groups.google.com/d/topic/clojurescript/RlESPn4PHkM/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to
>> clojurescrip...@googlegroups.com.
>> To post to this group, send email to clojur...@googlegroups.com.
>> Visit this group at http://groups.google.com/group/clojurescript.
>
> --
> Note that posts from new members are moderated - please be patient with your
> first post.
> ---
> You received this message because you are subscribed to the Google Groups
> "ClojureScript" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojurescrip...@googlegroups.com.

kovas boguta

unread,
Mar 12, 2015, 8:18:58 PM3/12/15
to clojur...@googlegroups.com, clo...@googlegroups.com
Hi Karsten,

Technical usage question. 

I want to associate a color to each face of a cuboid, tesselate the cuboid, and end up with an array of vertices and an array of matching colors. 

My problem is associating the colors of the cuboid faces to their tessellated versions. AFAICT tessellation simply produces new faces and does not have facilities for propagating annotations from the old face to the new faces. Furthermore, because the faces are stored in an unordered set, it is not possible to somehow match the new faces to the old ones based on ordering, at least in this simple case.

I tried to work around this by supplying the face set as an empty vector to the mesh constructor. Unfortunately this doesn't work because the creation of the new mesh simply calls the default constructor function, so the new faces end up getting poured into a set anyway. 

If instead, it called (empty) on the faces of the supplied mesh, this workaround could work. However it is brittle, requiring to one know ahead of time how many new faces will be generated for each input face. 

Is there a better way to do this?

Thanks!

kovas boguta

unread,
Mar 12, 2015, 8:25:45 PM3/12/15
to clojur...@googlegroups.com, clo...@googlegroups.com
On Thu, Mar 12, 2015 at 8:18 PM, kovas boguta <kovas....@gmail.com> wrote:

I want to associate a color to each face of a cuboid, tesselate the cuboid, and end up with an array of vertices and an array of matching colors. 

To clarify, I want to turn the cuboid into a mesh, and then do the tessellation of the mesh. Tessellating the cuboid directly gives me the faces in an obvious predictable order. However I want the mesh b/c theres other computations I want to perform with it. 
 

Karsten Schmidt

unread,
Mar 13, 2015, 8:28:02 AM3/13/15
to clojur...@googlegroups.com, clo...@googlegroups.com

Hi Kovas, so far the mesh types (GMesh & BasicMesh) were mainly used for 3d printing rather than viz purposes and have not yet support for vertex or face attributes. It is something I still need to port over from the previous version of the lib. I held off on that so far to first let the WebGL conversion parts settle (almost done) and will address this in the next month. The aim is to provide an attribute structure allowing any type of attribute along with serializers for common attribs (UVs, colors, IDs) for WebGL and provide hooks to interpolate attribs (e.g. for subdivisions). Ultimately this might even become available for other types too, i.e. directly on the cuboid, aabb, lines etc.

As for the current state: I've created a gist showing how this can be achieved currently, in principle:

https://gist.github.com/postspectacular/894fc58d75005069a546

Thanks for the feedback, as always highly appreciated!

K.

kovas boguta

unread,
Mar 15, 2015, 3:49:38 PM3/15/15
to clojur...@googlegroups.com
Thanks!
Reply all
Reply to author
Forward
0 new messages