Playing with drawing ribbons in Fluxus (part of my mater plan to port all of my live-drawing software to Fluxus).
(This code is about 70% taken from Dave Griffith‘s L-Systems drawing code – thanks Dave!)
(clear) (texture (load-texture "test.png")) ;----- 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)] ) ;(display (vector x y 0))(newline) (vector x y 0)) ) (define (build-ellipse rmin rmaj num-verts) (define p (build-polygons (* 3 num-verts) 'triangle-list)) (with-primitive p (for ([i (in-range 0 (* 3 num-verts) 3) ]) (pdata-set! "p" i (vector 0 0 0)) (pdata-set! "n" i (vector 0 0 -1)) (pdata-set! "p" (+ i 1) (calc-xyz (/ i 3) num-verts rmin)) (pdata-set! "n" (+ i 1) (vector 0 0 -1)) (pdata-set! "p" (+ i 2) (calc-xyz (+ (/ i 3) 1) num-verts rmin)) (pdata-set! "n" (+ i 2) (vector 0 0 -1))) (poly-convert-to-indexed) ) p) ; 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))))) ;------------------------------------------------------ ; strokes are collections of points representing mouse movement (define-struct stroke (points ribb) #:mutable) (define (build-stroke) (make-stroke (list (vector 0 0 -40)) (build-ribbon 2))) ; start with a point in the middle of the screen (define (stroke-clear stroke) (set-stroke-points! stroke (list (vector 0 0 -40))) (set-stroke-ribb! (build-ribbon 2))) (define (stroke-add stroke pos) (set-stroke-points! stroke (cons pos (stroke-points stroke)))) (define (stroke-last-point stroke) (car (stroke-points stroke))) (define (stroke-update stroke) (destroy (stroke-ribb stroke)) (set-stroke-ribb! stroke (build-ribbon (length (stroke-points stroke)))) ; make a new point when the mouse is suitibly far from the last point (when (> (vdist (stroke-last-point stroke) (mouse-pos)) 2) (stroke-add stroke (mouse-pos))) (with-primitive (stroke-ribb stroke) (pdata-map! (lambda (w) 1.5) "w") (pdata-index-map! (lambda (n p) (list-ref (stroke-points stroke) n)) "p")) ) ; draw some blobs to indicate the path drawn ;(define (stroke-render stroke)) (define mp (with-state (colour (vector 1 1 1)) (build-ellipse 1 1 12))) ;------------------------------------------------------ ; a fluxus mouse pointer! (define (draw-mouse) (with-primitive mp (identity) (colour (vector 1 1 0)) (translate (mouse-pos)) (hint-unlit) )) (define stroke (build-stroke)) (define root (build-locator)) (define debounce #t) (define (breathe stroke) (with-primitive (stroke-ribb stroke) (pdata-map! (lambda (w) 1.5) "w") (pdata-index-map! (lambda (n w) (+ 1.2 (sin (time)))) "w")) ) (define (animate) (draw-mouse) (when (mouse-button 1) (stroke-update stroke)) (breathe stroke) ) (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 -50 50 0)) (every-frame (animate))