« C4D R13 Demoをダウンロード… | トップページ | C4D Python R12 テスト:Python ジェネレータでスプラインを生成 »

C4D Python R12 テスト:Python ジェネレータの取っ掛かり…

ご無沙汰になってしまったね。
C4DはR12から、いきなりR13 だね。

ところで…

「Python ジェネレータ」ってあるよね…

Pythongene_12

「Python ジェネレータ」の使い方って?
分かり易い解説は無いのかなぁ…

C4D Python SDKでのサンプルは2個…

  • binary_kite.c4d

Binary_kite

スクリプトを見たけど分かりづらい…

  • mengersponge.c4d

Mengersponge

フラクタルかぁ…

初心者だと、こんなシーンファイルを見せてもらってもわかり辛いよね…
しかも、「Python ジェネレータ」の基本的な用法の説明が見当たらない…

「Python ジェネレータ」は…

ジオメトリを生成するために使用するようだ。
生成したジオメトリ(BaseObject)を、main()関数のreturnで返すようだ。

オリジナルのジオメトリを生成するという事は、新規でプリミティブのプラグインを作ることに似ているね。

新規でスプラインやポリゴンオブジェクトでプリミティブのような物をPythonで作ろうとすると…
ObjectData Pluginとして作る事になるだろうか?
Pluginを作ってC4Dで使えるようにするにはPluginIDが必要で、MaxonからPluginIDを貰う事になる。
世界中のC4Dユーザの為に、価値のプリミティブが作れるならIDを取得しても良いだろう…
興味本位で作った、さほど価値も無いプリミティブの為にIDを取得するのはいかがなものか?
Pythonを使えるC4Dユーザの大半が興味本位でIDを無駄に取得すると、あっという間にIDが無くなってしまうだろう…

ごめんね、大げさに書きました。
まぁ皆が皆、無駄にIDを取得する事は無いと思うけどね…

そんな事より、「Python ジェネレータ」の使い方ね…
PythonジェネレータにはPluginIDは必要ないし、プラグインを作るより簡単だ…

さて…
新規で、Python ジェネレータを追加すると…

Pythongene_01

Pythonジェネレータに内包された立方体プリミティブがシーンに追加される。

Pythongene_02

Pythonジェネレータを選択して…

Pythongene_03

編集可能にするを実行すると…

Pythongene_04

Pythongene_05

Pythonジェネレータと言う名前の立方体プリミティブが現れる。

新規で追加したPythonジェネレータのコードを見てみると…

Python
import c4d
#Welcome to the world of Python


def main():
    return c4d.BaseObject(c4d.Ocube)

単純に、main()関数からreturnでc4d.Ocubeを指定して生成されたBaseObjectが返されている。

立方体プリミティブ1個だけなので、この状態では全く意味の無い状態だね。

さて、手始めにプリミティブを組み合わせたオブジェクトを作ってみよう。

Pythongene_06

Pythongene_07

c4d.BaseObjectに指定できるオブジェクトの定数は…
http://villager-and-c4d.cocolog-nifty.com/blog/coffee-allocobject.html

円柱はc4d.Ocylinderです。

Python
import c4d
#Welcome to the world of Python


def main():
    #車体の設定
    bw = 200.0
    bh = 200.0
    bd = 400.0

    obj = c4d.BaseObject(c4d.Ocube)
    obj[c4d.PRIM_CUBE_LEN] = c4d.Vector(bw, bh, bd)


    tw = 40.0
    tr = 80.0
    tpos = 120.0
    tax = c4d.PRIM_AXIS_XP

    #タイヤ1の設定
    tire_1 = c4d.BaseObject(c4d.Ocylinder)
    tire_1[c4d.PRIM_CYLINDER_RADIUS] = tr
    tire_1[c4d.PRIM_CYLINDER_HEIGHT] = tw
    tire_1[c4d.PRIM_AXIS] = tax
    tire_1[c4d.ID_BASEOBJECT_REL_POSITION] = c4d.Vector(-(bw + tw) / 2, -bh / 2, tpos)
    tire_1.MakeTag(c4d.Tphong)
    tire_1.InsertUnder(obj)

    #タイヤ2の設定
    tire_2 = c4d.BaseObject(c4d.Ocylinder)
    tire_2[c4d.PRIM_CYLINDER_RADIUS] = tr
    tire_2[c4d.PRIM_CYLINDER_HEIGHT] = tw
    tire_2[c4d.PRIM_AXIS] = tax
    tire_2[c4d.ID_BASEOBJECT_REL_POSITION] = c4d.Vector((bw + tw) / 2, -bh / 2, tpos)
    tire_2.MakeTag(c4d.Tphong)
    tire_2.InsertUnder(obj)

    #タイヤ3の設定
    tire_3 = c4d.BaseObject(c4d.Ocylinder)
    tire_3[c4d.PRIM_CYLINDER_RADIUS] = tr
    tire_3[c4d.PRIM_CYLINDER_HEIGHT] = tw
    tire_3[c4d.PRIM_AXIS] = tax
    tire_3[c4d.ID_BASEOBJECT_REL_POSITION] = c4d.Vector(-(bw + tw) / 2, -bh / 2, -tpos)
    tire_3.MakeTag(c4d.Tphong)
    tire_3.InsertUnder(obj)

    #タイヤ4の設定
    tire_4 = c4d.BaseObject(c4d.Ocylinder)
    tire_4[c4d.PRIM_CYLINDER_RADIUS] = tr
    tire_4[c4d.PRIM_CYLINDER_HEIGHT] = tw
    tire_4[c4d.PRIM_AXIS] = tax
    tire_4[c4d.ID_BASEOBJECT_REL_POSITION] = c4d.Vector((bw + tw) / 2, -bh / 2, -tpos)
    tire_4.MakeTag(c4d.Tphong)
    tire_4.InsertUnder(obj)

    return obj

