clojure-art 2023-02-25

I'm having a lot of fun generating Lego models with Clojure and then rendering them with http://Stud.io, here's my two favorite gifs that I've made so far.

🎨 3
πŸ†’ 6
🀯 1

@danielmartincraig some time ago, I had a shelved project that was basically a limited LEGO editor that was modal and keyboard-focused and could be scripted, as well!

❀️ 1
😱 1

@hendursaga469 that sounds awesome! Is that project open source?

That is fantastic. Had no idea there were tools to help (but of course there are, on the internet… πŸ™‚ ) Care to explain the process a bit more?

Thanks so much for writing it up!

No, it's not, sorry! I didn't get too far beyond the conceptual, but I did find a good base to start on: there's this ANCIENT program buried in LDraw called LEdit and then there's also https://deeice.github.io/ldglite/

My idea was, until I became more proficient at 3D rendering and such, to use the C rendering part of the above and simply pass the ldraw output generated by the Lisp side along each time. I couldn't settle on which Lisp to use.

Yeah, I would also be really interested in how this came about.

I'm really flattered! So the way this is done is that I wrote a little program that writes an https://www.ldraw.org/article/218.html file, the details of the format are in the link but basically it's the open standard for modeling with Legos. I write each part as its own line in the ldraw file, (keeping in mind the dimensions of the lego brick, 20 x 20 x 24 Lego Draw Units). In the conventions of the ldraw file format, one part out of a lego model looks like this:

1 4 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 -1.0 0.0 0.0 18654.dat
where which is generalized as
1 <colour> x y z a b c d e f g h i <file>
The leading 1 declares that this is a lego part, the color is represented by an integer, and the x y z a b c d e f g h i represent a transformation matrix in either of the following forms:
/ a d g 0 \   / a b c x \
| b e h 0 |   | d e f y |
| c f i 0 |   | g h i z |
\ x y z 1 /   \ 0 0 0 1 /
And here is my code snippet that does the magic:

(ns greenbeam.core
  (:gen-class)
  (:require [clojure.string :as str]
            [ :as io]
            [clojure.core.matrix :as matrix]))

(defn part [color [[a b c x] [d e f y] [g h i z] _] file]
  [1 color x y z a b c d e f g h i file])

(defn pin-connector-perpendicular-3L-with-4-pins
  [color x y z a b c d e f g h i]
  (part color x y z a b c d e f g h i "3005.dat"))

(def origin (matrix/identity-matrix 4))

;; 90 degree in y direction
(def xm1 [[0 0 1 0]
          [0 1 0 0]
          [-1 0 0 0]
          [0 0 0 1]])

;; 90 degree in x direction
(def xm2 [[1 0 0 0]
          [0 0 -1 0]
          [0 1 0 0]
          [0 0 0 1]])

(def intervals-of-twenty (iterate #(+ % 20) 0))

(defn xmf [x y z]
  [[1 0 0 x]
   [0 1 0 y]
   [0 0 1 z]
   [0 0 0 1]])

(defn brick18654
  [color xm]
  (part color xm "18654.dat")
  )

(defn get-locations [n]
  (for [x (take n intervals-of-twenty)
        y (take n intervals-of-twenty)
        z (take n intervals-of-twenty)]
    (xmf x y z)))

(defn write-file
  [filename & _]
  (let [locations (get-locations 30)
        rotated-locations (map #(matrix/transform % (rand-nth [xm1 xm2 origin])) locations)
        parts (map #(brick18654 %1 %2) (repeatedly #(rand-int 7)) rotated-locations)]
    (spit filename (str/join " " ["0" "FILE" filename "\n"]))
    (doseq [part parts]
      (spit filename (str/join " " part) :append true)
      (spit filename "\n" :append true))))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (let [filename "model.ldr"]
    (write-file filename)))

As implemented, this will generate quite a large (30x30) block of 1L techic liftarms in random colors.

Then I open the .ldr file with http://stud.io and I render it

The code above is a bit crufty, not really ready for the gaze of the world, but such as it is, I give it to you 😁

Wow! Thanks! We'll go forth and create the equivalent of Mandalas in Lego now πŸ˜„

That's a great idea

Maybe there's demand for a declarative Clojure DSL for lego creations

βœ… 1

I'm interested in writing a technic-focused CAD tool, with physics and stuff

Here's another, not quite as favorite but still pretty cool

πŸ†’ 3