[plt-scheme] FrTime implementation

From: Gregory Cooper (greg at cs.brown.edu)
Date: Sun Dec 9 06:43:06 EST 2007

Ah.  Now I think I understand the problem a bit better.  It sounds
like what you'll want is a mechanism for synchronizing FrTime and the
Fluxus render loop.  Here's how I'd recommend doing it:

1.  Define an event stream called something like fluxus-pulse:

  (define fluxus-pulse (event-receiver))

2.  Define your own versions of the primitive input behaviors you
need, which only update on these pulses.  E.g.:

  (define clock (hold (map-e (lambda (e) (current-milliseconds)) fluxus-pulse)))

3.  Each time through the render loop, emit a pulse, then wait for
FrTime to stabilize, and finally draw.  Here's a rough sketch:

(define frtime-chan (make-channel))

(let loop ()
  ;; emit the next pulse
  (send-event fluxus-pulse #t)
  ;; have frtime send a message when it's done updating everything
  (do-in-manager-after (channel-put frtime-chan #t))
  ;; wait for the message from frtime
  (channel-get frtime-chan)
  ;; draw the frame from a consistent state
  (draw-a-frame <reactive scene description data structure>)

4.  Note that with this approach, there is no lifting at all
(regardless of DrScheme version).  Instead, as you traverse the
reactive structure, you'll just test whether each value you encounter
is a behavior, and if so, you'll call "value-now" on it before

Let me know whether this helps or not.


On Dec 9, 2007 5:57 AM, Dave Griffiths <dave at pawfal.org> wrote:
> On Sat, 2007-12-08 at 22:52 -0500, Gregory Cooper wrote:
> > Hi Dave,
> >
> > It looks like you have the right idea.  :-)
> >
> > Are you running a pre-v371 version of DrScheme / FrTime?  (From the
> > code and description you give, it sounds like you are...)  I ask
> > because around July I changed the way FrTime deals with lists and
> > other data structures, and this change makes it a bit more complicated
> > to lift over data structures containing behaviors.
> >
> > In pre-v371, all data constructors (including "cons") are lifted, so
> > any reactivity inside a data structure spreads to the structure
> > itself.  When you lift a procedure over a reactive structure, the
> > procedure gets called repeatedly with snapshots of the structure
> > (computed each time anything inside the structure changes).  This is
> > why the second (make-torus ...) gets redrawn every millisecond, even
> > though it only changes once a second: draw-list processes the entire
> > list whenever anything inside it changes.
> >
> > In v371 and later, data constructors are not lifted, so behaviors can
> > hide inside structures.  In order to lift over such structures, you'll
> > first need to use "raise-reactivity" to make the reactivity spread to
> > the top of the structure, or use "compound-lift" (like the new
> > animation.ss does), which lets your procedure find the reactivity
> > while traversing the structure.  (This avoids the work of constructing
> > a deep snapshot each time something changes.)  If you decide to
> > upgrade to v371 at some point, let me know and I'll be happy to help
> > explain this.
> That makes sense. I'm running 370 - time to upgrade :)
> > A couple of small comments: I'm surprised that you don't have code to
> > clear the buffer before rendering the list of shapes, like
> > animation.ss does.
> This is the nub of the problem for me really ;)
> When running in drscheme, the render loop is running in a different
> (plt) thread.
> This is due to the way fluxus works - you don't drive the render loop
> yourself, but you can optionally hook into it to get a function called
> by the engine every frame to animate/update things. (using frtime even
> this wont be needed)
> This is a Good Thing - the framerate can be detached from the script
> update (you can always interactively move the camera around with the
> mouse etc)
> The problem with this naive frtime script is that the primitives strobe
> as they are drawing once per millisecond, rather than once per frame.
> This is fixed by using retained mode primitives (rather than the
> immediate mode (draw-*) ones it uses at the moment), which are
> maintained inside the render engine and rendered every frame for you,
> optimised for speed. then frtime can just update them whenever it wants
> to.
> This has implications to how I implement the frtime interface - I'll
> need to do some work to make this stateful (for reasons of speed)
> situation appear stateless.
> One option is to require the 'user' to name each object, so the frtime
> implementation can infer some historical information - first time it
> appears build it, other times update it, when it doesn't appear in the
> list delete it.
> How does animation.ss cope with this? If a shape only updates once a
> second, how does it get redrawn when other things are updating more
> quickly?
> > Also, I'm not sure why you don't just write:
> >
> >   (define clock milliseconds)
> Ah, I was just playing with changing it, but left it as * 1 :)
> cheers,
> dave

Posted on the users mailing list.