教程 6:如何借助服务和对象使用 V2 界面

教程 6:如何借助服务和对象使用 V2 界面视频介绍了 VR 中的摄影机、视点和场景板的相关示例。

下载示例脚本

跳转到脚本示例

下载教程 PDF

视频字幕:大家好,欢迎学习这一面向 VRED Pro 的新 Python 教程。我叫 Christopher,今天我将介绍新的 API v2、为什么其工作方式不同,以及如何使用它。

随着 API v2 的发布,Autodesk 引入了一个新的对象模型,旨在更轻松地在 VRED 中使用 Python 界面。它引入了关键功能(即所谓的服务类),并提供了更多面向对象的数据类型供您使用。要理解为什么这是一件好事,我们首先必须讨论之前 API 的缺点。

我们来看看以下示例。版本 1 API 通常使用单独的值作为参数。举例来说,当您只想使用单个矢量的 X、Y 和 Z 值时,这没问题。但是,当一个函数需要多个矢量或矢量分量时,这会变得非常混乱。一个更好的方法是,将这些参数封装在一个对象中,该对象清楚地描述它应该是什么,比如矢量。对于返回值也是如此。

在 API v1 中,如果返回值是矢量的分量,我们会看到函数返回单个值或值列表。开发人员必须知道函数的返回值类型,才能知道这个返回值列表应该是什么。当函数返回单个对象(例如矢量)时,可以立即识别它。

API v1 的另一个缺点是它基于 Python 2.7。并不是 Python 2.7 版本不好,但使用 Python 3,提供完全静态类型的 API 要容易得多。虽然动态类型有吸引人之处,但是使用静态类型构建一致的 API 会更加容易。

在我看来,API v2 在很多方面都进行了改进。首先,它引入了多个专门的服务类,现在用作与 VRED 交互的主要方式。vrNodeServicevrSessionService 等服务将针对该特定主题的所有功能合并在一起。例如,会话服务包含管理协作会话的功能。摄影机服务使您能够管理摄影机和视点。这样可以更轻松地找到正确的函数,举例来说,所有与摄影机相关的功能现在都位于 vrCameraService 以及新的摄影机类型 vrdCameraNodevrdCameraBaseNode 中。

新 API 引入了一系列数据类型,这些数据类型封装了一段数据的功能。这些新类型都带有前缀“vrd”。例如,如我刚才所说,vrdCameraNode 包含有关场景中摄影机的所有信息。同样,vrdSessionUser 类型的对象包含协作会话中特定用户的所有相关信息。

每个新类型都包含添加或更改对象数据的函数。因此,如果要更改摄影机的设置(如其焦距),首先应从 vrCameraService 获取 vrdCameraNode 类型的对象,然后使用函数 setFocalLength 更改设置。VRED 中还有许多其他新类型的各种数据,我们在这里只是简单地介绍一二。例如,vrdPointLightNode,它提供了在场景中操纵点光源所需的功能。

另一个优点是,新 API v2 附带的其他支持数据类型的范围。我已经提到了矢量数据类型。它们组合了现在已明确标记为矢量的单独数字。这样,您的代码更具可读性,更容易理解。每个开发人员立即知道此函数需要一个矢量作为输入,而另一个函数返回一个矢量。另一个优势是,这些新数据类型附带数学运算,您可以直观地使用它们。下面我们来看几个例子。

首先,我想介绍新服务的基本用法。使用它们并没有什么困难。在此示例中,我们要了解如何使用 vrCameraService 来操作摄影机。首先,我们在场景中创建一个新摄影机。我们使用 vrCameraService 中的 createCamera 函数并为其提供一个名称。此函数的返回值是我们指定给变量的 vrdCameraNode

现在,我们可以使用此摄影机节点对象来创建新的摄影机轨迹。这也可以通过 vrCameraService 和函数 createCameraTrack 来完成。这次,返回值是 vrdCameraTrack 对象,我们也将其存储在变量中。

我们可以进一步旋转它,并在此摄影机轨迹上创建新视点。我们只需使用 vrCameraService 中的 createViewpoint 函数,并将摄影机轨迹对象用作输入参数。当我们查看摄影机编辑器时,可以看到我们创建的所有对象。

在下一个示例中,我们要在场景中创建一些光源。同样,我们可以使用 vrLightService 及其函数 createLight。这次,我们必须提供名称和灯光类型作为输入参数。

API v2 还包含带有某种类型的类。在此示例中,我们需要的 vrLightType 为点灯光。请不要将这些类型与我们之前在本视频中讨论的数据类型混淆。在新 API 中以“type”结尾的所有类都定义了一组不同的内容,或者说,类型。例如,灯光可以是点灯光、聚光灯、平行光等类型。使用此灯光类型,我们可以告知灯光服务要创建哪种灯光。

在摄影机示例中,我们已经接触了一些新的“vrd 对象”。当回到这个示例时,我们不仅可以使用摄影机服务创建新对象,还可以更改摄影机、摄影机轨迹和我们创建的视点。

首先,我想更改摄影机的位置。这可以通过定义摄影机应该位于的位置、摄影机的视点以及指示场景中“向上”的方向来完成。我们通过使用 fromAtUp 数据类型(用我们定义的矢量馈送)来设置这些值。这会将摄影机对准场景的中心。之后,我们激活摄影机以立即查看结果。

