Toad Circle particle system

Playing with a circular particle system based on a water simulation, done using Fluxus (http://pawfal.org/fluxus). Energy is tranferred between adjacent toads, so after time they start to bounce back and forth chaotically.

Code:

; a simple script that looks like it could be made into a 
; water simulation of some kind

(clear)

(require fluxus-016/shapes)

(hint-ignore-depth)

; dimensions of the circles
(define elems 20)
; angle between each element
(define elem-angle (/ 3.14156 elems))


; simulation constants
(define max-dist 10)
(define max-dist-sq (* max-dist max-dist))

(define min-dist 4)
(define min-dist-sq (* min-dist min-dist))

(define max-vel-mag 0.1)

; stops the simulation going out of control
(define max-vel (vmul (vector (cos elem-angle) (sin elem-angle) 0) max-vel-mag)) 
(define max-vel-sq (vdist-sq max-vel (vector 0 0 0)))
(define trans 0.008)  ; the amount the energy transmitted to 
; the neighboring vertex


; feedback velocity per frame
(define feedback 0.1)

; complexity of initial positions (sin peaks, basically)
(define complexity 4)

; make a list of points in a circle
(define circle-points (build-circle-points elems 1))

(define tex (load-texture "/Users/evan/cvs/newflx/fluxus/textures/whitetoady.png"))

(define s (build-particles elems))

(with-primitive s
    
    (pdata-add "vel" "v")
    (pdata-add "v0" "v")
    (pdata-add "p0" "v")
    
    (pdata-index-map! 
        (lambda (i p)
            (list-ref circle-points i))
        "p")
    
    ; copy default pos at radius 1
    (pdata-copy "p" "p0")
    
    ; scale circle radius
    (pdata-index-map! 
        (lambda (i p)
;            (vmul p (+ (* (* 0.5 (+ 1 (sin (* 3.4156 (/ i elems))))) 
;                (- max-dist min-dist)) min-dist)))
            (vmul p (* (* 0.5 (+ 1 (sin (* complexity (* 3.4156 (/ i elems)))))) max-dist))) 

        "p")
    
    ; start off the simulation with random point distances
;    (pdata-index-map! 
;        (lambda (i p)
;            (vadd p (vmul p (* (* max-dist 0.4) (crndf)) )))
;        "p")
    
    (pdata-index-map! 
        (lambda (i vel p)
            (vmul p (/ max-dist 10)))
        "vel" "p")
    
    ; store initial velocity  
    (pdata-copy "vel" "v0")
    
    ; start off the simulation with random colours
    (pdata-map! 
        (lambda (c)
            (rndvec))
        "c")
    
    
    
    ; start off the simulation with random colours
    (pdata-map! 
        (lambda (s)
            (vector 2 2 0.6))
        "s")
    )


(define (simulate n)
    (cond [(< n 0) 0]
        [else
            
            
            (let* [(result (pdata-get "vel" n)) 
                    (p (pdata-get "p" n))
                    (p-sq (vdist-sq p (vector 0 0 0)))]
                
                (cond [(> p-sq max-dist-sq)
                        ;                        (display "max")(newline)
                        ; we are above "sea level" head down
                        (pdata-set "vel" n (vmul (pdata-ref "vel" n) -0.9))
                        ;                        (pdata-set "vel" n (vmul (pdata-ref "v0" n) -1))
                        (pdata-set "p" n (vmul (pdata-ref "p0" n) max-dist))
                        ]
                    [(< p-sq min-dist-sq)
                        ;                        (display "mIN")(newline)
                        ; we are below "sea level" head up
                        ;                        (pdata-set "vel" n (pdata-ref "v0" n))
                        (pdata-set "vel" n (vmul (pdata-ref "vel" n) -0.9))
                        (pdata-set "p" n (vmul (pdata-ref "p0" n) min-dist))
                        ]
                    [else
                        
                        (let [(pv (* (vdist (pdata-get "vel" (- n 1)) (vector 0 0 0)) trans))
                                (nv (* (vdist (pdata-get "vel" (+ n 1)) (vector 0 0 0)) trans))]
                            
                            
                            ; mix in the surrounding verts to transmit energy around
                            (set! result (vadd result 
                                    (vmul result pv)))
                            
                            (set! result (vadd result 
                                    (vmul result nv)))
                            
                            ; add the result to the existing velocity
                            
                            (pdata-set "vel" n (vadd (pdata-get "vel" n) (vmul result feedback)))
                            ;(pdata-set "vel" n (vadd (pdata-get "vel" n) result))
                            )
                        ]
                    )
                
                (let* [ 
                        (v (pdata-get "vel" n))
                        (v0 (pdata-get "v0" n))
                        (vmax (vmul v0 max-vel-mag))
                        (v-sq (vdist-sq v (vector 0 0 0)))]
                    ; clamp the velocity - this stops the 
                    ; simulation going too fast and blowing up
                    (cond [(> v-sq max-vel-sq)
                            ; divide by mag to get sign, mult by max-vel
                            (pdata-set "vel" n (vmul (vmul v (/ 1 (vmag v))) max-vel-mag))
                            ]
                        )
                    )
                
                
                )
            
            
            (simulate (- n 1))
            ]
        )
    )

(define (render)
    (set! feedback (* 0.4 0.5 (+ 1 (sin (* 0.3 (time))))))
    (with-primitive s
     (rotate (vector 0 0 2))
        (texture tex)
        (simulate (pdata-size)) 
        (pdata-op "+" "p" "vel")
;        (recalc-normals 1)
        )
    )


(every-frame (render))