スレッド一覧 | 新規スレッド | 留意事項 | ワード検索 | 過去ログ | 管理用 |
icon pythonでの無限遠光源の設定について
日時: 2005/12/11 00:48
名前: A2

pythonスクリプト作りで悪戦苦闘しております。
無限遠光源ウインドの光源方向設定半球における点の位置をカメラの設定にかかわらず
同位置に保つにはどうしたらいいのでしょうか?

ちょっとわかりにくいと思いますが例えばカメラの視点を動かすと半球の点の位置も
同時に動くわけなのですが、それを視点を動かす前の位置に戻したいということです。
戻す位置はそれほど正確でなくていいのですがこれをpythonスクリプトでおこなうことは
可能でしょうか?

どうか御教授願います。
メンテ
Page: [1]

file Re: pythonでの無限遠光源の設定について ( No.1 )
日時: 2005/12/11 16:40
名前: 宮田

無限遠光源をカメラに追従したいということでしょうか?
カメラを動かさず、形状を動かせば目的の結果になりますよね。

パイソンでの書式は判りませんけど、考え方としては、

カメラの視点・注視点および無限遠光源の座標を取得。
視点・注視点のベクトルを計算
注視点・無限遠光源のベクトルを計算
視点を動かしたときの視点・注視点のベクトルを計算し、元ベクトルから
の回転角を計算。
上記の答えから注視点・無限遠光源のベクトルを補正計算。

で良いように思いますけど‥

ただ、この方法だと注視点のほうを動かした場合(視点との平行移動以外)
ベクトルが変わるのでうまく計算されないと思います。
また、ズームを使った場合もうまくかないかもしれません。
メンテ
file Re: pythonでの無限遠光源の設定について ( No.2 )
日時: 2005/12/13 07:38
名前: 加藤俊明 メールを送る

こんばんわ、

以下、apple script で書いてみました。
python でも基本的な構文は同じなので、何をやっているかは解って頂けるのではないかと思います。

script は二種類あります。

script - 1 で現在の視線方向と無限遠光源方向との関係を線形状で記憶します。

カメラの方向を変える度に script - 2 を実行します。

そうすると、無限遠光源の方向がお望みの状態に保たれるようになります。

エラーメッセージは最低限のものしか書いてませんので、そのあたりは適宜判断して下さい。
また script - 1 によって、視線方向と無限遠光源方向 との関係を記憶するための線形状がルートパート直下に "distant light direction" と言う名前で作成されます。

もし、必要ならこの名前は変更して下さい。

このような線形状が勝手に作られてしまうのがイヤなら、同様の情報をファイル出力するという方法もありますね。


----- script - 1  --------

tell application "Shade 8 professional"
    
    inhibit update
    
    --  無限遠光源の方向ベクトルを取得
    set v to distant light direction
    
    --  注視点座標を取得
    set p1 to target
    
    --  視点座標を取得
    set p2 to eye
    
    --  視線方向の単位ベクトルを求める
    set eV to {(item 1 of p2) - (item 1 of p1), (item 2 of p2) - (item 2 of p1), (item 3 of p2) - (item 3 of p1)}
    set L to sqrt ((item 1 of eV) ^ 2 + (item 2 of eV) ^ 2 + (item 3 of eV) ^ 2)
    set eV to {(item 1 of eV) / L, (item 2 of eV) / L, (item 3 of eV) / L}
    
    --  v, eV 座標をルートパート直下に線形状として出力する
    
    --  現在の選択状態を保存
    set hList to handle list
    
    --  既に "distant light direction" という名前の線形状オブジェクトがあればそれを削除する
    if select by name "distant light direction" then
        if object type = line object then
            set deletedH to handle  --  削除される線形状のハンドルを記憶しておく
            cut
        else
            set handle list to hList
            beep
            allow update
            return --  "distant light direction" という名前の線形状以外のオブジェクトがあれば警告音を出して終了
        end if
    end if
    
    --  形状編集モード状態を記憶
    set modifyMode to modify mode
    set modify mode to false
    
    --  ルートパートに移動
    repeat while (select parent 1000)
    end repeat
    
    -- 線形状として出力(名称を "distant light direction" としておく)
    start polygon without closed
    append point at eV
    append point at {0, 0, 0}
    append point at v
    finish polygon
    set object name to "distant light direction"
    
    --   選択状態を元に戻す
    --   hList の中に削除された線形状 "distant light direction" が含まれているなら、
    --   それをリストの中から除外した新たなリスト handleList を作成する
    set handleList to {} --  handleList の初期化
    repeat with h in hList
        if h ≠ deletedH then --  hList の中の h が deletedH と等しくなければ、handleList に追加する
            set handleList to handleList & h
        end if
    end repeat
    set handle list to handleList --  選択状態を元に戻す
    
    --  形状編集モードを元に戻す
    set modify mode to modifyMode
    
    allow update
    
