Lisp HUG Maillist Archive

Re: Displaying and scrolling live data

I just realized that this response from 6 March doesn't seem to have made it to the list. Is it because I answered directly to Raffael and cc:ed the list?
Anyway, I would be most grateful if someone could enlighten me when it comes to my questions regarding invalidate-rectangle etc.
/Sven again 
---
Thanks for the nice demo Raffael!
Possibly I can use image copying for parts of the scrolling, but a  
difficulty is that I draw a note head when a "note on" event arrives  
and later when the corresponding "note off" event arrives, I change  
the note head (now scrolled to the left) into its right shape  
(quarter note, half note etc).

Anyway, I have made some progress. I stuffed all drawing and also  
updates using set-horizontal-scroll-parameters into with-atomic- 
redisplay and now have a smoother scroll.

I lack understanding of the underpinnings of updating the pane though...
-I realize that calls to invalidate-rectangle, queue up calls to the  
display-callback and that some of these calls are thrown away. But  
what calls are thrown away?
-What happens when calling set-horizontal-scroll-parameters? It  
doesn't seem to call invalidate-rectangle and even if I don't call  
invalidate-rectangle after set-horizontal-scroll-parameters, things  
are redrawn.
Are the above things described somewhere?

Thanks again!
/Sven





5 mar 2010 kl. 20.11 skrev Raffael Cavallaro:

On Mar 5, 2010, at 6:39 AM, Sven Emtell wrote:
During MIDI input, a timer is calling an update function (note- pane-update) every 20ms. This updating function changes the :max- range of the horizontal scroll-bar using capi:set-horizontal- scroll-parameters followed by a "scroll :horizontal :move :end", and then calls the display-callback function (display-note-pane). The idea is to set the slug in its right-most position, so that score notes enter the note-pane from the right and scroll to the left. In the display-callback function, I have wrapped the drawing inside a with-atomic-redisplay. Note: The score notes displayed will change during scrolling, so I have to redraw them instead of just copying a bitmap. Some observations: -It works, but the drawing is not very smooth. It seems to jump a little back and forth while scrolling. -When updating every 200ms instead, it looks OK, but slow.
Other sorts of capi animation I've done as well as apple's docs suggest that you'll never get more than 60fps screen refresh from a Cocoa/AppKit application. If you do much computation and drawing you'll start to see aliasing (e.g., wheels appearing to rotate backwards) even at 60fps. So 20ms=50fps is right on the edge of what is possible even with minimal computation and drawing per frame. Have you tried a 33ms timer (i.e., 30 fps)? Another possibility: You could grab the already drawn notes in an image, draw that to the pane, then draw the new notes over it. For example, if you shift the notes by 1/10 of the visible pane width each frame, you grab the rightmost 9/10 of the pane in an image (gp:make-image-from-port), draw this image full left in the pane, then draw the new notes in the rightmost 1/10 of the pane. Of course whether this would be faster than just redrawing is entirely dependent on how much redrawing you're doing. My benchmarks suggest that you can draw just under 200 polygons (i.e., gp:draw-polygon) at 30 fps on a 2+GHz machine. Anything more than this and it's worthwhile to grab an image first, then do any new drawing for each frame over the grabbed image from the previous frame. Something like this would do the side scrolling: (defun anim-test-sidescroll (&key (framerate 10) (time 6)) ;; up framerate to see effect (declare (optimize speed (safety 1) (debug 0))) (let* ((frame-x-offset 70) ;; how far we'll shift the pane contents left each frame (circle-base-x-coordinate 600) ;; where we'll plunk down new circles (current-image nil) ;; the image we've grabbed of the port, left end choppped (old-image nil) ;; previous frame so we can free it and avoid a leak (still-running t)) (labels ((display-a-frame (self x y width height) (declare (ignorable x y width height)) (when current-image (gp:draw-image self current- image 0 0)) (dotimes (n 4) ;; draw 4 circles in a vertical line at the right edge (gp:draw-circle self (+ circle-base-x-coordinate (* n 3)) ;; x (+ 50 (* n 100) (random 100)) ;; y (+ 20 (random 15)) ;; radius :filled t :foreground (nth n '(:orange :blue :green :purple)))) (setf old-image current-image) ;; swap these cause we need a ref to old-image (setf current-image ;; grab the current port contents with the left end chopped (gp:make-image-from-port self frame-x-offset 0 ;; need to truncate width by frame-x-offset ;; or the image will be stretched when displayed (- (gp:port-width self) frame-x-offset) (gp:port-height self))) (when old-image (gp:free-image self old-image))) ;; free the old image (pane-destroyed (self) ;; stop the animation loop if pane goes bye bye (declare (ignorable self)) (setf still-running nil))) (let* ((the-pane ;; make a pane that uses the above func for display (capi:contain (make-instance 'capi:output-pane :display-callback #'display- a-frame :destroy-callback #'pane- destroyed) :best-height 600 :best-width 700))) (mp:process-run-function "anim-test-sidescroll-process" () (lambda () (loop for i below (round (* framerate time)) while still-running do ;; loop for time redisplaying at framerate (sleep (float (/ framerate) 1.0s0)) (gp:invalidate-rectangle the-pane)))))))) As you'll see if you experiment with the framerate keyword arg, you don't see any increase in speed beyond :framerate 60 - i.e., :framerate 300 looks just the same. hth, warmest regards, Ralph Raffael Cavallaro raffaelcavallaro@me.com

Re: Displaying and scrolling live data

Unable to parse email body. Email id is 10110

Updated at: 2020-12-10 08:39 UTC