Structural Informatics Group (SIG) logo
Home | Projects | Demos | Downloads | Publications | Local Info | About Us | New site
Go to the first, previous, next, last section, table of contents.

;PER-FRAME-HOOK prop x03d

source files: [xc]03d.[ch]


(SEND <x03d> :SET :PER-FRAME-HOOK (function <fn>))
(SEND <x03d> :SET :PER-FRAME-HOOK (list (function <fn>) ... ))


The :PER-FRAME-HOOK provides a simple, decentralized facility for animating any Skandha4 object -- that is, for making any property of that object an arbitrary function of time.

If :per-frame-hook on an object is set to a function or a list of functions (taking zero arguments), then those function(s) will be called (at most) once per frame, the first time the object in question is touched. A 'frame' is defined as the time between :swap-buffers messages to any camera. If the object in question is not used in any way during the frame, the :per-frame-hook functions will not be invoked. (If you want to ensure that a given action takes place every frame, you should instead use the global variable xg.3d-per-frame-hook.)


As an example, if *TIME* is a time-dependent variable and TRANSFORM is a mat44 controlling some thing, the thing may be made to rotate by:

(let* (
    (our-transform transform)    ; Build a local binding for TRANSFORM
  (:set our-transform :per-frame-hook
    (lambda NIL                ; Our 'lambda' will lock in OUR-TRANSFORM
      (send our-transform :ROTATE :DEGREES *TIME*)
) ) )

If *TIME* progresses linearly, the thing will rotate smoothly. (The :SCRIPT-TIME and :SCRIPT-RATE properties on cameras are the standard mechanism for specifying a smoothly varying time -- see ;GET ;SET etc cmr.)

Substituting (sin *TIME*) for *TIME* above would make the thing oscillate instead of rotate.


Again assuming that *TIME* is a time-dependent variable, and that GRL is a graphic relation containing :POINT-X :POINT-Y and :POINT-Z and :POINT-RED, :POINT-GREEN, :POINT-BLUE arrays, sinusoidal color waves travelling down the Z axis may be introduced by:

(let* (
    (our-grl grl)    ; Build a local binding for GRL
  (:set our-grl :per-frame-hook
    (lambda NIL                ; Our 'lambda' will lock in OUR-GRL
      (:pointwise-eval grl '(setq :point-red   (sin (+ :point-z *TIME* 1.0))))
      (:pointwise-eval grl '(setq :point-green (sin (+ :point-z *TIME* 2.0))))
      (:pointwise-eval grl '(setq :point-blue  (sin (+ :point-z *TIME* 3.0))))
) ) )


Assuming that THING is a thing of lines suitable for holding hershey text, THING may be set to visually display the count of frames generated by a hook expression like:

(let* (
    (our-thing thing)    ; Build a local binding for THING.
    (our-frame     0)    ; Build a local binding in which to count frames.
  ;; Note that since things are just lisp lists, we can't attach a
  ;; :per-frame-hook value to the thing as such, so we attach
  ;; it to a component of the relation:
  (:set (:get our-thing :facet-relation) :per-frame-hook
    (lambda NIL                ; Our 'lambda' will lock in our-thing, our-frame
      (xg.3d-empty-thing our-thing) ; Discard text from last frame
	:thing our-thing
	:text (format nil "Frame ~S" (setq our-frame (1+ our-frame)))
	:x 0 :y 0 :z 0
	:justify :center
) ) ) )

Go to the first, previous, next, last section, table of contents.