Behavioral Animation Example


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(load 'transform.al)
(load 'BooleanPrimitives.al)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define render-rib? #f)
(define *actors* '())    ;; list of live actors
(define (add-actor actor) (set! *actors* (cons actor *actors*)))
(define *num-actors* 10)
(define (randR low high) (+ (* (rand) (- high low)) low))
(define *boundary* 30)
(define *perfect-distance* 15)
(define *max-turn* 4)
(define *speed* .4)

(define (clamp x l h) (cond ((< x l) l) ((> x h) h) (else x)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (shark)
  (solid "difference"
	 (surface "matte")
	 (color (vec3 .2 .2 .2))
	 (translate 0 0 -.95)
	 (scale .1 1 1)
	 (solid-sphere 2 -2 2)
	 (translate 0 0 -1.2)
	 (scale 10 1.2 1)
	 (solid-sphere 2 -2 2)
	 ))

(define (water)
  (separator
   (surface "plastic")
   (rotate -90 (vec3 1 0 0))
   (color (vec3 0 .2 1))
   (disk 'radius 100)
   ))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (actor-create)
  
  (let (
	(direction (vec3 0 0 1))
	(speed .5)
	(position (vec3 0 0 0))
	(dead? #f)
	(id 0)
	)
    
    (define (set-direction! vel) (set! direction vel))
    (define (set-speed! vel) (set! speed vel))
    (define (set-position! pos) (set! position pos))
    (define (set-dead! dead) (set! dead? dead))
    (define (set-id! new-id) (set! id new-id))
    
    (define (influence-force other-pos)
      (let (
	    (d (norm (- position other-pos)))
	    )
	(if (< d *perfect-distance*)
	    (* (normalize (- position other-pos))
	       (expt (- *perfect-distance* d) 2))
	    (* (normalize (- other-pos position))
	       (expt (- d *perfect-distance*) 2))
	    )))
    
    (define (update)
      (let ((a-list *actors*)
	    (force (vec3 0 0 0))
	    )

	;; compute influence forces from other actors
	(while (not (null? a-list))
          (begin
	    (define other (car a-list))
	    (if (<> (other 'id) id)
              (set! force (+ force (influence-force (other 'position))))
	      )
	    (set! a-list (cdr a-list))
	    ))

	;; compute new direction
	(set! force (normalize force))
	
	; determine axis and angle of rotation 
	; from current direction to force direction
	(define axis (cross direction force))
	(define angle (degrees (acos (dot direction force))))
	(set! angle (clamp angle (- 0 *max-turn*) *max-turn*))
	(set! direction (transform-point direction (mat4-rotate angle axis)))

	;; compute new position
	(set! position (+ position (* direction speed)))
	))

    (define (draw) 
      (separator (translate position) 
		 (concat-transform (from-z-xfm direction))
		 (shark)
		 ))
      
    (lambda (message)
      (cond
       ((eq? message 'set-direction!) set-direction!)
       ((eq? message 'set-speed!) set-speed!)
       ((eq? message 'set-position!) set-position!)
       ((eq? message 'set-dead!) set-dead!)
       ((eq? message 'set-id!) set-id!)
       ((eq? message 'direction) direction)
       ((eq? message 'speed) speed)
       ((eq? message 'position) position)
       ((eq? message 'dead?) dead?)
       ((eq? message 'id) id)
       ((eq? message 'update) (update))
       ((eq? message 'draw) (draw))
       (else (error "actor: invalid operation" message))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (generate-actors)
  (let (
	(n *num-actors*)
	(actor '())
	)
    (while (> n 0)
	   (begin
	     (set! actor (actor-create))
	     ((actor 'set-direction!)
		     (normalize (vec3 (randR -1 1) 0 (randR -1 1))))
	     ((actor 'set-speed!) *speed*)
	     ((actor 'set-id!) n)
	     ((actor 'set-position!) (vec3 (randR -15 15) 
					   0
					   (randR -15 15)))
	     
	     (add-actor actor)
	     (set! n (sub1 n))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (update-actors)
  (define a-list *actors*)
  (while (not (null? a-list))
    (begin
      ((car a-list) 'update)
      (set! a-list (cdr a-list)))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (draw-actors)
  (define a-list *actors*)
  (while (not (null? a-list))
    (begin
      ((car a-list) 'draw)
      (set! a-list (cdr a-list)))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (animate duration)
  (begin 
    (set-time! 0)
    (generate-actors)

    (while (< time duration)
      (begin
	(update-actors)
	(world
	 (srand 1)
	 (tessellate 4 4)
	 (camera "main" "perspective" 
		 'from (vec3 20 5 20)
		 'fov 60)
	 (light "pointlight" 'from (vec3 0 10 10) 'intensity 1000)
	 (water)
	 (draw-actors)
	 )

	(if render-rib? 
	      (render
	       'display-name (string-append "frame." (number->string time))
	       'format '(160 121 1)
	       ))
	
	(set-time! (add1 time))
	))))
  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;(animate 90)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Return to Behavioral Animation
mrl