end tell



----- script - 2  --------

tell application "Shade 8 professional"
    
    inhibit update
    
    --  現在の選択状態を保存
    set hList to handle list
    
    --  "distantlight direction" という名前のオブジェクトを選択する
    select by name "distant light direction"
    
    --  もし見つからなかったなら、警告音を出して終了
    if not result then
        beep
        allow update
        return
    end if
    
    --  形状編集モード状態を記憶
    set modifyMode to modify mode
    set modify mode to false
    
    --  保存してあった視線方向単位ベクトルを読み込む
    set prev_eV to anchor point 0
    
    --  注視点座標を取得
    set p1 to target
    
    --  視点座標を取得
    set p2 to eye
    
    --  視線方向の単位ベクトルを求める
    set eV to {(item 1 of p2) - (item 1 of p1), (item 2 of p2) - (item 2 of p1), (item 3 of p2) - (item 3 of p1)}
    set L to sqrt ((item 1 of eV) ^ 2 + (item 2 of eV) ^ 2 + (item 3 of eV) ^ 2)
    set eV to {(item 1 of eV) / L, (item 2 of eV) / L, (item 3 of eV) / L}
    
    --  prev_eV が eV に重なるようにオイラー回転する--------------------------------
    
    -- eV の経度 longitude1 を求める
    set L to sqrt ((item 1 of eV) ^ 2 + (item 3 of eV) ^ 2)
    if L > 1.0E-6 then --  eV は単位ベクトル故、長さの絶対値で判定可
        set longitude1 to acos ((item 3 of eV) / L)
        if (item 1 of eV) < 0 then
            set longitude1 to -longitude1
        end if
    else
        set longitude1 to 0
    end if
    
    -- eV の緯度 latitude1 を求める
    set latitude1 to asin (item 2 of eV)
    
    -- prev_eV の経度 longitude2 を求める
    set L to sqrt ((item 1 of prev_eV) ^ 2 + (item 3 of prev_eV) ^ 2)
    if L > 1.0E-6 then --  prev_eV は単位ベクトル故、長さの絶対値で判定可
        set longitude2 to acos ((item 3 of prev_eV) / L)
        if (item 1 of prev_eV) < 0 then
            set longitude2 to -longitude2
        end if
    else
        set longitude2 to 0
    end if
    
    -- prev_eV の緯度 latitude2 を求める
    set latitude2 to asin (item 2 of prev_eV)
    
    --  現在選択状態にあるのは "distantlight direction"。 これを回転する
    move object around {0, 0, 0} rotate {0, -longitude2 * 180 / pi, 0}
    move object around {0, 0, 0} rotate {-(latitude1 - latitude2) * 180 / pi, 0, 0}
    move object around {0, 0, 0} rotate {0, longitude1 * 180 / pi, 0}
    
    ---------------------------------------------------------------------
    
    --  回転された "distantlight direction" の 無限遠光源ベクトル座標 v を読み取る
    set v to (anchor point 2)
    
    --  無限遠光源をセット
    set distant light direction to v
    
    --   選択状態を元に戻す
    set handle list to hList
    
    --  形状編集モードを元に戻す
    set modify mode to modifyMode
    
    allow update
    
end tell


-----  おしまい  -----