当然,我们可以用类似的方式更改其他对象。例如,我们可以使用函数 createPreview() 更新视点的预览。这将创建当前场景中视点的新预览。

在最后一个示例中,我想介绍新的数据类型如何让您的工作更轻松。我们在即将发布的视频中提供了更详细的教程,因此我现在不会讲得太深。只需注意我们如何使用新的矢量类型来封装矢量分量,并使整个脚本更具可读性且更短。

在右侧,我们创建几个几何体,并设置其在三维空间中的位置。在左侧,是使用 API v1 中的函数编写脚本的同一个示例。至少对我来说,它更具可读性,也更容易理解。您还可以看到,我们可以使用矢量类型提供的数学运算来使脚本更短。

有关文档的最后一点说明。在文档中,您可以看到版本 1 中已被版本 2 替换的所有函数。这些函数称为“已弃用”。这基本上意味着,它们仍然可用,但将来可能被移除或替换。

例如,在版本 2 中,几乎所有包含在 vrCamera 中的函数都被现在包含在 vrCameraServicevrdCameraNodevrdCameraBaseNode 中的函数所替换。在编写新脚本时,您应避免使用已弃用的函数。它们仍然起作用,但使用新的 API,您会更加安全。当您查看页面顶部时,还会看到一个指向版本 2 中现在包含此功能的类的链接。

在 API v2 中,Autodesk 为 VRED Python 界面引入了令人兴奋的新变化。当您熟悉编写脚本后,使用新的类和数据类型应该没有问题。当您刚开始时,我希望能帮助您快速入门。今天就到这里。希望您喜欢此视频,下次见。


Python 代码示例

下面是教程 6:如何借助服务和对象使用 V2 界面视频随附的 Python 脚本示例。

提示:

要下载这些压缩文件,请单击此处

camera.py

import math

# Example 1.0
# Get active camera with vrCameraService
camera = vrCameraService.getActiveCamera()

# Set Focal Length
camera.setFocalLength(35)


# Example 2.0
# Creating a camera using API v1 and settings its fov to 35
vrCamera.selectCamera("Perspective")
camera_v1 = vrCamera.getActiveCameraNode()

# read field of view mode (0 := vertical, 1 := horizontal)
fov_mode = camera_v1.fields().getUInt32("fovMode")
sensor_size = camera_v1.fields().getVec("sensorSize", 2)

# calculate fov based on sensor size
fov = vrOSGWidget.getFov()
focal_length = 35

if fov_mode is 0:
    fov = 2 * math.degrees(math.atan((sensor_size[1] / 2) / focal_length))
else:
    fov = 2 * math.degrees(math.atan((sensor_size[0] / 2) / focal_length))

vrOSGWidget.setFov(fov)


# Example 3.0
# Creating a camera using API v2 and calculating the fov manually
camera_v2_1 = vrCameraService.createCamera("Camera v2_1")

# read field of view mode (vertical or horizontal)
fov_mode = camera_v2_1.getFovMode()

# read sensor size as QtVector2D
sensor_size = camera_v2_1.getSensorSize()

# calculate fov based on sensor size
fov = camera_v2_1.getFov()
focal_length = 50

if fov_mode is vrCameraTypes.FovMode.Vertical:
    fov = 2 * math.degrees(math.atan((sensor_size.y() / 2) / focal_length))
else:
    fov = 2 * math.degrees(math.atan((sensor_size.x() / 2) / focal_length))

camera_v2_1.setFov(fov)

light.py

# Example 1

# Get vrdPointLightNode with the vrLightService
myPointLight = vrLightService.findLight("MyPointLight")

# Set the ground shadow intensity
myPointLight.setGroundShadowIntensity(0.5)

service.py

#Example 1

# Get the active camera from the camera service
camera = vrCameraService.createCamera("My New Camera")

# Create a new camera track on the camera object
cameraTrack = vrCameraService.createCameraTrack("My New Camera Track", camera)

# Create a new viewpoint on the camera track
viewpoint = vrCameraService.createViewpoint("My New Viewpoint", cameraTrack)


#Example 2

# Create a new pointlight with the vrLightService
newPointLight = vrLightService.createLight(
                    "My New PointLight",
                    vrLightTypes.LightType.Point
                )
                
# Set the translation of this pointlight                               
newPointLight.setTranslation(QVector3D(0,0,1000))


#Example 3

# Create a new camera with the vrCameraService
camera = vrCameraService.createCamera("New Camera")

# Create vectors that define the location and look-at point of the camera
cameraFrom = QVector3D(5000, 8000, 3000)
cameraAt = QVector3D(0, 0, 0)
cameraUp = QVector3D(0, 0, 1)

# Set the camera parameters
fromAtUp = vrCameraFromAtUp(cameraFrom, cameraAt, cameraUp)
camera.setFromAtUp(fromAtUp)

# Activate the camera
camera.activate()


# Create a new camera track on the camera object
cameraTrack = vrCameraService.createCameraTrack("My New Camera Track", camera)

# Create a new viewpoint on the camera track
viewpoint = vrCameraService.createViewpoint("My New Viewpoint", cameraTrack)

viewpoint.createPreview(True)