タイヤの様な同じ形状のものは、for等のループを使ったほうが効率的かな…

成功していれば、下のように現れているはずです。

Pythongene_08

オブジェクトカラーがグレーなのは、Pythonジェネレータによるものではありません。
ここでは、シーンファイルのデフォルトオブジェクトカラーが「80%グレー」に設定されています。

Pythongene_09

さて、このままでのPythonジェネレータは、常に同じ大きさのオブジェクトでしかありません。
プリミティブオブジェクトの様にパラメータ設定できると、使い勝手がよくなりますな。
パラメータには、Pythonジェネレータのユーザデータを使います。

Pythongene_10_2

全てのパラメータは実数です。
下のスクリプトの黄色の部分をユーザデータに対応させました。

Pythongene_11

Python
import c4d
#Welcome to the world of Python


def main():
    #車体の設定
    bw = op[c4d.ID_USERDATA, 2]
    bh = op[c4d.ID_USERDATA, 3]
    bd = op[c4d.ID_USERDATA, 4]

    obj = c4d.BaseObject(c4d.Ocube)
    obj[c4d.PRIM_CUBE_LEN] = c4d.Vector(bw, bh, bd)


    tw = op[c4d.ID_USERDATA, 6]
    tr = op[c4d.ID_USERDATA, 7]
    tpos = op[c4d.ID_USERDATA, 8]
    tax = c4d.PRIM_AXIS_XP

    #タイヤ1の設定
    tire_1 = c4d.BaseObject(c4d.Ocylinder)
    tire_1[c4d.PRIM_CYLINDER_RADIUS] = tr
    tire_1[c4d.PRIM_CYLINDER_HEIGHT] = tw
    tire_1[c4d.PRIM_AXIS] = tax
    tire_1[c4d.ID_BASEOBJECT_REL_POSITION] = c4d.Vector(-(bw + tw) / 2, -bh / 2, tpos)
    tire_1.MakeTag(c4d.Tphong)
    tire_1.InsertUnder(obj)

    #タイヤ2の設定
    tire_2 = c4d.BaseObject(c4d.Ocylinder)
    tire_2[c4d.PRIM_CYLINDER_RADIUS] = tr
    tire_2[c4d.PRIM_CYLINDER_HEIGHT] = tw
    tire_2[c4d.PRIM_AXIS] = tax
    tire_2[c4d.ID_BASEOBJECT_REL_POSITION] = c4d.Vector((bw + tw) / 2, -bh / 2, tpos)
    tire_2.MakeTag(c4d.Tphong)
    tire_2.InsertUnder(obj)

    #タイヤ3の設定
    tire_3 = c4d.BaseObject(c4d.Ocylinder)
    tire_3[c4d.PRIM_CYLINDER_RADIUS] = tr
    tire_3[c4d.PRIM_CYLINDER_HEIGHT] = tw
    tire_3[c4d.PRIM_AXIS] = tax
    tire_3[c4d.ID_BASEOBJECT_REL_POSITION] = c4d.Vector(-(bw + tw) / 2, -bh / 2, -tpos)
    tire_3.MakeTag(c4d.Tphong)
    tire_3.InsertUnder(obj)

    #タイヤ4の設定
    tire_4 = c4d.BaseObject(c4d.Ocylinder)
    tire_4[c4d.PRIM_CYLINDER_RADIUS] = tr
    tire_4[c4d.PRIM_CYLINDER_HEIGHT] = tw
    tire_4[c4d.PRIM_AXIS] = tax
    tire_4[c4d.ID_BASEOBJECT_REL_POSITION] = c4d.Vector((bw + tw) / 2, -bh / 2, -tpos)
    tire_4.MakeTag(c4d.Tphong)
    tire_4.InsertUnder(obj)

    return obj

これで、Pythonジェネレータでパラメータを使ったジオメトリの生成の基本的な部分はイメージできるた思うけど…

Pythonジェネレータのスクリプト部分の実行のタイミングは…

Pythongene_13

「キャッシュを最適化」がonの場合、Pytnonジェネレータのパラメータ(ユーザデータも含む)が変更された時のみ実行されます。
他のイベントが起こっても実行されません。
offの場合は、イベントが起こるたび(アニメーションのフレームの移動時も)に実行されます。C4Dに負荷がかかるので、ジオメトリの生成後に形状の変更が無い場合はonにすべきだね。

「フレーム0でリセット」がonの場合、0フレームに移動した時の最初の一度だけ実行されます。

今回は、Pythonジェネレータでプリミティブを使った単純なジオメトリの生成を試してみましたが…
少しは、興味が沸いてきただろうか?

|

« C4D R13 Demoをダウンロード… | トップページ | C4D Python R12 テスト:Python ジェネレータでスプラインを生成 »

コメント

コメントを書く



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




« C4D R13 Demoをダウンロード… | トップページ | C4D Python R12 テスト:Python ジェネレータでスプラインを生成 »