メンテ
file Re: pythonでの無限遠光源の設定について ( No.3 )
日時: 2005/12/12 02:07
名前: 管理人

結構難しそうな話だなと思っていたら、強力な助っ人が (^^)
やっぱりオイラー回転が必要なんですね。

操作性を考えると、視線を変更すると自動的に無限遠光源も更新されるというのが
望ましいのでしょうが、スクリプトでは難しいのでしょうね。
ShadeR5まではスクリプト実行中の画面層が可能だったので、
ループを使った疑似常駐風スクリプトというのも使えたのですが。
メンテ
file Re: pythonでの無限遠光源の設定について ( No.4 )
日時: 2005/12/12 09:30
名前: A2

ご返事ありがとうございます。大変参考になりました。
そもそも特殊な用途なので返信はないだろうと思っておりました。

加藤さんのスクリプトをpythonで作ろうと思います(出来るかどうかわからんが・・・)。

以下私事ですが、この無限遠光源方向の設定というのはPhotoshopにおける輪郭線抽出の為に必要で、
その他の設定は自作のレンダリングスクリプト(VB)で自動化していたのですが光源の方向と
全オブジェの表面材質全削除だけは(これは今でもできない)手動でおこなっています。

shade8はダウンロード販売がアップデートより安かったので購入しました。
目当ては当然トーンシェーダです。これで半自動化しているとはいえ、同じ絵に計4回のレンダリングや
その他特殊な色の設定など面倒なことから解放されると喜び勇んだのですが、
これが少なくとも自分の環境では全く使い物にならない。

体験版でブーリアンなどの制約は知っていたのですが、これほどのろく、使い物にならないとは・・・
まあその他よくなっている点は多々あるし、輪郭線抽出は今まで通りやればいいかと思ったら
今度はVBスクリプトの動きが変。スクリプトウインドやマニュアルからもなくなっている。

何しろプログラミングど素人なのでVBからpythonに書き換えるのは並の苦労ではございません。

以上私事というよりグチでした。
メンテ
file Re: pythonでの無限遠光源の設定について ( No.5 )
日時: 2005/12/12 11:13
名前: 加藤俊明 メールを送る

>全オブジェの表面材質全削除だけは(これは今でもできない)手動でおこなっています。

え〜、これはですねえ、再帰関数( 自分で自分自身を呼び出す関数 )を使って簡単にできます。

またまた Apple Script で恐縮ですが、サンプルスクリプトを二つ書いておきますね。

最初のは、ファイル内の全オブジェクトの表面材質設定を削除するもの。
二番目は、選択オブジェクトとその全ての子オブジェクトの表面材質設定を削除するものです。

最初の部分が異なるだけで、再帰関数の中身は両者とも全く同じです。

どなたか Python での 関数の書き方をご存じの方がいたならアドバイスお願い致します。


--  ファイル内の全オブジェクトの表面材質設定削除  ------------------------------

tell application "Shade 8 professional"
    
    inhibit update
    
    --  現在の選択状態を保存
    set hList to handle list
    
    --  ルートパートを選択
    repeat while (select parent 1000)
    end repeat
    
    my DeleteSurfaceAttributes() --  再帰関数を呼ぶ
    
    --  選択状態を元に戻す
    set handle list to hList
    
    allow update
    
end tell


--  ここから再帰関数
on DeleteSurfaceAttributes()
    tell application "Shade 8 professional"
        set has surface attributes to false --  表面材質設定削除
        if select child then --  子オブジェクトが選択できるなら
            my DeleteSurfaceAttributes() --  再帰関数を呼ぶ
            select parent  --  親オブジェクトを選択
        end if
        
        repeat while select brother --   全ての弟オブジェクトについて
            my DeleteSurfaceAttributes() --  再帰関数を呼ぶ
        end repeat
        
    end tell
end DeleteSurfaceAttributes

--  おしまい  --------------------------------------------------------------




--  選択オブジェクトとその全ての子オブジェクトの表面材質設定削除  ------------------

