;; p l a n t e y e s [ copyright (c) 2009 foam vzw : gpl v3 ] #lang scheme/base (require scheme/class fluxus-016/fluxus fluxus-016/shapes "sound.ss" "message.ss" "list-utils.ss" "ornament-views.ss") (provide (all-defined-out)) ; the fluxus code to make things look the way they do (define debug-messages #f) ; prints out all the messages sent to the renderer (define (ornament-colour) (vector 0.7 0.7 0.7)) (define (pickup-colour) (vector 1 1 1)) (define (earth-colour) (vector 0.2 0.15 0.1)) (define (dust-colour) (vmul (vector 0.05 0.05 0.05) (* 2 (rndf)))) (define (stones-colour) (vmul (vector 0.5 0.5 0.5) (* (crndf) 0.5))) (define (alive-colour) (vmul (vector 1 1 1) (+ 0.5 (* (rndf) 0.5)))) (define (worm-colour) (vmul (vector 0.8 0.8 0.8) (+ 0.5 (* (rndf) 0.5)))) (define wire-mode #f) (define fog-col (earth-colour)) (define fog-strength 0.1) (define default-grow-speed 0.5) (define grow-overshoot 10) (define min-fin-len 3) (define fin-length-var 4) (define fin-grow-prob 200) (define max-fins-per-twig 5) (define above-fog-col (vector 0.9 1 0.95)) (define above-fog-strength 0.01) (define ground-change-duration 4) (define (pre-ripple) (when (not (pdata-exists? "rip-pref")) (pdata-copy "p" "rip-pref"))) (define (ripple t speed wave-length) (pdata-map! (lambda (p pref) (vadd pref (vmul (srndvec) (* 0.1 (+ 1 (sin (+ (* t speed) (* wave-length (vdist (vtransform p (minverse (get-transform))) (vector 0 0 0)))))))))) "p" "rip-pref")) (define (fract n) (- n (floor n))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define dust% (class object% (field (rate 1) (above-ground #f) (next-p 0) (root (let ((p (with-state (colour 0) (hint-depth-sort) (texture (load-texture "textures/particle.png")) (build-particles 1000)))) (with-primitive p (pdata-map! (lambda (c) (vector 0 0 0 0.01)) "c") (pdata-map! (lambda (p) (vmul (srndvec) 100)) "p") (pdata-map! (lambda (s) (let ((s (* 4 (rndf)))) (vector s s s))) "s")) p)) (emitter (with-state (build-locator))) (pos (with-primitive root (vtransform (vector 0 0 0) (get-global-transform))))) (define/public (set-above-ground s) (set! above-ground s) (with-primitive root (colour (if s 1 0)) (pdata-map! (lambda (c) (if s (vector 1 1 1 0.01) (vector 0 0 0 0.01))) "c"))) (define/public (update t d) (let ((emitter-pos (with-primitive emitter (identity) (translate (vmul pos -1)) ; makes the particles relative to the centre of the plant (concat (get-locked-matrix)) ; which makes the depth sorting work better (translate (vector 0 0 -10)) (vtransform (vector 0 0 0) (get-transform))))) (with-primitive root (for ((i (in-range 0 rate))) (pdata-set! "p" next-p (vadd emitter-pos (vmul (srndvec) 10))) (pdata-set! "c" next-p (if above-ground (vector 1 1 1 0.01) (vector 0 0 0 0.01))) (pdata-set! "s" next-p (let ((s (* 4 (rndf)))) (vector s s s))) (set! next-p (+ next-p 1))) (pdata-op "*" "c" 1.04) (pdata-op "*" "s" 0.995)))) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define insect-view% (class object% (init-field (id 0) (from (vector 0 0 0)) (type 'none)) (field (to (vector 0 0 0)) (from-dir (vector 1 0 0)) (to-dir (vector 1 0 0)) (time 0) (tick 1)) (define/public (move pos dur) (set! from to) (set! from-dir to-dir) (set! to pos) (set! to-dir (vnormalise (vsub from to))) (set! time 0) (set! tick dur)) (define/public (update t d) (set! time (+ time d))) (define/public (do-tx t d) (let* ((t (min (/ time tick) 1)) (h (hermite-tangent from to (vmul from-dir 2) (vmul to-dir 2) t))) (translate (car h)) (concat (maim (vector 0 0 1) (vnormalise (cadr h))))) (set! time (+ time d))) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define (add-blendshape key model) (let ((b (load-primitive model)) (pname (string-append "p" (number->string key)))) (pdata-add pname "v") (pdata-index-map! (lambda (i p) (with-primitive b (pdata-ref "p" i))) pname) (destroy b))) (define (set-blendshape key) (pdata-copy (string-append "p" (number->string key)) "p")) (define spider-insect-view% (class insect-view% (inherit-field from to from-dir to-dir time tick) (inherit do-tx) (field (root (let ((p (with-state (hint-unlit) (colour (vector 0 0 0)) (load-primitive "meshes/spider-1.obj")))) (with-primitive p (pdata-copy "p" "p0") (add-blendshape 1 "meshes/spider-2.obj") (add-blendshape 2 "meshes/spider-3.obj") p))) (anim-t 0) (anim-d (* 0.2 (rndf))) (blendshape 0)) (define/override (update t d) (with-primitive root (when (> anim-t anim-d) (set! anim-t 0) (set! blendshape (modulo (+ blendshape 1) 3)) (set-blendshape blendshape)) (identity) (do-tx t d) (scale 1)) (set! anim-t (+ anim-t d))) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define butterfly-insect-view% (class insect-view% (inherit-field from to from-dir to-dir time tick) (inherit do-tx) (field (root (let ((p (build-locator))) (with-state (colour (rndvec)) (parent p) (hint-depth-sort) (hint-unlit) (backfacecull 0) (texture (load-texture "textures/butterfly.png")) (load-primitive "meshes/butterfly.obj") (translate (vector 0 0.001 0)) (load-primitive "meshes/butterfly.obj")) p))) (define/override (update t d) (with-primitive root (let ((a (* 90 (rndf)))) (with-primitive (car (get-children)) (rotate (vector 0 0 a))) (with-primitive (cadr (get-children)) (rotate (vector 0 0 (- a))))) (identity) (do-tx t d) (scale 1)) (set! time (+ time d))) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define worm-insect-view% (class insect-view% (inherit-field from to from-dir to-dir time tick) (field (hidden #t) (from2 (vector 0 0 0)) (from-dir2 (vector 0 0 0)) (root (let ((p (build-ribbon 20))) (with-primitive p (translate (vector 0 0 -0.1)) (hint-depth-sort) ;(hint-unlit) (colour (worm-colour)) (texture (load-texture "textures/worm.png")) (let ((width (+ 0.5 (* 0.5 (rndf))))) (pdata-index-map! (lambda (i w) width #;(+ 0.05 (* (abs (sin (* i 0.5))) 0.1))) "w")) #;(pdata-map! (lambda (c) (vector 1 1 1)) "c")) p))) (define/override (move pos dur) (set! from2 from) (set! from to) (set! from-dir2 from-dir) (set! from-dir to-dir) (set! to pos) (set! to-dir (vmul (vsub to from) 5)) (set! time 0) (set! tick dur)) (define/override (update t d) (let ((nt (/ time tick))) ; normalise time (with-primitive root (pdata-index-map! (lambda (i p) (let ((st (- nt (* i 0.05)))) (if (< st 0) (hermite from2 from (vmul from-dir2 2) (vmul from-dir 2) (+ st 1)) (hermite from to (vmul from-dir 2) (vmul to-dir 2) st)))) "p"))) (set! time (+ time d))) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define (build-squiggle x y) (let ((p (build-ribbon 30)) (x (/ x 10)) (y (/ y 10))) (with-primitive p (pdata-index-map! (lambda (i p) (vector (cos (/ i x)) (sin (/ i y)) (/ i (pdata-size)))) "p") (pdata-index-map! (lambda (i p) (* 0.1 (sin (* 3.141 (/ i (pdata-size)))))) "w") (pdata-map! (lambda (c) (vector 1 1 1)) "c") (recalc-bb)) p)) (define pickup-view% (class object% (init-field (id -1) (type 'none) (pos (vector 0 0 0))) (field (rot (vmul (rndvec) 360)) (root (with-state (translate pos) (rotate rot) (colour (pickup-colour)) (emissive (pickup-colour)) (hint-frustum-cull) (cond ; 0127461816 ((eq? type 'wiggle) (build-squiggle 4 2)) ((eq? type 'leaf) (build-squiggle 2 4)) ((eq? type 'curly) (build-squiggle 4 6)) ((eq? type 'nutrient) (build-squiggle 2 2)) ((eq? type 'horn) (build-squiggle 3 4)) ((eq? type 'inflatoe) (build-squiggle 4 5)) ((eq? type 'fork) (build-squiggle 5 2)) ((eq? type 'flower) (build-squiggle 4 3))))) (from pos) (destination (vector 0 0 0)) (speed 0.05) (t -1)) (define/public (pick-up) (destroy root)) (define/public (get-root) root) (define/public (move-to s) (set! t 0) (set! from pos) (set! destination s)) (define/public (update t d) (with-primitive root (rotate (vector (* d 10) 0 0))) #;(when (and (>= t 0) (< t 1)) (set! pos (vadd pos (vmul (vsub destination from) speed))) (with-primitive root (identity) (translate pos) (rotate rot)) (set! t (+ t speed)))) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define twig-view% (class object% (init-field (id 0) (pos (vector 0 0 0)) (type 'none) (dir (vector 0 1 0)) (radius 1) (num-points 0)) (field (index 0) (parent-twig-id -1) (child-twig-ids '()) (ornaments '()) (col (vector 1 1 1)) (tex "") (markers '()) (shrink-t 0) (grow-t -1) (marker-destroy-t 0) (grow-speed default-grow-speed) (delme #f)) (define/public (get-id) id) (define/public (delme?) delme) (define/public (get-dir) dir) (define/public (set-dir! s) (set! dir s)) (define/public (set-col! s) (set! col s)) (define/public (set-tex! s) (set! tex s)) (define/public (get-pos) pos) (define/public (build) 0) (define/public (get-num-points) index) (define/public (get-grow-t) grow-t) (define/public (set-pos! s) (set! pos s)) (define/public (get-child-twig-ids) child-twig-ids) (define/public (get-root) (error "need to overide this")) (define/public (destroy-twig) (destroy (get-root))) (define/public (set-parent-twig-id s) (set! parent-twig-id s)) (define/public (get-point point-index) (error "need to overide this")) (define/public (get-width point-index) (error "need to overide this")) (define/public (set-grow-speed s) (set! grow-speed s)) (define/public (add-child-twig-id twig-id) (set! child-twig-ids (cons twig-id child-twig-ids))) (define/public (growing?) (< grow-t (+ num-points grow-overshoot))) (define/public (start-growing) (set! grow-t 0) (set! markers (cons (build-locator) markers))) (define/public (start-shrinking) (set! shrink-t (if (growing?) grow-t (+ num-points grow-overshoot)))) (define/pubment (add-point point width make-marker) (play-sound "snd/event01.wav" point (+ 0.1 (rndf)) 0.3) (when make-marker (set! markers (append markers (list (with-state (parent (get-root)) (translate point) (scale 0.1) (shader "shaders/toon.vert.glsl" "shaders/toon.frag.glsl") (colour col) (build-sphere 8 8)))))) (inner (void) add-point point width make-marker)) (define/public (add-ornament point-index property) (when (< point-index grow-t) (play-sound "snd/nix.00203.wav" (get-point point-index) (+ 0.1 (rndf)) 0.3) (with-state (parent (get-root)) (let ((ornament (property->ornament property (get-point point-index) (get-width point-index) (vnormalise (vsub (get-point point-index) (get-point (- point-index 1)))) col))) ; check above ground (let ((pos (with-primitive (get-root) (vtransform (vector 0 0 0) (get-global-transform))))) (if (not (and (send ornament above-ground-only?) (< (vy (vadd pos (get-point point-index))) 1))) ; todo - delete existing ornaments here (set! ornaments (cons (list point-index ornament) ornaments)) (send ornament destroy-ornament))))))) (define/pubment (set-excitations! a b) (for-each (lambda (ornament) (send (cadr ornament) set-excitations! a b)) ornaments)) (define/pubment (update t d) (for-each (lambda (ornament) (send (cadr ornament) update t d)) ornaments) (when (> shrink-t 0) (set! shrink-t (- shrink-t (* d grow-speed)))) (when (< shrink-t 0) (set! delme #t)) (inner (void) update t d) (when (and (not (eq? grow-t -1)) (< grow-t (+ num-points grow-overshoot))) (set! grow-t (+ grow-t (* d grow-speed))) (when (and (not (null? markers)) (> 0 (- marker-destroy-t grow-t))) ; soundtodo: marker gobble (set! marker-destroy-t (+ 1 marker-destroy-t)) (destroy (car markers)) (set! markers (cdr markers)))) (when (> grow-t (+ num-points 10)) (set! grow-t 999))) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define ribbon-twig-view% (class twig-view% (inherit-field pos radius num-points index col tex grow-t) (field (root 0) (widths '()) (points '()) (global-growth 0) (global-growth-time 100)) (define/override (build) (set! root (let ((p (with-state (translate pos) (colour (vmul col 0.2)) (hint-unlit) (texture (load-texture "textures/ribbon-twig.png")) (build-ribbon num-points)))) (with-primitive p (pdata-map! (lambda (w) 0) "w") (pdata-set! "w" 0 radius)) p))) (define/override (get-root) root) #;(define/override (get-point point-index) (with-primitive root (pdata-ref "p" point-index))) #;(define/override (get-width point-index) (with-primitive root (pdata-ref "w" point-index))) (define/override (get-point point-index) (list-ref points point-index)) (define/override (get-width point-index) (list-ref widths point-index)) (define/augment (add-point point width make-marker) #;(with-primitive root (pdata-index-map! ; set all the remaining points to the end (lambda (i p) ; in order to hide them (if (< i index) p point)) "p")) (set! widths (append widths (list width))) (set! points (append points (list point))) (set! index (+ index 1))) (define/augment (update t d) (when (and (> grow-t 0) (< grow-t (+ (length points) 10))) (with-primitive root (pdata-index-map! (lambda (i w) (* (/ global-growth global-growth-time) (cond ((< i (- grow-t 1)) (list-ref widths i)) ((< i grow-t) (* (list-ref widths i) (fract grow-t))) (else 0)))) "w") (pdata-index-map! (lambda (i p) (cond ((< i (- grow-t 1)) (list-ref points i)) ((equal? i (inexact->exact (floor (+ grow-t 1)))) (vmix (list-ref points i) (list-ref points (- i 1)) (fract grow-t))) (else (list-ref points i)))) "p"))) (when (< global-growth global-growth-time) (set! global-growth (+ global-growth d)))) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; bunches of ribbon twigs (define twiglets% (class object% (init-field (par 0)) (field (twigs '())) (define/public (build pos dir width length) (set! twigs (list (build-tree pos dir width length)))) (define (build-tree pos dir width length) (let ((t (make-object ribbon-twig-view% 0 pos 'ribbon dir (* width (+ 0.5 (rndf))) length))) (send t set-grow-speed 0.1) (with-state (parent par) (send t build)) (let ((m (mrotate (vmul (srndvec) 45))) (ppos (vector 0 0 0))) (for ((i (in-range 0 length))) (let ((dir (vtransform (send t get-dir) m)) (width (if (eq? i (- length 1)) 0 (/ width (+ i 1))))) (send t set-dir! dir) (send t add-point ppos width #f) (set! ppos (vadd ppos (vmul dir (* 5 width))))))) (send t start-growing) t)) (define/public (update t d) (for-each (lambda (twig) (send twig update t d) (when (and (< (length twigs) 20) (> (send twig get-num-points) 2) (zero? (random 400))) (let ((pi (inexact->exact (floor (send twig get-grow-t))))) (when (and (> pi 0) (< pi (send twig get-num-points))) (set! twigs (cons (build-tree (vadd (send twig get-pos) (send twig get-point pi)) (send twig get-dir) (/ (send twig get-width pi) 1.4) (/ (send twig get-num-points) 2)) twigs)))))) twigs)) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define fin% (class object% (init-field (fin-size 1) (twig-ob #f) (col (vector 0 0 0)) (path-len 0) (profile-len 0)) (field (fin-len (min (- path-len 1) (+ min-fin-len (random fin-length-var)))) (root (build-polygons (* fin-len 2) 'triangle-strip)) (pos (random profile-len)) (start (* (random (- path-len fin-len)) profile-len)) (grow-t 0) (grow-speed (* (rndf) 0.1))) (define/public (build) (with-primitive root (parent twig-ob) (texture (load-texture "textures/fin-roots.png")) (hint-unlit) (hint-depth-sort) (colour col) (backfacecull 0) (pdata-index-map! (lambda (i t) (vector (/ (+ (quotient i 2) 1) (/ (pdata-size) 2)) (if (odd? i) 1 0) 0)) "t"))) (define/public (update t d) (when (< grow-t 1) (with-primitive root (pdata-index-map! (lambda (i p) (let* ((ti (+ start pos (* (quotient i 2) profile-len))) (tp (with-primitive twig-ob (pdata-ref "p" ti))) (tn (with-primitive twig-ob (pdata-ref "n" ti)))) (if (even? i) tp (vadd tp (vmul tn (* grow-t fin-size)))))) "p")) (set! grow-t (+ grow-t (* d grow-speed))))) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define extruded-twig-view% (class twig-view% (inherit growing?) (inherit-field index radius num-points pos dir col tex grow-t shrink-t) (field (profile '()) (path '()) (root 0) (widths '()) (fins '()) (twiglets '())) (define/override (build) (set! profile (build-circle-points 12 1)) (set! path (build-list num-points (lambda (_) (vector 0 0 0)))) (set! widths (build-list num-points (lambda (_) 1))) (set! root (let ((p (with-state (backfacecull 0) (when wire-mode (hint-none) (hint-wire)) (shader "shaders/twig.vert.glsl" "shaders/twig.frag.glsl") ;(shader "shaders/toon.vert.glsl" "shaders/toon.frag.glsl") (texture (load-texture "textures/cells-1.png")) (multitexture 1 (load-texture "textures/cells-2.png")) (multitexture 2 (load-texture "textures/cells-3.png")) (multitexture 3 (load-texture "textures/root-norm.png")) (opacity 0.6) (colour col) #;(colour (vector 1 1 1)) #;(texture (load-texture "textures/root.png")) (build-partial-extrusion profile path 3)))) (with-primitive p (shader-set! (list "Maps" (list 0 1 2) "NormalMap" 3))) p))) (define/override (get-root) root) (define/override (get-point point-index) (list-ref path point-index)) (define/override (get-width point-index) (list-ref widths point-index)) (define (list-set l c s) (cond ((null? l) '()) ((zero? c) (cons s (list-set (cdr l) (- c 1) s))) (else (cons (car l) (list-set (cdr l) (- c 1) s))))) (define/augment (add-point point width make-marker) (set! path (list-set path index point)) (set! widths (list-set widths index width)) (set! index (+ index 1))) (define/augment (update t d) (with-primitive root (shader-set! (list "Time" t)) #;(let ((t (inexact->exact (round (fmod (* 5 t) 3))))) (cond ((eq? t 0) (texture (load-texture "textures/cells-1.png"))) ((eq? t 1) (texture (load-texture "textures/cells-2.png"))) ((eq? t 2) (texture (load-texture "textures/cells-3.png")))))) #;(when (and (zero? (random fin-grow-prob)) (< (length fins) max-fins-per-twig) (not (growing?)) (> (length path) 1)) (let ((new-fin (make-object fin% (+ 0.3 (* radius (rndf))) root (vmul col (rndf)) (length path) (length profile)))) (send new-fin build) (set! fins (cons new-fin fins)))) (for-each (lambda (fin) (send fin update t d)) fins) (for-each (lambda (twiglet) (send twiglet update t d)) twiglets) (when (and (not (eq? grow-t -1)) (not (eq? grow-t 999))) ; randomly add twiglets as we are growing (when (and (zero? (random 100)) (< grow-t num-points)) (let ((t (make-object twiglets% (get-root))) (pi (inexact->exact (floor grow-t)))) (send t build (get-point pi) dir (/ (get-width pi) 2) 20) (set! twiglets (cons t twiglets)))) (with-primitive root (partial-extrude grow-t profile path widths (vector 1 0 0) 0.05))) (when (> shrink-t 0) (with-primitive root (partial-extrude shrink-t profile path widths (vector 1 0 0) 0.05))) #;(when (not (growing?)) (with-primitive root (pre-ripple) (ripple t 1 0.001)))) (define/public (get-end-pos) (list-ref path (if (zero? index) 0 (- index 1))) #;(with-primitive root (pdata-ref "p" (- (* index (length profile)) 1)))) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define plant-view% (class object% (init-field (id "none") (pos (vector 0 0 0)) (size 0) (col (vector 1 1 1)) (tex "") (is-player #f)) (field (twigs '()) ; a assoc list map between ids and twigs stored flat here, ; for fast access, but prims heirachically in the scenegraph (root (with-state (translate pos) (build-locator))) (seed (let ((p (with-state (parent root) (shader "shaders/twig.vert.glsl" "shaders/twig.frag.glsl") ;(shader "shaders/toon.vert.glsl" "shaders/toon.frag.glsl") (texture (load-texture "textures/cells-1.png")) (multitexture 1 (load-texture "textures/cells-2.png")) (multitexture 2 (load-texture "textures/cells-3.png")) (multitexture 3 (load-texture "textures/root-norm.png")) (backfacecull 0) (opacity 0.75) (colour col) (hint-depth-sort) (scale (* 0.06 size)) (when wire-mode (hint-none) (hint-wire)) ;(hint-unlit) (load-primitive "meshes/seed.obj")))) (with-primitive p (shader-set! (list "Maps" (list 0 1 2) "NormalMap" 3))) p)) (dust (if is-player (with-state (parent root) (make-object dust%)) #f)) (nutrients (let ((p (with-state (hint-depth-sort) (hint-unlit) (parent root) (blend-mode 'src-alpha 'one) (texture (load-texture "textures/smoke.png")) (build-particles 100)))) (with-primitive p (pdata-add "twig" "f") (pdata-add "point" "f") (pdata-add "offset" "v") (pdata-add "speed" "f") (pdata-map! (lambda (point) 0) "point") (pdata-map! (lambda (point) (* 3 (+ 0.1 (rndf)))) "speed") (pdata-map! (lambda (offset) (vector 0 0 0)) "offset") (pdata-map! (lambda (c) (vector 1 1 1)) "c") (pdata-map! (lambda (p) (vmul (vadd (crndvec) (vector 0 -1 0)) 900)) "p") (pdata-map! (lambda (s) (vmul (vector 1 1 1) (+ 0.1 (rndf)))) "s")) p))) (define/public (get-id) id) (define/public (get-col) col) (define/public (get-twig twig-id) (let ((l (assq twig-id twigs))) (if l (cadr (assq twig-id twigs)) #f))) (define/public (destroy-branch-twig twig-id) (when (get-twig twig-id) ; might have destroyed itself already (for-each (lambda (twig-id) (destroy-branch-twig twig-id)) (send (get-twig twig-id) get-child-twig-ids)) (send (get-twig twig-id) destroy-twig)) (set! twigs (assoc-remove twig-id twigs))) (define/public (destroy-plant) (destroy root) (for-each (lambda (twig) (destroy-branch-twig (car twig))) twigs)) (define/public (shrink-twig twig-id) (send (get-twig twig-id) start-shrinking) (for-each (lambda (twig-id) (shrink-twig twig-id)) (send (get-twig twig-id) get-child-twig-ids))) (define/public (add-twig parent-twig-id point-index twig) (let ((ptwig (get-twig parent-twig-id))) (when ptwig (send twig set-pos! (send ptwig get-point point-index)) ; attach to parent twig ; tell the twigs about this relationship (might turn out to be overkill) (send ptwig add-child-twig-id (send twig get-id)) (send twig set-parent-twig-id parent-twig-id)) (send twig set-col! col) (send twig set-tex! tex) (send twig build) (with-primitive (send twig get-root) (parent root)) (set! twigs (cons (list (send twig get-id) twig) twigs)))) (define/public (add-twig-point twig-id point width) (when (get-twig twig-id) (send (get-twig twig-id) add-point point width is-player))) (define/public (start-twig-growing twig-id) (when (get-twig twig-id) (send (get-twig twig-id) start-growing))) (define/public (grow-seed amount) (with-primitive seed (scale amount))) (define/public (add-ornament twig-id point-index property) (when (get-twig twig-id) (send (get-twig twig-id) add-ornament point-index property))) (define/public (set-excitations! a b) (for-each (lambda (twig) (send (cadr twig) set-excitations! a b)) twigs)) (define/public (nutrient-absorb twig-id twig-point) (with-primitive nutrients (let ((p (random (pdata-size)))) (pdata-set! "twig" p twig-id) (pdata-set! "point" p twig-point) (pdata-set! "p" p (send (get-twig twig-id) get-point twig-point)) (pdata-set! "offset" p (vmul (srndvec) ( send (get-twig twig-id) get-width twig-point)))))) (define/public (update-nutrients t d) (when (not (null? twigs)) (with-primitive nutrients (pdata-index-map! (lambda (i p twig-id point offset speed) (let* ((twig-id (inexact->exact twig-id)) (twig (get-twig twig-id)) (point (inexact->exact point))) (cond ((or (< point 1) (not twig)) (let* ((new-twig (choose twigs)) (num-points (send (cadr new-twig) get-num-points)) (new-point (if (zero? num-points) 0 (random num-points)))) (pdata-set! "twig" i (car new-twig)) (pdata-set! "point" i new-point) (pdata-set! "offset" i (vmix offset (vmul (srndvec) (send (cadr new-twig) get-width new-point)) 0.2)) (send (cadr new-twig) get-point new-point))) ((< (vdist (vadd (send twig get-point point) offset) p) 0.1) (pdata-set! "point" i (- point 1)) (vadd p (vmul (vnormalise (vsub (vadd (send twig get-point (- point 1)) offset) p)) (* speed d)))) (else (vadd p (vmul (vnormalise (vsub (vadd (send twig get-point point) offset) p)) (* speed d))))))) "p" "twig" "point" "offset" "speed")))) (define/public (above-ground) (when dust (send dust set-above-ground #t))) (define/public (below-ground) (when dust (send dust set-above-ground #f))) (define/public (update t d) (when dust (send dust update t d)) (with-primitive seed (shader-set! (list "Time" t)) #;(let ((t (inexact->exact (round (fmod (* 5 t) 3))))) (cond ((eq? t 0) (texture (load-texture "textures/cells-1.png"))) ((eq? t 1) (texture (load-texture "textures/cells-2.png"))) ((eq? t 2) (texture (load-texture "textures/cells-3.png")))))) (update-nutrients t d) (with-primitive seed (scale (+ 1 (* 0.001 (sin (* 2 t)))))) (for-each (lambda (twig) (when (send (cadr twig) delme?) (destroy-branch-twig (car twig)))) twigs) (for-each (lambda (twig) (send (cadr twig) update t d)) twigs)) (super-new))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define (build-env-box top bottom left right front back lower) (let ((p (build-locator))) (with-state (parent p) (hint-unlit) (list (let ((t (with-state (texture (load-texture top)) (translate (vector 0 0.5 0)) (rotate (vector 90 0 0)) (build-plane)))) (when lower (with-primitive t (pdata-map! (lambda (t) (vmul t 10)) "t")) ) t) (with-state (texture (load-texture left)) (translate (vector 0 0 -0.5)) (rotate (vector 0 0 0)) (build-plane)) (with-state (texture (load-texture back)) (translate (vector 0.5 0 0)) (rotate (vector 0 90 0)) (build-plane)) (with-state (texture (load-texture right)) (translate (vector 0 0 0.5)) (rotate (vector 0 0 0)) (build-plane)) (with-state (texture (load-texture front)) (translate (vector -0.5 0 0)) (rotate (vector 0 90 0)) (build-plane)) (if lower (with-state (texture (load-texture bottom)) (translate (vector 0 -0.5 0)) (rotate (vector 90 0 0)) (build-plane)) 0))))) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (define game-view% (class object% (field (plants '()) ; map of ids -> plants (pickups '()) ; map of ids -> pickups (insects '()) ; map of ids -> insects (camera-dist 1) (env-root (with-state (scale 1000) (build-locator))) (root-camera-t 0) (num-msgs 0) (floor (let ((p (with-state (hint-unlit) (colour 0.2) (texture (load-texture "textures/stone.png")) (translate (vector 0 -0.5 0)) (rotate (vector 90 0 0)) (scale 1000) (backfacecull 0) (build-seg-plane 10 10)))) (with-primitive p (pdata-map! (lambda (t) (vmul t 10)) "t")) p)) #;(upper-env (with-state (parent env-root) (hint-depth-sort) (colour 2) (translate (vector 0 0.28 0)) (build-env-box "textures/top.png" "textures/bottom-trans.png" "textures/left.png" "textures/right.png" "textures/front.png" "textures/back.png"))) #;(lower-env (with-state (parent env-root) (hint-depth-sort) (translate (vector 0 -0.22001 0)) (build-env-box "textures/bottom-trans.png" "textures/bottom.png" "textures/sleft.png" "textures/sright.png" "textures/sfront.png" "textures/sback.png"))) #;(upper-env (with-state (parent env-root) ;(hint-depth-sort) (hint-unlit) (translate (vector 0 0.28 0)) (build-env-box "textures/sky-top.png" "textures/floor.png" "textures/sky-side.png" "textures/sky-side.png" "textures/sky-side.png" "textures/sky-side.png" #f))) #;(lower-env (with-state (parent env-root) ;(hint-depth-sort) (hint-unlit) (colour (earth-colour)) (translate (vector 0 -0.22001 0)) (build-env-box "textures/floor.png" "textures/earth-bottom.png" "textures/earth-side.png" "textures/earth-side.png" "textures/earth-side.png" "textures/earth-side.png" #t))) (stones '()) (ground-change-t 0) (going-up #f)) (define/public (setup world-list) (let ((l (make-light 'point 'free))) (light-diffuse 0 (vector 0.5 0.5 0.5)) (light-diffuse l (vector 1 1 1)) (light-position l (vector 10 50 -4))) (below-ground) (set! stones (map (lambda (stone) (let ((p (with-state (hint-frustum-cull) ;(shader "shaders/toon.vert.glsl" "shaders/toon.frag.glsl") (colour (stones-colour)) (translate (list-ref stone 2)) (scale (list-ref stone 3)) (rotate (list-ref stone 4)) (texture (load-texture "textures/stone.png")) (load-primitive (list-ref stone 1))))) (with-primitive p (apply-transform) (recalc-bb)) ; apply the transform to speed up the ray tracing, don't have to tranform the ray into object space p)) (list-ref world-list 2)))) (define/public (above-ground) (printf "above-ground~n") (for-each (lambda (plant) (send (cadr plant) above-ground)) plants) (for-each (lambda (pickup) (with-primitive (send (cadr pickup) get-root) (hide 1))) pickups) (set! going-up #t) (set! ground-change-t ground-change-duration)) (define/public (below-ground) (printf "below-ground~n") (for-each (lambda (plant) (send (cadr plant) below-ground)) plants) (for-each (lambda (pickup) (with-primitive (send (cadr pickup) get-root) (hide 0))) pickups) (set! going-up #f) (set! ground-change-t ground-change-duration)) (define/public (update-ground-change t d) (when (> ground-change-t 0) (set! ground-change-t (- ground-change-t d)) (let* ((t (/ ground-change-t ground-change-duration)) (anim-t (if going-up t (- 1 t)))) (clip 1 (lerp 100 500 anim-t)) (clear-colour (vmix fog-col above-fog-col anim-t)) (fog (vmix fog-col above-fog-col anim-t) (lerp 0.04 0.01 anim-t) 1 100)))) (define/public (get-stones) stones) (define/public (add-plant plant) ;(destroy-plant (send plant get-id)) ; just in case (set! plants (cons (list (send plant get-id) plant) plants))) (define/public (get-plant plant-id) (let ((p (assoc plant-id plants))) (if (not p) #f (cadr p)))) (define/public (destroy-plant plant-id) (let ((p (get-plant plant-id))) (when p (send p destroy-plant) (set! plants (assoc-remove plant-id plants))))) (define/public (destroy-branch-twig plant-id twig-id) (send (get-plant plant-id) destroy-branch-twig twig-id)) (define/public (add-twig plant-id parent-twig-id point-index twig) (when (get-plant plant-id) (send (get-plant plant-id) add-twig parent-twig-id point-index twig))) (define/public (grow-seed plant-id amount) (when (get-plant plant-id) (send (get-plant plant-id) grow-seed amount))) (define/public (get-pickup pickup-id) (let ((p (assq pickup-id pickups))) (if p (cadr p) #f))) (define/public (add-pickup pickup-id type pos) (set! pickups (cons (list pickup-id (make-object pickup-view% pickup-id type pos)) pickups))) (define/public (add-insect insect-id pos type) (cond ((eq? type 'worm) (set! insects (cons (list insect-id (make-object worm-insect-view% insect-id pos type)) insects))) ((eq? type 'spider) (set! insects (cons (list insect-id (make-object spider-insect-view% insect-id pos type)) insects))) ((eq? type 'butterfly) (set! insects (cons (list insect-id (make-object butterfly-insect-view% insect-id pos type)) insects))))) (define/public (get-insect insect-id) (cadr (assq insect-id insects))) (define/public (pick-up-pickup pickup-id) (let ((pu (get-pickup pickup-id))) (when pu (send (get-pickup pickup-id) pick-up) (set! pickups (assoc-remove pickup-id pickups))))) (define/public (add-ornament plant-id twig-id point-index property) (when (get-plant plant-id) (send (get-plant plant-id) add-ornament twig-id point-index property))) (define/public (shrink-twig plant-id twig-id) (when (get-plant plant-id) (send (get-plant plant-id) shrink-twig twig-id))) (define/public (set-excitations! a b) (for-each (lambda (plant) (send (cadr plant) set-excitations! a b)) plants)) (define/public (update t d messages) (update-ground-change t d) (for-each (lambda (plant) (send (cadr plant) update t d)) plants) (for-each (lambda (pickup) (send (cadr pickup) update t d)) pickups) (for-each (lambda (insect) (send (cadr insect) update t d)) insects) (when debug-messages (for-each (lambda (msg) (send msg print)) messages)) (for-each (lambda (msg) (cond ((eq? (send msg get-name) 'player-plant) (printf "adding player plant to view ~a~n" (send msg get-data 'plant-id)) (add-plant (make-object plant-view% (send msg get-data 'plant-id) (send msg get-data 'pos) (send msg get-data 'size) (send msg get-data 'col) (send msg get-data 'tex) #t))) ((eq? (send msg get-name) 'new-plant) (printf "adding new plant to view ~a~n" (send msg get-data 'plant-id)) (add-plant (make-object plant-view% (send msg get-data 'plant-id) (send msg get-data 'pos) (send msg get-data 'size) (send msg get-data 'col) (send msg get-data 'tex)))) ((eq? (send msg get-name) 'grow-seed) (grow-seed (send msg get-data 'plant-id) (send msg get-data 'amount))) ((eq? (send msg get-name) 'destroy-branch-twig) (destroy-branch-twig (send msg get-data 'plant-id) (send msg get-data 'twig-id))) ((eq? (send msg get-name) 'new-twig) (add-twig (send msg get-data 'plant-id) (send msg get-data 'parent-twig-id) (send msg get-data 'point-index) (cond ((eq? (send msg get-data 'render-type) 'ribbon) (make-object ribbon-twig-view% (send msg get-data 'twig-id) (vector 0 0 0) ; will be filled in by add-twig (send msg get-data 'type) (send msg get-data 'dir) (send msg get-data 'width) (send msg get-data 'num-points))) ((eq? (send msg get-data 'render-type) 'extruded) (make-object extruded-twig-view% (send msg get-data 'twig-id) (vector 0 0 0) ; will be filled in by add-twig (send msg get-data 'type) (send msg get-data 'dir) (send msg get-data 'width) (send msg get-data 'num-points)))))) ((eq? (send msg get-name) 'add-twig-point) (when (get-plant (send msg get-data 'plant-id)) (send (get-plant (send msg get-data 'plant-id)) add-twig-point (send msg get-data 'twig-id) (send msg get-data 'point) (send msg get-data 'width)))) ((eq? (send msg get-name) 'start-growing) (when (get-plant (send msg get-data 'plant-id)) (send (get-plant (send msg get-data 'plant-id)) start-twig-growing (send msg get-data 'twig-id)))) ((eq? (send msg get-name) 'new-pickup) (add-pickup (send msg get-data 'pickup-id) (send msg get-data 'type) (send msg get-data 'pos))) ((eq? (send msg get-name) 'pick-up-pickup) (pick-up-pickup (send msg get-data 'pickup-id))) ((eq? (send msg get-name) 'shrink-twig) (shrink-twig (send msg get-data 'plant-id) (send msg get-data 'twig-id))) ((eq? (send msg get-name) 'new-ornament) (add-ornament (send msg get-data 'plant-id) (send msg get-data 'twig-id) (send msg get-data 'point-index) (send msg get-data 'property))) ((eq? (send msg get-name) 'vrob) (set! num-msgs (+ num-msgs 1)) (printf "num light-level msgs: ~a~n" num-msgs) (set-excitations! (send msg get-data 'light-level) (send msg get-data 'soil-moisture)) #;(for-each (lambda (p) (with-primitive p (colour (send msg get-data 'amount)))) upper-env)) ((eq? (send msg get-name) 'new-insect) (add-insect (send msg get-data 'insect-id) (send msg get-data 'pos) (send msg get-data 'type))) ((eq? (send msg get-name) 'insect-move) (send (get-insect (send msg get-data 'insect-id)) move (send msg get-data 'pos) (send msg get-data 'duration))) )) messages)) (super-new)))