VRED Pro の Python スクリプト作成について説明します。また、独自のスクリプトの開発を開始する例をいくつか確認します。
ビデオのキャプション: VRED Pro の Python スクリプト作成に関するチュートリアル シリーズへようこそ。Christopher といいます。このビデオでは、VRED で開発する場合に必要な Python の基本について少し説明します。また、独自のスクリプトの開発するためのサンプルをいくつか紹介します。
Python は、プラグイン開発で非常に一般的なインタープリタ型プログラミング言語です。Python インタフェースを提供する CGI ツールは他にも多数ありますが、Python が使用されるのは単なる偶然ではありません。Python は、表現力に優れた言語で、習得も容易だと評価されています。C++、C#、Java などのプログラミング言語と異なり、コンパイルする必要はありません。コードを記述して[実行]をクリックするだけで、コードに指定した機能が直ちに実行されます。Python は C++ と緊密に連携することもできますが、これは、VRED の内部でも C++ が使用されているからです。Python と VRED の両方についてお話ししましょう。
オートデスクは API バージョン 2 を導入したときに、Python 2.7 から Python 3 に切り替えました。これは、Python 2.7 の公式サポートが 2020 年 1 月に終了したためです。Python 2.7 を引き続き使用するスクリプトを使用している場合も、心配は不要です。VRED には、Python 2.7 を Python 3 に自動的に変換するオプションがあります。
Python と VRED について付け加えると、VRED では独自の統合 Python 3 インタプリタが使用されています。このインタプリタを使用することで、Python 環境に直接 VRED API を挿入することができます。
これは私たちにどのようなメリットをもたらすでしょうか。Python は、すべての機能をモジュールと呼ばれる形式で提供します。モジュールは、クラスと関数の集まりにすぎません。VRED API についてもまったく同じで、VRED API はモジュールが集まったものです。通常、これらのモジュールを使用するには、すべてのモジュールを手動で読み込む必要があります。たとえば、vrNodeUtils
モジュールを使用する場合は、「import vrNodeUtils」と入力して読み込む必要があります。ところが、VRED にはこれらのすべてのモジュールが既に追加されているので、この操作を行う必要はありません。このため、VRED 内のスクリプトが格段に読みやすくなり、追加されるコードが大幅に削減されます。
外部モジュールまたはスクリプト プラグインを開発する場合は、注意が必要です。VRED API を明示的に読み込む必要がありますが、読み込むのは API バージョン 1 のみです。これについては、この後のビデオで少し詳しく説明します。
それでは、実際のサンプルをいくつか見てみましょう。あまり複雑ではない、準備運動のためのサンプルです。多くのスクリプトでは、何らかの方法でシーングラフにアクセスする必要があります。シーングラフは 3D グラフィックスの中心として機能し、ジオメトリ、ライト、トランスフォームなどについての情報をすべて保持します。シーングラフは階層構造になっていて、ルート ノードから始まり、シーンをトランスフォーム ノード、グループ ノード、またはスイッチ ノードに分け、ジオメトリ自体に到達するようになっています。一般的なスクリプトでは、シーングラフにノードやジオメトリを追加したり、ノードをある場所から別の場所に移動したり、シーングラフ内のノードを見つけて操作することができます。
最初のサンプルでは、まずシーングラフ内のノードを検索します。メニュー バーの[編集]にある[スクリプト エディタ]を開き、スクリプトを入力します。ここでは、最初に vrNodeService
を使用してシーンのルートとカメラ ノードを検索します。カメラ ノードは、シーングラフに表示されているように、Perspective
と呼ばれます。
シーングラフ内のノードは通常、名前で参照されます。この操作の結果は変数として保存されます。現在、この変数には vrdNode
タイプのオブジェクトが格納されています。vrdNodes
は API バージョン 2 で定義されています。[実行]ボタンをクリックしてスクリプトを実行すると、ターミナルに出力メッセージが表示されます。このメッセージは、2 つの変数で保持されているオブジェクトのタイプを示します。
次に、新しいノードを作成してシーングラフに追加します。ここでは、Group
タイプのノードを作成します。ドキュメントを参照して、作成できるすべてのノード タイプを特定することができます。そのためには、createNode
関数を使用するときに、最初のパラメータでノード タイプを定義し、2 番目のパラメータで名前を設定し、3 番目のパラメータで新しいノードの親となるノードを VRED に指示します。この場合は、新しいノードをシーンのルートの下に配置します。その後で、vrSceneGraph
モジュールから updateSceneGraph
関数を呼び出します。このコマンドを実行すると、シーングラフに変更内容が直接表示されます。
ジオメトリを作成して、新しいグループ ノードに追加してみましょう。この操作を行うには、プリミティブ ジオメトリを作成する一連の関数を使用します。ここでは、createPlane
関数と createBox
関数を使用しています。
入力を開始するときに使用できるお勧めの関数が、エディタに既に表示されていることに注目してください。この機能は、スクリプトを作成する場合に非常に便利です。入力を開始するだけで、使用できる関数が表示されます。残念ながら、使用する必要があるパラメータは、この機能では示されません。使用する必要があるパラメータについては、ドキュメントを参照してください。申し訳ありません。
最初のいくつかのパラメータは平面とボックスのサイズを記述し、次の 3 つのパラメータは解像度を定義します。最後の 3 つの値は色を定義します(100% の白色)。スクリプトを実行するたびに古いグループ ノードを削除する 2 つの関数も追加しました。この関数がなければ、シーングラフ内に古いグループ ノードが散らばることになります。
次に、各ジオメトリの名前を追加し、setTranslation
関数を使用してシーン内でのジオメトリの移動を設定します。この関数は、シーン内の位置を示す x、y、z 成分を受け取ります。この setTranslation
関数は API バージョンの関数であるため、ベクトル表現ではなく、古いパラメータ セットを使用することに注意してください。
最後の手順で、これらの 2 つのジオメトリをグループ ノードに追加します。こうしないと、ジオメトリがメモリ内で浮遊した状態になり、シーングラフにアタッチされなくなります。[実行]をクリックすると、シーン内に新しいジオメトリが表示されます。
ノードを親から別のノードに移動することもできます。まず、「Another node」という別のノードを作成してみましょう。今回は、ノード typeTransform
を使用します。この方法では、setTranslation
関数を使用して、ノードを作成した後に移動することができます。
最初のサンプルと同様に、名前を使用して 2 つのジオメトリを見つけます。次に、新しいトランスフォーム ノードに対して addChild
関数を使用します。この方法では、グループ ノードからノードを削除して、トランスフォーム ノードに追加します。ジオメトリの位置も少し上に移動しました。
次に、新しいカメラを作成します。ここでは vrCameraService
を使用できます。また、シーン内の位置を設定して、外観を定義します。ここでは、vrCameraFromAtUp
タイプのオブジェクトを使用するカメラに対して setFromAtUp
関数を使用します。このオブジェクトを作成するには、コンストラクタを使用し、3 つのベクトルを入力して、位置、表示場所、およびシーン内の「アップ」側を定義するベクトルを定義します。最後に、新しいカメラをアクティブにして、シーン内のカメラが変更されていることを確認します。
現在のカメラ位置からビューポイントを作成する場合も、非常に簡単に行えます。この操作には、vrCameraService
を使用します。入力として名前を使用する createViewpoint
関数があります。この方法では、シーン内でカメラを移動したり、ビューポイントをキャプチャして、カメラ メニューからアクセスできるようにしたりできます。
次のサンプルでは、独自のマテリアルを作成します。createMaterial
関数を使用して、新しいマテリアルを 2 つ作成してみましょう。マテリアル タイプを指定する必要があります。マテリアル タイプについては、ドキュメントを参照してください。
ここでは、基本的なフォン マテリアルを作成します。マテリアルの色を設定するには、fieldAccess
を使用する必要があります。これは、ノードに保存されているほぼすべてのデータを操作して読み取ることができる特殊なモジュールです。
fieldAccess
については、別のチュートリアルで詳しく説明します。ここではこれを使用して、拡散チャネル内の赤と緑のマテリアルを定義します。スクリプトを実行してマテリアル エディタを開くと、2 つの新しいマテリアルがあることがわかります。変更を表示するには、マテリアル エディタを閉じて、再度開かなければならない場合があります。
もちろん、これらのマテリアルを新しいジオメトリに追加することもできます。ここでも、シーン内でジオメトリを見つけて、setMaterial
関数を使用してマテリアルを変更します。
最後のサンプルでは、新しいバリアント セットを作成します。この操作を行うには、入力として新しいバリアント セットの名前を使用する createVariantSet
関数を使用します。また、getVariantSet
関数を使用してバリアント セットを検索するときに、バリアント セットの名前をパラメータとして使用することもできます。もちろん、バリアント セットに内容を追加することもできます。次に、新しいバリアント セットに Python スクリプトを追加する方法を示す小規模なサンプルを示します。
これは、Python でスクリプトを作成するときに使用できる機能の一部にすぎません。シーンプレートの管理やアニメーションの作成など、たくさんの機能が表示されます。このサンプルは、みなさんに興味を持ってもらうためのものです。
VRED のサンプル セクションには多数のサンプルがあり、特定のタスクに対する解決策を検索することができます。たとえば、VRED シーンにメニューを追加する場合は、このメニューのサンプルを調べると、このサンプルの基本事項をすべて把握できます。
今日の説明はこれで終わりです。VRED の基本的な Python スクリプトの作成手順に関するビデオをご覧いただきました。ご参加いただき、ありがとうございました。またお会いしましょう。
これは、「チュートリアル 2: Python を使用して VRED 用のスクリプトを作成する方法」ビデオに付属する Python サンプル スクリプトです。
以下のファイルが含まれた ZIP ファイルをダウンロードするには、ここをクリックしてください。
コード スニペットをコピーし、VRED スクリプト エディタに貼り付けると Python のサンプルを実行できます。[実行]を押して結果を確認してください。
groupNode = vrNodeService.findNode("Group Node")
deleteNode(groupNode)
# Example 1.0:
# Finding nodes in the screnegraph
root = vrNodeService.findNode('Root')
camera = vrNodeService.findNode('Perspective')
print(root)
print(camera)
# Example 1.1:
# Creating new nodes
print()
print('---------------')
groupNode = createNode('Group', 'Group Node', root)
print(groupNode)
updateScenegraph(True)
# Example 1.2:
# Creating geometry and add them to the scenegraph
print()
print('---------------')
planeNode = createPlane(1000, 1000, 1, 1, 1, 1, 1)
planeNode.setName('Plane Geometry')
planeNode.setTranslation(100, 200, 10)
groupNode.addChild(planeNode)
boxNode = createBox(500, 500, 500, 1, 1, 1, 1, 1, 1)
boxNode.setName('Box Geometry')
boxNode.setTranslation(-100, -200, 10)
groupNode.addChild(boxNode)
# Example 1.3:
# Move nodes in the scenegraph
print()
print('---------------')
anotherNode = createNode('Transform', 'Another Node', root)
anotherNode.setTranslation(0, 0, 500)
planeNode = vrNodeService.findNode('Plane Geometry')
boxNode = vrNodeService.findNode('Box Geometry')
anotherNode.addChild(planeNode)
anotherNode.addChild(boxNode)
# Example 2.0:
# Create a new camera
camera = vrCameraService.createCamera("New Camera")
cameraFrom = QVector3D(2000, 2000, 5000)
cameraAt = QVector3D(0, 0, 0)
cameraUp = QVector3D(0, 0, 1)
fromAtUp = vrCameraFromAtUp(cameraFrom, cameraAt, cameraUp)
camera.setFromAtUp(fromAtUp)
camera.activate()
# Create a camera viewpoint from the current camera
viewpointName = 'New Viewpoint'
viewpoint = vrCameraService.createViewpoint(viewpointName)
# Example 3.0:
# Create a basic phong material
materialA = createMaterial("UPhongMaterial")
materialA.setName("Material A")
materialA.fields().setVec("diffuseColor", [1, 0, 0])
materialB = createMaterial("UPhongMaterial")
materialB.setName("Material B")
materialB.fields().setVec("diffuseColor", [0, 1, 0])
# Example 3.1:
# Create a material switch and add the newly created materials
materialSwitch = createMaterial("SwitchMaterial")
materialSwitch.setName("Material Switch")
materialSwitch.addMaterial(materialA)
materialSwitch.addMaterial(materialB)
# Example 3.2:
# Apply the material to geometry
plane = findNode("Plane Geometry")
box = findNode("Box Geometry")
materialA = findMaterial("Material A")
materialB = findMaterial("Material B")
plane.setMaterial(materialA)
box.setMaterial(materialB)
# Example 4.0
# Create a variant set
variantSetName = 'New Variant Set'
createVariantSet(variantSetName)
variantSet = getVariantSet(variantSetName)
# Example 4.1
# Add stuff to the variant set
variantSet.addScript("print('Hello World!')")
variantSet.addView(vrCameraService.getViewpoint('New Viewpoint'))