tell application "Shade 8 professional"
    
    inhibit update
    
    --  現在の選択状態を保存
    set hList to handle list
    
    --  選択されている各オブジェクトについて
    repeat with h in hList
        set handle to h --  選択オブジェクトを一つずつ選択
        set has surface attributes to false --  表面材質設定削除
        if select child then --  子オブジェクトが選択できるなら
            my DeleteSurfaceAttributes() --  再帰関数を呼ぶ
        end if
    end repeat
    
    --  選択状態を元に戻す
    set handle list to hList
    
    allow update
    
end tell


--  ここから再帰関数
on DeleteSurfaceAttributes()
    tell application "Shade 8 professional"
        set has surface attributes to false --  表面材質設定削除
        if select child then --  子オブジェクトが選択できるなら
            my DeleteSurfaceAttributes() --  再帰関数を呼ぶ
            select parent  --  親オブジェクトを選択
        end if
        
        repeat while select brother --   全ての弟オブジェクトについて
            my DeleteSurfaceAttributes() --  再帰関数を呼ぶ
        end repeat
        
    end tell
end DeleteSurfaceAttributes

--  おしまい  --------------------------------------------------------------
メンテ
file Re: pythonでの無限遠光源の設定について ( No.6 )
日時: 2005/12/12 17:32
名前: 宮田

すごいなぁ。加藤さんにはいつも本当に感服させられます。

美術系に理数の知識は必要ないと言う人もいらっしゃるんですが、
美術には整然と創られた美しさ(幾何文様とか加藤さんのModelingPackIIもそうですよね)
とそれを崩した美しさ(アニメやデフォルメなど)があると思います。
3Dでは2Dに比べてこの差が大きいので、双方を取り扱える・歩み寄らせる技術・知識を
持っている方は強力なクリェータですね。
メンテ
file Re: pythonでの無限遠光源の設定について ( No.7 )
日時: 2005/12/13 07:41
名前: 加藤俊明 メールを送る

おっとっと、Re No.2 の所で紹介した script - 1 の所で、エラーチェックが不十分で場合によっては Shade がクラッシュしてしまう場合があったので、既に書き込みは直接訂正しておきました。

訂正前

    --  既に "distant light direction" という名前の線形状オブジェクトがあればそれを削除する
    if select by name "distant light direction" then
        if object type = line object then
            cut

         --  中略

    --   選択状態を元に戻す
    set handle list to hList

訂正後

    --  既に "distant light direction" という名前の線形状オブジェクトがあればそれを削除する
    if select by name "distant light direction" then
        if object type = line object then
            set deletedH to handle  --  削除される線形状のハンドルを記憶しておく
            cut

         --  中略

    --   選択状態を元に戻す
    --   hList の中に削除された線形状 "distant light direction" が含まれているなら、
    --   それをリストの中から除外した新たなリスト handleList を作成する
    set handleList to {} --  handleList の初期化
    repeat with h in hList
        if h ≠ deletedH then --  hList の中の h が deletedH と等しくなければ、handleList に追加する
            set handleList to handleList & h
        end if
    end repeat
    set handle list to handleList --  選択状態を元に戻す



>双方を取り扱える・歩み寄らせる技術・知識を持っている

いやあ、結局のところ単なる算数フェチだけなのかも、
Illustrator で絵を描くのは得意ですが、自由曲面を手でチマチマと編集するのは未だに苦手で、はっきり言って下手くそでありますです。
メンテ

親記事を見る

Page: [1]
検索フォームに戻る スレッド一覧 | 新規スレッド | 留意事項 | ワード検索 | 過去ログ | 管理用 |

題名 スレッドをトップへソート
名前
E-Mail
スパムメール対策のため、[表示]にしてもメールアドレスが直接表示されることはありませんが、サンプルのようなメールフォームでメールを受け取ることができます。
メールフォームサンプル サンプル  メールヘッダについて
URL
パスワード (記事メンテ時に使用)
投稿キー (投稿時 投稿キー を入力してください)
添付ファイル (最大300KBまで gif jpeg png text zip pdf midi swf)
コメント (^^) (^_^) (+_+) (^o^) (^^;) (^_-) (;_;)

(改行、インデントが反映されます)

   クッキー保存