了解如何使用 Python 为 VRED Pro 编写脚本,以及查看一些示例以开始开发您自己的脚本。
视频字幕:大家好,欢迎学习我们的系列教程“使用 Python 为 VRED Pro 编写脚本”。我是主持人 Christopher,在本视频中,我将介绍在 VRED 中开发时所需的一些 Python 基础知识。我还将向您展示一些示例,帮助您开始开发自己的脚本。
Python 是一种解释性编程语言,在插件开发中应用广泛。还有许多其他 CGI 工具提供了 Python 界面,这不仅仅是一个巧合。Python 是一种非常有表现力的语言,易于学习。与 C++、C# 或 Java 等编程语言相比,它不需要进行编译,因此您只需编写一些代码,点击“运行”,代码就会立即执行您要求的操作。Python 还可以与 C++ 完美地搭配使用,之所以说完美,是因为在后台 VRED 也使用 C++。为大家提供一些在聚会上谈论的话题。
当 Autodesk 推出 API v2 时,他们从 Python 2.7 转换为 Python 3。这很正常,因为对 Python 2.7 的官方支持已于 2020 年 1 月停止。但是,如果您的脚本仍使用 Python 2.7,不必担心,VRED 提供了一个选项,可自动将 Python 2.7 转换为 Python 3。
关于 Python 和 VRED,我还能说什么呢…嗯,VRED 使用其自己的集成 Python 3 解释器。这样,可以直接将 VRED API 注入 Python 环境。
这对我们意味着什么?Python 通过模块提供所有功能。它们只是类和函数的集合。VRED API 也是如此。它是模块的集合。通常,必须手动导入所有这些模块才能使用它们。例如,如果想要使用 vrNodeUtils
模块,则必须键入“import vrNodeUtils”来导入它。但是 VRED 已经为我们添加了所有这些模块,因此我们不必这样做。这使得 VRED 内的脚本更具可读性,并减少了大量额外的代码。
当开发外部模块或脚本插件时,请务必小心。在这里,您必须明确导入 VRED API,但仅导入 API v1。在接下来的视频中,我将对此进行更详细的讨论。
我们来看一些真实的示例。它们不会太复杂,但这只是简单的热身。在很多脚本中,您都必须以某种方式访问“场景图形”。“场景图形”是三维图形的中心部分,包含有关几何体、灯光、变换等的所有信息。它是一个从根节点开始的层次结构,将场景分为变换节点、组节点或切换节点,直到几何体本身。在典型脚本中,您可以将节点或几何体添加到“场景图形”中,将节点从一个位置移动到另一个位置,或者在“场景图形”中查找节点以对其进行操纵。
在第一个示例中,我们首先在“场景图形”中搜索节点。我们打开位于菜单栏中“编辑”下的“脚本编辑器”,然后输入脚本。首先,使用 vrNodeService
搜索场景的根节点和摄影机节点。如“场景图形”中所示,摄影机节点称为 Perspective
。
在“场景图形”中,节点通常按其名称来引用。我们将此操作的结果存储为一个变量,该变量现在包含 vrdNode
类型的对象。vrdNodes
是在 API v2 中定义的。我们可以通过点击“运行”按钮来执行脚本,并在终端的输出消息中查看结果。此消息告知我们这两个变量现在包含的对象类型。
接下来,我们要创建新节点,并将其添加到“场景图形”中。在这里,我们将创建一个 Group
类型的节点。您可以查看文档,查找可以创建的所有节点类型。为了创建节点,我们将使用带有三个参数的 createNode
函数:第一个参数定义节点类型,第二个参数设置其名称,第三个参数告知 VRED 哪个节点是新节点的父节点。在本例中,我们希望新节点位于场景的根节点下。之后,我们要从 vrSceneGraph
模块调用 updateSceneGraph
函数。此命令将直接在“场景图形”中显示更改。
我们来创建某个几何体,并将它添加到新的组节点中。通过使用一组用于创建基本几何体的函数,可实现此目的。在这里,我们使用的是 createPlane
和 createBox
函数。
请注意,在开始键入时,编辑器会提示我们可以使用的函数。这在编写脚本时非常有用。您只需开始键入,然后查看可用的函数。遗憾的是,此功能不会告诉您需要使用哪些参数,此时需要阅读文档。抱歉。
前几个参数描述平面和长方体的大小,接下来的三个参数定义分辨率,最后三个数字定义了颜色,即 100% 白色。我还添加了两个函数,只要我执行脚本,就会移除旧的组节点。否则,“场景图形”就会被旧的组节点弄得乱七八糟。
接下来,我们为每个几何体添加一个名称,并使用 setTranslation
函数设置其在场景中的平移。此函数会接收描述场景中位置的 x、y 和 z 分量。请注意,此 setTranslation
函数来自 API 版本,并使用旧的参数集,而不是矢量表示。
在最后一步中,我们将这两个几何体添加到组节点中。否则,几何体将在内存中的某个位置浮动,但永远不会附加到“场景图形”。现在,点击“运行”时,可以在场景中看到新的几何体。
我们还可以将节点从其父节点移动到另一个节点。让我们先创建另一个名为“Another node”的节点。这次,我们使用节点 typeTransform
。这样,我们可以在创建节点后使用 setTranslation
函数平移该节点。
如第一个示例中所示,我们使用两个几何体的名称来查找它们。然后,我们使用新变换节点的 addChild
函数。这样,我们将从组节点中移除该节点,并将该节点添加到变换节点。您还会看到,几何体现在向上移动了一点儿。
接下来,我们要创建新的摄影机。在这里,我们可以使用 vrCameraService
。我们还要设置它在场景中的位置,并定义它的朝向。在这里,我们使用摄影机的 setFromAtUp
函数,它需要一个 vrCameraFromAtUp
类型的对象。我们可以通过使用构造函数来创建此对象,输入三个矢量来定义位置、朝向,输入一个矢量来定义在场景中哪一侧“向上”。最后,我们激活新的摄影机,然后看到场景中的摄影机已更改。
从当前摄影机位置创建视点也很容易。这也可以通过 vrCameraService
完成。它有一个 createViewpoint
函数,只需要一个名称作为输入。这样,我们可以在场景中移动摄影机,并捕获可以在摄影机菜单中访问的视点。
在下一个示例中,我们要创建自己的材质。我们来使用 createMaterial
函数创建两个新材质。我们必须指定材质类型,如文档中所述。
在这里,我们要创建基本的 Phong 材质。要设置材质的颜色,需要使用 fieldAccess
。这是一种特殊的模块,它使我们基本上可以操纵和读取节点中存储的所有数据。
我将在另一个教程中更深入地讨论 fieldAccess
。请注意,我们在这里使用它来定义漫反射通道中的红色和绿色材质。当我们运行脚本并打开“材质编辑器”时,可以看到现在有两个新材质。可能需要关闭“材质编辑器”并再次打开,这样才能显示更改。
当然,我们还希望将这些材质添加到新几何体中。同样,我们在场景中找到几何体,然后使用 setMaterial
函数更改其材质。
在最后一个示例中,我们要创建一个新的变量集。这可以通过 createVariantSet
函数来完成,该函数需要新变量集的名称作为输入。我们还可以使用变量集的名称作为参数,通过 getVariantSet
函数查找变量集。当然,我们也可以向变量集添加内容。下面只是一个小示例,说明如何将 Python 脚本添加到新的变量集。
这只是使用 Python 编写脚本时可能实现的功能的一小部分。还有很多内容要向您展示,例如管理场景板、创建动画等等。这几个示例只是为了让您产生兴趣。
请记住,VRED 的示例部分中有许多示例,您可以在其中搜索特定任务的解决方案。例如,如果要向 VRED 场景添加菜单,可以查看此菜单示例,它会告诉您相关内容的所有基础知识。
好,今天就到这里。希望您喜欢我们今天有关在 VRED 中进行基本的 Python 脚本编写的视频。感谢您参加本课程,下次见。
这是教程 2:如何使用 Python 为 VRED 编写脚本视频的随附 Python 脚本示例。
要下载这些压缩文件,请单击此处。
通过将代码段复制并粘贴到 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'))