From 716cb9a7aaa9afbbc9a9016993a5fb9d2c4d7e3d Mon Sep 17 00:00:00 2001 From: Sasha Kovar Date: Tue, 23 May 2017 21:00:31 -0700 Subject: [PATCH] add molecule and gongshi --- src/voxelburst/core.clj | 254 +++++++++++++++++++++++++++++++++------- 1 file changed, 210 insertions(+), 44 deletions(-) diff --git a/src/voxelburst/core.clj b/src/voxelburst/core.clj index 1560fc5..b0f8753 100644 --- a/src/voxelburst/core.clj +++ b/src/voxelburst/core.clj @@ -13,8 +13,11 @@ [thi.ng.geom.voxel.isosurface :as iso] [thi.ng.geom.voxel.svo :as svo] [thi.ng.math.core :as m] - [clojure.math.numeric-tower :as math])) - + [clojure.math.numeric-tower :as math] + ;;[clisk.patterns :as patterns] + ) + (:import clisk.noise.Simplex)) + ;;; ;;; geometry ;;; @@ -28,6 +31,9 @@ (defn v-- [v1 v2] (mapv - v1 v2)) +(defn v-* [v1 v2] + (mapv * v1 v2)) + (defn round-point [v] (map math/round v)) @@ -35,41 +41,11 @@ "Return a set of points contained in the sphere." [origin radius] (let [rg (range (- radius) radius)] - (set (for [x rg, y rg, z rg - :let [v (vector x y z)] - :when (<= (v-mag v) radius)] (v-+ origin v))))) - -;;; -;;; trace -;;; - -(def start-radius 1.0) -(def start-lifespan 120) -(def radius-step 0 #_(/ start-radius start-lifespan)) - -(defrecord Trace [position velocity radius lifespan start-time]) - -(defn new-trace [origin] - (Trace. origin (random-vel) start-radius start-lifespan (+ 70 (rand-int 10)))) - -(defn drawing? [t bounds] - (and (in-draw-bounds? (:position t) bounds) - (> (:radius t) 0) - (> (:lifespan t) 0) - (< (:start-time t) 0))) - -(defn update-trace [trace bounds] - (let [t (Trace. (next-pos (:position trace) (:velocity trace)) - (next-vel (:velocity trace)) - (- (:radius trace) radius-step) - (dec (:lifespan trace)) - (dec (:start-time trace)))] - (if (and (in-bounds? (:position t) bounds) - (> (:lifespan t) 0)) - t - (do #_(println "died at " (:lifespan t)) - nil)))) + (for [x rg, y rg, z rg + :let [v (vector x y z)] + :when (<= (v-mag v) radius)] (v-+ origin v)))) + ;;; ;;; physics ;;; @@ -113,15 +89,55 @@ (or (<= v (- mid gap)) (>= v (+ mid gap)))))) +(defn shell-in-bounds? + [v [lo hi]] + (let [thickness 20] + (and (>= v lo) (<= v hi) + (or (<= v (+ lo thickness)) + (>= v (- hi thickness)))))) + (defn in-draw-bounds? "Inside complex box?" [p bounds] - (every? true? (map #(complex-single-in-bounds? %1 %2) p bounds))) + true + #_(some true? (map #(shell-in-bounds? %1 %2) p bounds))) -#_(defn in-bounds? +(defn sphere-in-bounds? "Inside sphere?" [p bounds] - (<= (v-mag (v-- p [500 500 500])) 400)) + (<= (v-mag (v-- p [500 500 500])) 200)) + + +;;; +;;; trace +;;; + +(def start-radius 1.0) +(def start-lifespan 120) +(def radius-step 0 #_(/ start-radius start-lifespan)) + +(defrecord Trace [position velocity radius lifespan start-time]) + +(defn new-trace [origin] + (Trace. origin (random-vel) start-radius start-lifespan (+ 70 (rand-int 10)))) + +(defn drawing? [t bounds] + (and (in-draw-bounds? (:position t) bounds) + (> (:radius t) 0) + (> (:lifespan t) 0) + (< (:start-time t) 0))) + +(defn update-trace [trace bounds] + (let [t (Trace. (next-pos (:position trace) (:velocity trace)) + (next-vel (:velocity trace)) + (- (:radius trace) radius-step) + (dec (:lifespan trace)) + (dec (:start-time trace)))] + (if (and (in-bounds? (:position t) bounds) + (> (:lifespan t) 0)) + t + (do #_(println "died at " (:lifespan t)) + nil)))) (defn trace-trajectory [trace bounds] @@ -148,18 +164,168 @@ (repeatedly count #(trace-trajectory (new-trace origin) bounds))) -;;; -;;; tie it together -;;; - (defn trace-tree [count] (let [tree (svo/voxeltree 1000 1.0) trace (sample-traces count)] (svo/apply-voxels svo/set-at tree trace))) -(defn sample-write-ply +(defn trace-write-ply [count] (time (with-open [o (io/output-stream "sample.ply")] (let [tree (time (trace-tree count))] (mio/write-ply o (g/tessellate (g/scale (iso/surface-mesh tree 5 0.9) 0.01))))))) + + +;;; +;;; points +;;; + +(defn point-voxels [point] + (sphere point 2)) + +(defn rand-int-between [low high] + (+ low (rand-int (- high low)))) + +(defn new-point [bounds] + (mapv #(rand-int-between (first %) (second %)) bounds)) + +(defn hollow-sphere-in-bounds? + "Inside sphere?" + [p bounds] + (let [thickness 30 + radius 300 + p-mag (v-mag (v-- p [500 500 500]))] + (and (<= p-mag radius) + (>= p-mag (- radius thickness))))) + +(defn sample-point [] + (let [bounds (vec (repeat 3 [200 800])) + point (new-point bounds)] + (if (hollow-sphere-in-bounds? point bounds) + (point-voxels point) + (recur)))) + +(defn sample-points [count] + (reduce set/union (repeatedly count sample-point))) + +(defn point-tree [count] + (let [tree (svo/voxeltree 1000 1.0) + points (sample-points count)] + (svo/apply-voxels svo/set-at tree points))) + +(defn points-write-ply + [count] + (time + (with-open [o (io/output-stream "points.ply")] + (let [tree (time (point-tree count))] + (mio/write-ply o (g/tessellate (g/scale (iso/surface-mesh tree 5 0.9) 0.01))))))) + + +;;; +;;; molecule +;;; + +(defn rand-int-between [low high] + (+ low (rand-int (- high low)))) + +(defn new-point [bounds] + (mapv #(rand-int-between (first %) (second %)) bounds)) + +(defn molecule-point [] + (let [bounds (vec (repeat 3 [350 650])) + point [363 456 540] #_(new-point bounds)] + (if (in-draw-bounds? point bounds) + point + (recur)))) + +(defn take-percent [pct coll] + (set (filter (fn [_] (< (rand-int 100) pct)) coll))) + +(defn count-n-print [msg set] + (println msg (count set)) + set) + +(defn molecule-points [count density] + (let [centers (repeatedly count molecule-point)] + (println "centers" centers) + (reduce set/union (map (fn [x] (take-percent density (sphere x 10 #_(+ 20 (rand-int 30))))) centers)))) + +(defn molecule-tree [count density] + (let [tree (svo/voxeltree 1000 1) + points (molecule-points count density)] + (svo/apply-voxels svo/set-at tree points))) + +(defn molecule-write-ply + [count density depth] + (with-open [o (io/output-stream "molecule.ply")] + (let [tree (time (molecule-tree count density))] + (mio/write-ply o (time (g/tessellate (g/scale (time (iso/surface-mesh tree depth 0.9)) 0.01))))))) + + +;;; +;;; scholar stones +;;; + +#_(defn rand-int-between [low high] + (+ low (rand-int (- high low)))) + +#_(defn new-point [bounds] + (mapv #(rand-int-between (first %) (second %)) bounds)) + +#_(clisk.noise.Simplex/noise 0 0 0 1) + +#_(defn molecule-point [] + (let [bounds (vec (repeat 3 [350 650])) + point [363 456 540] #_(new-point bounds)] + (if (in-draw-bounds? point bounds) + point + (recur)))) + +(defn gongshi-points [radius] + (sphere [500 500 500] radius)) + +(defn average [coll] + (/ (reduce + coll) (count coll))) + +(defn noise-at + "Return the simplex noise value (0-1) for the scaled point." + [p scale] + (apply #(clisk.noise.Simplex/noise %1 %2 %3) (v-* scale p))) + +(defn noise-sum [p scale] + (let [first (noise-at p scale) + second (noise-at p (v-* scale (repeat 2))) + ;;third (noise-at p (v-* scale (repeat 4))) + ;;fourth (noise-at p (v-* scale (repeat 6))) + ] + (average [first second]))) + +#_(defn noise-sum [p scale] + (noise-at p scale)) + +(defn filter-noise [coll scale cutoff] + (filter (fn [p] (> (noise-sum p scale) cutoff)) coll)) + +(defn gongshi-tree [radius scale cutoff] + (let [tree (svo/voxeltree 1000 1) + points (filter-noise (gongshi-points radius) scale cutoff)] + (svo/apply-voxels svo/set-at tree points))) + +(defn gongshi-write-ply + [radius scale cutoff depth] + (with-open [o (io/output-stream "gongshi.ply")] + (let [tree (time (gongshi-tree radius scale cutoff))] + (mio/write-ply o (time (g/tessellate (g/scale (time (iso/surface-mesh tree depth 0.9)) 0.01))))))) + +;; (gongshi-write-ply 150 0.003 0.5 8) + + + +;; shell instead of filled +;; multiple primitives linked by tendrils +;; tweak surface mesh generation - add curves +;; https://github.com/cmaher/noise +;; https://github.com/mikera/clisk/ +;; take 2d image or 3d input +