Skip to content

Instantly share code, notes, and snippets.

@minikomi
Last active January 20, 2017 04:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save minikomi/f513a1a897f6e739f41592232902c4a4 to your computer and use it in GitHub Desktop.
Save minikomi/f513a1a897f6e739f41592232902c4a4 to your computer and use it in GitHub Desktop.
(ns fractal.core
(:require [arcadia.core :as a]
[arcadia.linear :as l])
(:import
[UnityEngine Mesh
Material Time MeshFilter WaitForSeconds
MonoBehaviour
Color
MeshRenderer Shader]
[System.Collections IEnumerator]
MonoObj
))
(defn get-fractal []
(or (first (a/objects-named "Fractal"))
(GameObject. "Fractal")))
(def shared-material (Material. (Shader/Find "Standard")))
(defn rotate-fractal [go]
(.. go transform
(Rotate
(* 35 Time/deltaTime)
(* -20 Time/deltaTime) 0)))
(defn init-fractal []
(when-let [f (a/object-named "Fractal")]
(a/destroy f))
(let [f (a/create-primitive :cube)]
(set! (.. f name) "Fractal")
(set! (.. (a/cmpt f MeshRenderer) material) shared-material)
(a/set-state! f
:max-depth 4)
(a/set-state! f
:child-scale 0.5)
(a/hook+ f :update #'rotate-fractal)
f))
(defn do-later [n f]
(let [waited (volatile! false)
coro-root (a/object-typed MonoBehaviour)]
(.StartCoroutine
coro-root
(reify IEnumerator
(MoveNext [this]
(if @waited
(f)
(do
(vswap! waited not)
true)))
(get_Current [this] (WaitForSeconds. n))))))
(def colors (mapv (fn [[r g b]] (Color. (/ r 255) (/ g 255) (/ b 255)))
[[120 120 0]
[120 120 120]
[0 120 0]
[0 120 120]
]))
(def shared-mat (MeshRenderer.))
(def cube-pool
(atom
(vec
(take 6000
(repeatedly
(fn []
(let [c (a/create-primitive :sphere)]
(.SetActive c false)
c)))))))
(defn reset-pool []
(doseq [c @cube-pool]
(.SetActive c false)))
(defn get-cube []
(or (some #(and (not (.activeSelf %)) %) @cube-pool)
(let [new-cube (a/create-primitive :cube)]
(swap! cube-pool conj new-cube)
new-cube
)))
(defn create-dirs [down?]
(let [base-dirs
[[0 Vector3/up Quaternion/identity]
[1 Vector3/right (Quaternion/Euler 0 0 -90.0)]
[2 Vector3/left (Quaternion/Euler 0 0 90.0)]
[3 Vector3/forward (Quaternion/Euler 90.0 0 0)]
[4 Vector3/back (Quaternion/Euler -90.0 0 0)]]]
(if down?
(conj base-dirs [5 Vector3/down (Quaternion/Euler 0 -90.0 0)])
base-dirs
)))
(defn fractal-step [^GameObject parent
depth
down?]
(when (> (a/state (get-fractal) :max-depth) depth)
(doseq [[n
direction
orientation]
(create-dirs down?)]
(let [^GameObject new-child (get-cube)]
(.SetActive new-child true)
(set! (.. new-child transform localScale)
(l/v3* Vector3/one (a/state (get-fractal) :child-scale)))
(set! (.. new-child transform localPosition)
(l/v3* direction (+ 0.5
(* 0.5
(a/state (get-fractal) :child-scale)))))
(set! (.. new-child transform localRotation)
orientation)
(set! (.. (a/cmpt new-child MeshRenderer) material)
(.. (a/cmpt parent MeshRenderer) material))
(set! (.. (a/cmpt new-child MeshRenderer) material color)
(get colors (mod (+ depth n) (count colors))))
(a/child+ parent new-child)
(do-later
(+ n (rand 4))
(fn [] (fractal-step new-child
(inc depth)
(and down? (= n 5)))))))))
(comment
(a/destroy (get-fractal))
(init-fractal)
(reset-pool)
(fractal-build (get-fractal) 0 true)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment