« C4D Python R12 テスト:現在の編集モードを取得 | トップページ | C4D Python R13 テスト:storageモジュールのファイルを開く/保存ダイアログ »

C4D Python R13 テスト:ローカル座標からグローバル座標へ、更に違うローカル座標へ

C4D SDK R13がアップされているのだ…
気付いていなかった…

ダウンロードは…
http://www.maxon.net/en/support/plugin-cafe.html

Pythonをちょっとだけ見たけど…
threadingモジュールが追加された。
C.O.F.F.E.E.も変わったんだろうか…?

それは、それで…

今回は、ポリゴンオブジェクトを2個用意して、その2個を一体化してみようかなぁと思う…
CallCommand()なんかを使わないでね、ちまちま作ってみる。

2つ目のポリゴンオブジェクトのポイント座標(ローカル)をグローバル座標に変換して、1つ目のポリゴンオブジェクトのローカル座標へ変換して再構築…
こんな具合です。

適当に2つのポリゴンオブジェクトを用意して適当に配置する。

Localtoglobaltolocal_01

立方体のポイント座標をグローバル座標へ変換。
ローカル座標からグローバル座標への変換は、つい最近の記事に書いたね。
http://villager-and-c4d.cocolog-nifty.com/blog/2011/10/c4d-python-r12-.html

まずは、選択された2つのポリゴンオブジェクトの2つ目のポリゴンオブジェクトのポイントをグローバル座標に変換ね。

C4D Python R13 SDK Docには、複数の選択オブジェクトをフィルタを設定して任意のオブジェクトだけを抽出できそうなメソッドがあるんだけど…

BaseDocument.GetActiveObjectsFilter()

3番目の引数の意味がわからない…
C4DAtom.IsInstanceOf()をチェックしろって書いてあるようだけど…
C4DAtomクラスにIsInstanceOf()メソッドは、見当たりません…
またしても、C4D Python R13 SDK Docに悩まされるのだ…
ま、自分の頭が悪いのを棚に上げてみた…

いつも通り

BaseDocument.GetActiveObjects()

を使うことにした。

Python
'''
2つの選択されたポリゴンオブジェクトの2つ目のポイントをグローバル座標へ変換
'''


import c4d
   
   
def main():
    sel_obj = doc.GetActiveObjects(False)
   
    #選択オブジェクトが2個のポリゴンオブジェクトでなければ終了
    if len(sel_obj) != 2:return
    for obj in sel_obj:
        if not isinstance(obj, c4d.PolygonObject):return

    print sel_obj
       
    #2個目のポリゴンオブジェクトのポイントをグローバル座標へ変換
    mg_1 = sel_obj[1].GetMg()
    pts = []
    for id in xrange(sel_obj[1].GetPointCount()):
        p = sel_obj[1].GetPoint(id) * mg_1
        pts.append(p)
       
        print id, ':', p
   
   
    print 'ok'
   
   
if __name__=='__main__':
    main()
    c4d.EventAdd()
[<c4d.PolygonObject object called '正多面体/ポリゴン' with ID 5100 at 0x25A4E4C0>, <c4d.PolygonObject object called '立方体/ポリゴン' with ID 5100 at 0x25A4E560>]
0 : Vector(-19.412, -118.257, 146.832)
1 : Vector(23.693, 68.651, -2.354)
2 : Vector(210.095, -193.194, 119.26)
3 : Vector(253.2, -6.286, -29.925)
4 : Vector(277.308, -57.183, 309.082)
5 : Vector(320.413, 129.725, 159.897)
6 : Vector(47.801, 17.754, 336.654)
7 : Vector(90.906, 204.662, 187.468)
ok

変換の確認は、座標マネージャを「ワールド」に変更し1個づつポイントを選択するしかないね。
構造マネージャでは確認でいないよ…

Localtoglobaltolocal_02

問題なさそうだから、次にいこう…

グローバル座標に変換されたポイント座標はptsに格納されています。
これを、更に1個目のポリゴンオブジェクトのグローバルマトリクスの逆マトリクスで1個目のポリゴンオブジェクトのローカル座標に変換します。

print 'ok'の前に追加ね。

Python
    #1個目のポリゴンオブジェクトのローカル座標へ変換
    mg_0 = sel_obj[0].GetMg()
    mg_0 = mg_0.__invert__()
    for id in xrange(sel_obj[1].GetPointCount()):
        pts[id] = pts[id] * mg_0

未だにPythonの事を知らないのだ…
__invert__()モジュールの使い方は、これで良いのかなぁ…
__add__()とか__num__()とかの意味は極最近知ったんだけど… ちょっと照れた… 過去の記事に何かあったね…

1個目のポリゴンオブジェクトのポイント数を2個目のポリゴンオブジェクトのポイント数だけ増やして、変換した座標を適用します。
ポリゴン数も増やします。

ポリゴンオブジェクトのポイント数やポリゴン数の変更は以前に書いたね…
http://villager-and-c4d.cocolog-nifty.com/blog/2011/02/c4d-python-r1-7.html

print 'ok'の前に追加ね。

Python
    #1個目のポリゴンのポイント数とポリゴン数を変更
    #変換した座標を適用する。

    #ポリゴンも適用する。
    #1個目のオブジェクトを更新し2個目を削除

    #1個目のポイント数/ポリゴン数を確保
    #ポリゴン数/ポイント数を変更

    ptc_0 = sel_obj[0].GetPointCount()
    plc_0 = sel_obj[0].GetPolygonCount()
    sel_obj[0].ResizeObject(ptc_0 + sel_obj[1].GetPointCount(), plc_0 + sel_obj[1].GetPolygonCount())
   
    #変換したポイントの適用
    for id in xrange(sel_obj[1].GetPointCount()):
        sel_obj[0].SetPoint(ptc_0 + id, pts[id])
   
    #ポイント番号をシフトさせてポリゴンを適用
    for id in xrange(sel_obj[1].GetPolygonCount()):
        poly = sel_obj[1].GetPolygon(id)
        poly.a += ptc_0
        poly.b += ptc_0
        poly.c += ptc_0
        poly.d += ptc_0
        sel_obj[0].SetPolygon(plc_0 + id, poly)
   
    #1個目のポリゴンオブジェクトを更新
    sel_obj[0].Message(c4d.MSG_UPDATE)
   
    #2個目のポリゴンオブジェクトを削除
    sel_obj[1].Remove()

これで、一通り完成しました。
実行すると2個目のポリゴンオブジェクトのポイントの座標は変換され、1つのポリゴンオブジェクトとして変更されているはずです。

Localtoglobaltolocal_03

あ、大きいポリゴンオブジェクトで試す前に、コンソールに表示している部分を削除しておいてください。
じゃないと、変換された座標がズラズラズララ…と表示されるので…

Python
'''
座標変換をして、2つの選択されたポリゴンオブジェクトを一体化する。
'''

   
import c4d
   
   
def main():
    sel_obj = doc.GetActiveObjects(False)
   
    #選択オブジェクトが2個のポリゴンオブジェクトでなければ終了
    if len(sel_obj) != 2:return
    for obj in sel_obj:
        if not isinstance(obj, c4d.PolygonObject):return
   
       
    #2個目のポリゴンオブジェクトのポイントをグローバル座標へ変換し
    #更に1個目のポリゴンオブジェクトのローカル座標へ変換
    mg_1 = sel_obj[1].GetMg()
    mg_0 = sel_obj[0].GetMg()
    mg_0 = mg_0.__invert__()
    pts = []
    for id in xrange(sel_obj[1].GetPointCount()):
        pts.append((sel_obj[1].GetPoint(id) * mg_1) * mg_0)
   
   
    #1個目のポイント数/ポリゴン数を確保
    #ポリゴン数/ポイント数を変更
    ptc_0 = sel_obj[0].GetPointCount()
    plc_0 = sel_obj[0].GetPolygonCount()
    sel_obj[0].ResizeObject(ptc_0 + sel_obj[1].GetPointCount(), plc_0 + sel_obj[1].GetPolygonCount())
   
    #変換したポイントの適用
    for id in xrange(sel_obj[1].GetPointCount()):
        sel_obj[0].SetPoint(ptc_0 + id, pts[id])
   
    #ポイント番号をシフトさせてポリゴンを適用
    for id in xrange(sel_obj[1].GetPolygonCount()):
        poly = sel_obj[1].GetPolygon(id)
        poly.a += ptc_0
        poly.b += ptc_0
        poly.c += ptc_0
        poly.d += ptc_0
        sel_obj[0].SetPolygon(plc_0 + id, poly)
   
    #1個目のポリゴンオブジェクトを更新
    sel_obj[0].Message(c4d.MSG_UPDATE)
   
    #2個目のポリゴンオブジェクトを削除
    sel_obj[1].Remove()
   
   
    print 'ok'
   
   
if __name__=='__main__':
    main()
    c4d.EventAdd()

C4D Demo版はアクティベーションする前や期限切れでも、Pythonスクリプトはスクリプトマネージャのメニューから保存ができるんだね。
C.O.F.F.E.E.スクリプトは無理みたいだけど…
単なるPythonモジュールと同じ.pyの拡張子のテキストファイルで…
pyファイルとして、公開できるじゃないか… 知らんかった… 試しもしなかった…

今回のテストスクリプト「local_to_global_to_local.ZIP」です。
あくまでもテストスクリプトなので、Undoは書いていない…

ごめんね、いつもオブジェクト指向じゃなくて…

あ、記事のタイトルと内容がマッチしていない…
これじゃ、ポリゴンオブジェクトの一体化だね…

久々に書くと、こんなもんか…

|

« C4D Python R12 テスト:現在の編集モードを取得 | トップページ | C4D Python R13 テスト:storageモジュールのファイルを開く/保存ダイアログ »

コメント

コメントを書く



(ウェブ上には掲載しません)




« C4D Python R12 テスト:現在の編集モードを取得 | トップページ | C4D Python R13 テスト:storageモジュールのファイルを開く/保存ダイアログ »