教程 7:如何使用 VRED 2021.3 中引入的新 vrdTransformNode 编写场景对象变换的脚本

教程 7:如何使用 VRED 2021.3 中引入的新 vrdTransformNode 编写场景对象变换的脚本视频介绍了 VR 中的摄影机和视点以及场景板的相关示例。

下载示例脚本

跳转到脚本示例

下载教程 PDF

视频字幕:大家好,欢迎学习面向 VRED Pro 的 Python 教程。我是主持人 Christopher,今天我想介绍如何使用新的 vrdTransformNode 来编写对象变换的脚本。

在 VRED 最新版本 13.3 之前,API v2 不包含我们在本视频中讨论的 vrdTransformNode 类。vrdTransformNode 类合并了可操纵几何体节点的所有变换操作。在先前的 VRED 版本中,您应该是使用 vrNodePtr 类中提供的函数(如 setTranslationsetRotation 等)进行变换的。与旧 vrdTransformNode 相比,新 vrNodePtr 自身的功能没有发生太大的变化。但是,我们使用这些函数的方式有所变化。

查看旧变换操作时,可以看到我们必须将所有参数作为单个值进行传递。因此,我们将矢量的 x、y 和 z 分量分别传递到函数中。返回值也是矢量分量的列表。

当前示例显示了一个简单脚本,用于创建两个点并计算它们之间的中心点。我们必须分别处理每个矢量分量,并将它们传递到平移函数。这都可以,直到我们执行一些矢量数学运算,例如计算两个位置之间的中心点。我们必须将这些值转换为正确的矢量表示形式,或编写自己的数学函数来完成此操作。在这里,我们只是手动计算值。

要解决此问题,所有变换操作现在都是 vrdTransformNode 的一部分,并使用新的 Qt 数据类型。新的数据类型将单独的 x、y 和 z 分量合并为单个矢量,并使我们能够直接在矢量数学运算中使用它们。看一下与之前相同的示例,我们可以看到不必手动计算中心点。我们可以直接将两个矢量相加,除以二,然后使用结果矢量作为平移函数的输入。因此,我们不必导入外部库或编写自己的矢量运算。这样,代码更具可读性,更容易维护。

我们再看一个示例。我想生成许多长方体,它们沿一条线以螺旋方式旋转。它们应相互旋转,并根据位置更改其比例。这是一个很好的示例,可显示某些变换操作如何工作。当然,我们可以使用旧 API 执行此操作,但新的变换节点可帮助我们更好地完成数学运算。

首先,我们在希望长方体所在的位置创建一个组节点。我们定义几个变量来控制长方体螺旋的行为。下一步是循环创建长方体,将它们添加到组节点,然后沿 X 轴移动它们。createBox 函数从旧 API 返回节点指针,因此我们必须使用 getNodeFromId 函数将其转换为 vrdTransformNode。然后,我们创建一个简单的矢量,其中包含我们的平移,并放入长方体的 setTranslation 函数中。循环的“i”参数负责将每个长方体沿 X 轴稍微向前移动一点。

接下来,我们要更改长方体沿 X 轴的缩放比例。为此,我们首先获得长方体的当前缩放比例,然后将其乘以随循环增量增加的较小因子。我们使用结果矢量作为 setScale 的输入参数,并看到这些长方体现在变得更大。

最后一步,我们要使长方体绕中心线呈螺旋状。对此,请大家相信我。首先,我们创建一个旋转矢量,其中保存旋转的 Euler 角度,并设置长方体的旋转。这样,每个长方体都能很好地旋转。现在,我们使用零矢量调用 setWorldRotatePivot 函数,使用指定旋转轴位置的矢量调用 setRotatePivotTranslation。它基本上会使旋转轴远离长方体,以便旋转变换偏移并生成这样美观的螺旋效果。旋转不再应用于长方体的中心,而是应用于长方体上方的 X 轴。

正如我之前所说,我们可以使用旧 API 实现相同的结果,但使用新的变换节点会更容易。在 Qt 框架文档中搜索“Python QT 矢量”时,您可以找到有关这些新数据类型的文档。例如,在 Qt 矢量文档中,可以找到使用此数据类型可以执行的所有数学函数,如加减基础运算或规格化矢量等函数。我们还有另一个教程,更深入地介绍 VRED 中的新数据类型。

好,今天就到这里。希望您喜欢。感谢您的参与,欢迎学习我们的下一教程。


Python 代码示例

下面是教程 7:如何使用 VRED 2021.3 中引入的新 vrdTransformNode 编写场景对象变换的脚本视频随附的 Python 脚本示例。

提示:

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

old_vs_new_transformations.py

# Old API transformations

# Create a point p1
x1 = -500
y1 = 0
z1 = 1500

p1 = vrNodeUtils.createSphere(1, 100, 1, 1, 1)
p1.`setTranslation`(x1, y1, z1)
p1.setName("p1")

# Create a point p2
x2 = 500
y2 = 0
z2 = 500

p2 = vrNodeUtils.createSphere(1, 100, 1, 1, 1)
p2.`setTranslation`(x2, y2, z2)
p2.setName("p2")

# Create a point p_center at the geometrical center between p1 and p2
x_c = (x1 + x2) / 2
y_c = (y1 + y2) / 2
z_c = (z1 + z2) / 2

p_center = vrNodeUtils.createSphere(1, 100, 1, 1, 1)
p_center.`setTranslation`(x_c, y_c, z_c)
p_center.setName("p_center")


# NEW API transformations

# Create a point p1
v1 = QVector3D(-500, 500, 1500)
p1 = vrNodeUtils.createSphere(1, 100, 1, 1, 1)
vrNodeService.getNodeFromId(p1.getID()).`setTranslation`(v1)
p1.setName("p1")

# Create a point p2
v2 = QVector3D(500, 500, 500)
p2 = vrNodeUtils.createSphere(1, 100, 1, 1, 1)
vrNodeService.getNodeFromId(p2.getID()).`setTranslation`(v2)
p2.setName("p2")

# Create a point p_center at the geometrical center between p1 and p2
v_center = (v1 + v2) / 2
p_center = vrNodeUtils.createSphere(1, 100, 1, 1, 1)
vrNodeService.getNodeFromId(p_center.getID()).`setTranslation`(v_center)
p_center.setName("p_center")

vrdTransformNode.py

groupNode = vrNodeService.findNode("Group")
deleteNode(groupNode)

numberOfBoxes = 50
boxSize = 50
xStep = 125
xRotationStep = 20
z = 500
radius = 400

boxGroup = createNode("Group")

for i in range(0, numberOfBoxes):
    box = vrNodeUtils.createBox(boxSize, boxSize, boxSize, 1, 1, 1, 0, 0, 0)
    box.setName("box {}".format(i))
    boxGroup.addChild(box)
    
    # Get the vrdNode object of the box
    boxNode = vrNodeService.getNodeFromId(box.getID())
    
    boxTranslation = QVector3D(xStep * i, 0 ,z)
    boxNode.`setTranslation`(boxTranslation)
    
    boxScale = boxNode.getScale() * (1 + (i * 0.01))
    boxNode.setScale(boxScale)
    
    boxLocalRotation = QVector3D(xRotationStep, 0, 0) * i
    boxNode.`setRotation`AsEuler(boxLocalRotation)
    
    boxNode.`setWorldRotatePivot`(QVector3D(0, 0, 0))
    boxNode.`setRotatePivotTranslation`(QVector3D(0, 0, z + radius))