medusa – extruding drawing

medusa

Originally uploaded by da mad pixelist

I was playing around with Fluxus today and Dave’s new extruding library. Now I can make drawings out of a collection of different 3d shapes along a path, and animate them growing… very fun stuff. Hopefully this will make its way into a music video soon. Code included – needs cleanup for the web, references a list of texture images that I’m sure you don’t have (unless you hacked my precious laptop).

Oh, by the way, there is a subtle bug in the code where points get added to a “stroke” when they don’t exist – that’s why all lines connect to the center of the screen.  I didn’t fix it, though, because I like the effect (for now, anyway).  Happy scheming!

(clear)

(define (empty? l) (null? l))

(define txtr-path “/Users/evan/cvs/tmpflx/fluxus/drawing/textures/”)

(define txtr-names (list “truck-front.png” “kittenhead.png”
“car-front.png” “tv.png”
“circlt.png” “ol-fish.png”
“piece9.png” “routmastergrill.png”
“leatherchair.png” “cathair.png”
“texture_4.png” “moonclr.png”
“grillhair.png” “grillteeth.png”
“rose.png” “rustytextr.png”
)
)

; build texture list from file names and return it
(define (build-txtr-list txtr-names)
(for/list ([s txtr-names])
(load-texture (string-append txtr-path s))
))

(define txtrs (build-txtr-list txtr-names))

;— mix two numbers based on percent of first
(define (mix val1 val2 amt)
(+ (* val2 (- 1 amt)) (* val1 amt))
)

;—– return a vector on a circle based on index

(define (calc-xyz index max-index r)
(let*
( [angle (* 6.28312 (/ index (- max-index 1)))]
[x (* (cos angle) r)]
[y (* (sin angle) r)] )
(vector x y 0))
)

; gets a line representing a segment of the projection of the mouse into 3D space
; should move this into the fluxus scheme library
(define (get-line-from-mouse)
(let* ((ndcpos (vector (* (- (/ (mouse-x) (vx (get-screen-size))) 0.5) 2)
(* (- (- (/ (mouse-y) (vy (get-screen-size))) 0.5)) 1.5) -1))
(scrpos2 (vtransform (vmul ndcpos 50) (minverse (get-camera-transform))))
(scrpos (vtransform ndcpos (minverse (get-camera-transform)))))
(list scrpos scrpos2)))

; we’ll just use the end of the projection line here
(define (mouse-pos)
(cadr (get-line-from-mouse)))

; converts a 2D vector into an angle, with some dodgy dave maths
(define (2dvec->angle x y)
(let ((q (/ 3.141 2)))
(when (zero? y) (set! y 0.0001))
(cond
((>= y 0)
(fmod (* (+ q q q (- q (atan (/ x y)))) 57.2957795) 360))
(else
(fmod (* (+ q (- q (atan (/ x y)))) 57.2957795) 360)))))

;—–
;– extrusion builder funcs

(define profile (build-circle-profile 12 0.5))

(define empty-path ‘( (vector 0 0 0) (vector 0 0 0) ))

(define (extruder path)
(define a
(with-state
(wire-colour 0)
(colour (vector 1 1 1))
(specular (vector 1 1 1))
(shinyness 20)
(hint-wire)
(build-partial-extrusion profile path 1)))
a)

;——————————————————
; strokes are collections of points representing mouse movement

(define-struct stroke (points extr txtr rot) #:mutable)

(define (build-stroke)
(make-stroke (list) (extruder empty-path) (car txtrs) (vector 0 0 0)))

(define (stroke-clear stroke)
(set-stroke-extr! (extruder empty-path)))

(define (stroke-add stroke pos)
(set-stroke-points! stroke (append (stroke-points stroke) (list pos))))

(define (stroke-last-point stroke)
(cond
[(not (empty? (stroke-points stroke)))
(car (reverse (stroke-points stroke)))]
[else (vector -999 -999 -999)]
)
)

(define (stroke-update stroke)

; make a new point when the mouse is suitibly far from the last point
(when (> (vdist (stroke-last-point stroke) (mouse-pos)) 0.5)
(stroke-add stroke (mouse-pos))
;        (printf “point: ~a / ~a” (mouse-pos) (stroke-last-point stroke))(newline)
)

(destroy (stroke-extr stroke))
(set-stroke-extr! stroke (extruder (stroke-points stroke)))
)

(define (stroke-rotate stroke r)
(set-stroke-rot! stroke (vector 0 0 (fmod (+ (vector-ref (stroke-rot stroke) 2) r) 360)))
)

(define (stroke-advance stroke)
(cond ([not (empty? (stroke-points stroke))]
(let*
((lst (stroke-points stroke))
(1st (car lst))
(l (- (length lst) 1))
(last (list-ref lst l))
(prv (list-ref lst (- l 1)))
(diff (vsub prv last))
)
(set-stroke-points! stroke (append (cdr lst) (list diff)))
)
(stroke-update stroke)
))
)

;——————————————————

; a fluxus mouse pointer!
(define (draw-mouse)
(with-primitive mp
(identity)
(colour (vector 1 1 0))
(translate (mouse-pos))
(hint-unlit)
))

(define strokes (list))
(define mouseIsDown #f)

(define cstroke ‘())

(define last-txtr (car txtrs))

(define (draw-stroke s)
(with-state
(texture (stroke-txtr s))
(rotate (stroke-rot s))
(with-primitive (stroke-extr s)
(partial-extrude
(* (* 0.5 (+ 1 (sin (* 4 (time))))) (length (stroke-points s)))
profile
(stroke-points s)
(build-list (length (stroke-points s)) (lambda (n) 4))
(vector 0 0 1)
0.05)))
)

(define (draw-strokes strokes)
(cond [(not (empty? strokes))
(for/list ((s (reverse strokes)))
(draw-stroke s)
(stroke-rotate s rotz))
]
)
)

(define (print-stroke-points s)
(define points (stroke-points s))
(for/list ((p points))
(display p)(newline)))

;(start-audio “system:capture_3” 512 44100)

(define speed -20)

(define e (build-plane))

;——– useful state vars

(define rotz 0)
(define txoffset 0)

;——— where the drawing gets done!!!!

(define (animate)

;(hint-unlit)
(blur 0)
;(texture last-txtr)
(opacity 0.5)
;   (blend-mode ‘src-alpha ‘dst-alpha)
;    (blend-mode ‘src-alpha ‘one)

(hint-ignore-depth)
(colour (vector 1 1 1))

;   (draw-mouse)
(cond [(mouse-button 1)
;(display “down”)(newline)
(cond [(not mouseIsDown)
(set! mouseIsDown #t)
(set! cstroke (build-stroke))
(set-stroke-txtr! cstroke last-txtr)
]
)
(stroke-update cstroke)]

[else
(cond [ mouseIsDown
(set! strokes (cons cstroke strokes))
])
(set! mouseIsDown #f)
]
)

;            (audio-distort cstroke)

(draw-strokes strokes)

)

(set-camera-transform (mtranslate (vector 0 0 -10)))
(light-diffuse 0 (vector 0 0 0))
(define l (make-light ‘point ‘free))
(light-diffuse l (vector 1 1 1))
(light-position l (vector -10 10 0))

(every-frame (animate))