euslisp / jskeus

This repository contains EusLisp software developed and used by JSK at The University of Tokyo
23 stars 55 forks source link

irtviewerの視点・画角をプログラムから任意に設定したい #606

Open pazeshun opened 2 years ago

pazeshun commented 2 years ago

論文の図を作るような時に、プログラムを再起動しても再起動前と同じ視点・画角のirtviewerを表示してほしい時があります。 良い見た目となるようにirtviewerをマウスで操作した後、その視点・画角を保存して、次回起動時に読み込むようにしたいと考えています。

jmanualとirtviewer.lを読んで、以下のようにすると視点・画角の保存・再現ができましたが、irtviewerクラスのスロット変数left-right-angleup-down-angleのgetter/setterメソッドがないために:get-val:set-valを使っており、正規の方法ではないと思われます。 よりよい方法はありませんでしょうか。

1.irteusgl$ setq a (make-cube 100 100 100)
#<body #X560090199610 (:cube 100.0 100.0 100.0) 0.0 0.0 0.0 / 0.0 0.0 0.0>
2.irteusgl$ objects (list a)
;; (make-irtviewer) executed
(#<body #X560090199610 (:cube 100.0 100.0 100.0) 0.0 0.0 0.0 / 0.0 0.0 0.0>)
3.irteusgl$ setq vp (send *irtviewer* :viewpoint)
#f(155.272 268.939 113.029)
4.irteusgl$ setq vt (send *irtviewer* :viewtarget)
#f(0.0 0.0 0.0)
5.irteusgl$ setq lra (send *irtviewer* :get-val 'x::left-right-angle)
60
6.irteusgl$ setq uda (send *irtviewer* :get-val 'x::up-down-angle)
20
;; ここでirtviewerを適当にマウス操作
7.irteusgl$ send *irtviewer* :viewpoint vp
#f(155.272 268.939 113.029)
8.irteusgl$ send *irtviewer* :viewtarget vt
#f(0.0 0.0 0.0)
9.irteusgl$ send *irtviewer* :set-val 'x::left-right-angle lra
60
10.irteusgl$ send *irtviewer* :set-val 'x::up-down-angle uda
20
11.irteusgl$ send *irtviewer* :look1
#<coordinates #X560090308378  155.272 268.939 113.029 / 2.618 -2.776e-17 1.222>
12.irteusgl$ send *irtviewer* :draw-objects
1
;; irtviewerの表示がマウス操作前の状態に戻る
pazeshun commented 2 years ago

備忘録を兼ねて、これまでの試行錯誤を以下に書いておきます。

試行1

irtviewerクラスの:viewpoint:viewtargetがgetter/setterメソッドのようだったので、これらの値をバックアップしてマウス操作した後、バックアップした値を設定してみましたが、irtviewerは元に戻りませんでした。

1.irteusgl$ setq a (make-cube 100 100 100)
#<body #X557f1e73e610 (:cube 100.0 100.0 100.0) 0.0 0.0 0.0 / 0.0 0.0 0.0>
2.irteusgl$ objects (list a)
;; (make-irtviewer) executed
(#<body #X557f1e73e610 (:cube 100.0 100.0 100.0) 0.0 0.0 0.0 / 0.0 0.0 0.0>)
3.irteusgl$ setq vp (send *irtviewer* :viewpoint)
#f(155.272 268.939 113.029)
4.irteusgl$ setq vt (send *irtviewer* :viewtarget)
#f(0.0 0.0 0.0)
;; ここでirtviewerを適当にマウス操作
5.irteusgl$ send *irtviewer* :viewpoint vp
#f(155.272 268.939 113.029)
6.irteusgl$ send *irtviewer* :viewtarget vt
#f(0.0 0.0 0.0)
7.irteusgl$ send *irtviewer* :draw-objects
1
;; irtviewerに変化なし

試行2

jmanualとirtviewer.lをもう少しちゃんと読んで、:look1メソッドを使うと良さそうだとわかりましたが、:look1メソッドに与えないといけないleft-right-angleup-down-angleのgetterメソッドがなく、ひとまず:get-valを使ってバックアップした値を:look1に与えたところ、irtviewerの表示はバックアップ時の状態から拡大・縮小のみ変化したものになりました。 また、irtviewerをマウスで操作しようとすると:look1する前の状態に戻ってしまいました。

1.irteusgl$ setq a (make-cube 100 100 100)
#<body #X55b6d35ed610 (:cube 100.0 100.0 100.0) 0.0 0.0 0.0 / 0.0 0.0 0.0>
2.irteusgl$ objects (list a)
;; (make-irtviewer) executed
(#<body #X55b6d35ed610 (:cube 100.0 100.0 100.0) 0.0 0.0 0.0 / 0.0 0.0 0.0>)
3.irteusgl$ setq vp (send *irtviewer* :viewpoint)
#f(155.272 268.939 113.029)
4.irteusgl$ setq vt (send *irtviewer* :viewtarget)
#f(0.0 0.0 0.0)
5.irteusgl$ setq lra (send *irtviewer* :get-val 'x::left-right-angle)
60
6.irteusgl$ setq uda (send *irtviewer* :get-val 'x::up-down-angle)
20
;; ここでirtviewerを適当にマウス操作
7.irteusgl$ send *irtviewer* :viewpoint vp
#f(155.272 268.939 113.029)
8.irteusgl$ send *irtviewer* :look1 vt lra uda
#<coordinates #X55b6d375c378  155.272 268.939 113.029 / 2.618 -2.776e-17 1.222>
9.irteusgl$ send *irtviewer* :draw-objects
1
;; irtviewerは変化するが、意図したようには変わらない

試行3

最新の方法。 irtviewer.lを更によく読んだところ、マウス操作イベントのコールバックで使われている:move-viewing-around-viewtargetではスロット変数left-right-angleup-down-angleを更新して使用している一方、:look1では更新していなかったので、マウス操作でおかしくならないためにはそれらの更新が必要なのではないかと推測しました。 また、拡大・縮小で変化するのはviewpointだったのと、:look1の中で最新のviewpointを読み込んでそれを元に計算していることから、viewpointもバックアップして設定し直さないといけないのではないかと推測しました。

k-okada commented 2 years ago
(setq vp (send *irtviewer* :viewpoint)
      vt (send *irtviewer* :viewtarget)
      lra (*irtviewer* . x::left-right-angle)
      uda (*irtviewer* . x::up-down-angle))
;; ここでマウス操作
(send *irtviewer* :viewpoint vp)
(send *irtviewer* :look1 vt lra uda)
(send *irtviewer* :draw-objects)

するとやりたいことができそうですが,https://github.com/euslisp/jskeus/issues/606#issue-983885480 になっているのは,マウスクリックするともとに戻るのが嫌だったのかな. (set-val よりは,. の書き方のほうがよく見る気はします)

同じ様に,マウスクリックすると視点が戻っちゃうけど, viewing 自体を保存して使う,というのがある気がします.

$ (setq a (copy-object (send *irtviewer* :viewer :viewing)))
#<perspective-viewing #X55d721868e88 #:title62 31.6deg 203.62 -301.878 -12.716 / 0.593 0.0 1.606>
$ (setq ((send *irtviewer* :viewer) . geo::eye) a)
#<perspective-viewing #X55d721868e88 #:title62 31.6deg 203.62 -301.878 -12.716 / 0.593 0.0 1.606>
$ (send *irtviewer* :draw-objects)

このケースが結構あるなら,

  (:left-right-angle (&optional a) (if a (setq left-right-angle a)) left-right-angle)
  (:up-down-angle  (&optional a) (if a (setq up-down-angle a))  up-down-angle))

を定義しても良いかもしれないですね. `

pazeshun commented 2 years ago
(setq vp (send *irtviewer* :viewpoint)
      vt (send *irtviewer* :viewtarget)
      lra (*irtviewer* . x::left-right-angle)
      uda (*irtviewer* . x::up-down-angle))
;; ここでマウス操作
(send *irtviewer* :viewpoint vp)
(send *irtviewer* :look1 vt lra uda)
(send *irtviewer* :draw-objects)

するとやりたいことができそうですが,#606 (comment) になっているのは,マウスクリックするともとに戻るのが嫌だったのかな.

はい、その通りです。 読みにくくて申し訳なかったですが、https://github.com/euslisp/jskeus/issues/606#issuecomment-909270678 の「試行2」で言及していました。 なぜマウスクリックで戻ってほしくないかというと、複数のシーンを同じ視点・画角で撮ろうと思っている時に、あるシーンに対して最適化された視点・画角を見つけて保存した上で、それで他のシーンも表示してみて、はみ出したりするシーンがあれば視点・画角をマウスで微調整する、ということをしたいからです。

同じ様に,マウスクリックすると視点が戻っちゃうけど, viewing 自体を保存して使う,というのがある気がします.

$ (setq a (copy-object (send *irtviewer* :viewer :viewing)))
#<perspective-viewing #X55d721868e88 #:title62 31.6deg 203.62 -301.878 -12.716 / 0.593 0.0 1.606>
$ (setq ((send *irtviewer* :viewer) . geo::eye) a)
#<perspective-viewing #X55d721868e88 #:title62 31.6deg 203.62 -301.878 -12.716 / 0.593 0.0 1.606>
$ (send *irtviewer* :draw-objects)

このissueを立てた段階では:viewingメソッドを知らなかったので:look1しか使わなかったのですが、マウスクリックしない状況であれば、:viewingメソッドを使う方法が最も簡単な気が僕もしています。

このケースが結構あるなら,

  (:left-right-angle (&optional a) (if a (setq left-right-angle a)) left-right-angle)
  (:up-down-angle  (&optional a) (if a (setq up-down-angle a))  up-down-angle))

を定義しても良いかもしれないですね.

「このケースが結構ある」かと聞かれると微妙なところですが、図にこだわりたい人には便利な機能だとは思っています。 後でPR作ってみようかなと思います。