Bamboo touchでのマルチタッチ

prev : http://d.hatena.ne.jp/mjt/20091004/p1
というわけで、mosh canvasを使って取得した座標を表示してみる。手持ちで撮影しているので手ぶれがひどい。
http://storage.osdev.info/pub/idmjt/diaryimage/0910/neta091005l1.flv

  • 黄色い点 : 最初のタッチポイント
  • 小さい点 : おそらく中間点
  • 青い点 : 次のタッチポイント

青い点だけ という状況があることに注意。一度離すと点は黄色くなる。2つの点は独立してコントロールできる。
動画では解りづらいが、10秒おき程度に一瞬固まる。これはGCによる。

canvasの使用

実際の描画は、canvas-draw!に描画命令のリストを渡すことで行う。描画命令はmove-toのようなよく知られたものを受け付け、描画命令のセットはOpenVGに由来する。
Window上のcanvasはmake-simple-canvas-windowで作ることができる。これはバックグラウンドで(mosh concurrentによる)スレッドを作り、イベントを処理する。今回は、リアルタイムのビジュアライズを行いたいため明示的にWindowを作っているが、通常のシチュエーションではファイルと同様の感覚で画面に表示できる。
ただし、画面に表示できるのはWindowsのみ。他のOSではファイル(cairoによるPDF/PNG)への出力のみ利用できる。
実際の描画部は以下のようになる :

(define (draw-rect x y s r g b)
  (let ((sx (- x s))
        (sy (- y s))
        (d (* 2 s)))
    `((pen-width 0)
      (paint-color-rgb ,r ,g ,b)
      (move-to ,sx ,sy)
      (line-to* ,d 0)
      (line-to* 0 ,d)
      (line-to* ,(- d) 0)
      (close-path)
      (fill))))
...
    (canvas-draw! ca (append
                       pro
                       (draw-rect x0 y0 (/ p0 3.0) 255 255 0)
                       (draw-rect x1 y1 5 255 0 0)
                       (draw-rect x2 y2 (/ p2 3.0)  0 255 255)))))

今の実装には描画クロージャが含まれていないので、明示的にリストを作成して連結する必要がある。描画クロージャを導入すると、描画命令をユーザサイドで拡張することが出来るようになる。
draw!はリストを深さ優先で辿って実行するので、描画部のappendはlistでも動作する。ただ、この仕様が将来的に残るかは検討中。

(import (rnrs)
        (ext win32 usb)
        (ext canvas win32 window) ;→(ext canvas simple)になる予定

        ; STUB。将来的にはこれらは不要になる。
        (ext win32 mainthread) (ext win32 window-master))

; STUB
(init-window-master)

(usb_init)
(define dh (usb_open0 #x56a #xd1))
(usb_set_configuration dh 1)
(usb_claim_interface dh 0)
(usb_claim_interface dh 1)
(define pktlen #x14)
(define buf (make-bytevector pktlen))
(define init-data #vu8(2 2))
(usb_control_msg dh 33 9 #x0302 0 init-data 2)

(define ca (make-simple-canvas-window 480 320))

(define pro '((paint-color-rgb 255 255 255)
              (clear)))

(define (draw-rect x y s r g b)
  (let ((sx (- x s))
        (sy (- y s))
        (d (* 2 s)))
    `((pen-width 0)
      (paint-color-rgb ,r ,g ,b)
      (move-to ,sx ,sy)
      (line-to* ,d 0)
      (line-to* 0 ,d)
      (line-to* ,(- d) 0)
      (close-path)
      (fill))))

(define (tab-display buf)
  (define (b x)
    (bytevector-u8-ref buf x))
  (define (w x)
    (bitwise-and #x7fff (bytevector-u16-ref buf x (endianness big))))
  (let ((p0 (b 2))
        (x0 (w 3))
        (y0 (w 5))
        (x1 (w 7))
        (y1 (w 9))
        (p2 (b 11))
        (x2 (w 12))
        (y2 (w 14)))
    (canvas-draw! ca (append
                       pro
                       (draw-rect x0 y0 (/ p0 3.0) 255 255 0)
                       (draw-rect x1 y1 5 255 0 0)
                       (draw-rect x2 y2 (/ p2 3.0)  0 255 255)))))

(define (loop)
  (let ((r (usb_interrupt_read dh #x82 buf pktlen)))
    (if (< r 0)
      (loop)
      (begin
        (tab-display buf)
        (loop)))))

(loop)