这是由来自日本游戏公司的高级TA(技术艺术家)MaximeJeanmougin所写的博客文章,它很好的向我们解释了Bifrost里数据结构的高级操作。Bifrost节点可视化编程是非常底层和开放的,它的目标是超越传统的c++代码式编程,让艺术家或者TD、TA等技术家轻松地构建自己的大型高性能工具。
MAXIMEJEANMOUGIN–技术艺术家
欢迎来到博客!我叫MaximeJeanmougin,我是一名法国角色技术艺术家,目前在日本大阪的PlatinumGames工作,我在3D领域拥有大约8年的经验,主要从事角色FX方面的工作,还从事程序设计和绑定等其它领域。我在视觉编程方面的旅程始于年的ICE,在Softimage之后转入FabricEngine。在年,我加入了BifrostBeta计划,从此我就获得了很多乐趣。在此博客中,我将尝试分享自那时以来我收集的一些知识。
正文
欢迎回到博客!自从我写上一篇文章以来已经有很长时间了。今天,我想谈谈Bifrost的另一个高级和隐藏功能:自定义数据结构。这些可以在图形中或化合物内部使用,在涉及可视化编程的复杂方案时,它们非常有用,在这种情况下,仅处理标准数据结构将使事情变得非常混乱。
第1部分:原始数据类型
在进入主题的核心之前,让我们从基础开始。与常见的编程语言一样,Bifrost中的数据类型也基于基本数据类型。这些是人们可以使用的最低级别的数据类型。每种数据类型都有不同的大小,该大小定义了用于存储值的内存量。较大的数据类型允许使用更大范围的值。
在Bifrost中,所有这些类型都列在“SetValueTtype”对话框的“简单”选项卡中,可通过使用value节点进行访问,在右键单击节点的自动类型端口时也可以使用这些类型。以及任何可编辑化合物的端口。
“SetValueTtype”对话框,通常用于设置数据类型
第2部分:数据结构
现在我们已经了解了原始数据类型,我们可以跳到下一个主题并开始讨论“数据结构”。这些是由多种原始数据类型组成的数据类型。最常用的数据结构是float3(通常用作向量或颜色)。它仅由3个浮点数组成。如果使用值节点并将类型设置为Math::float3,然后单击图标,则可以清楚地看到3个结构成员是浮点型。
Math::float3数据结构
在Bifrost中,几乎所有的不是原始类型的数据类型都是数据结构。确定数据类型是否为数据结构的最简单方法是将鼠标悬停在端口上,然后在“图形编辑器”的信息栏中检查数据类型的名称。如果数据类型的名称具有名称空间,则您正在处理数据结构。仅原始类型使用纯名称,当使用具有单个值的值节点时,您还可以检查是否有一个+图标,表示该数据类型具有成员。请注意,还有一些数据结构不会显示成员。对于已编译的硬编码数据类型就是这种情况。
Bifrost中的所有数据类型都可以用于多维数组。当在数组中使用数据类型时,Bifrost将通过在数组标志的尖括号之间封装数据类型的基本名称空间来更改数据类型的名称,如下所示:arrayxxx。如果我们要处理多维数组,那么先前的数据类型也将封装到另一个array中,依此类推。
数组的float和float3数据类型
Bifrost中的大多数标准数据结构都在Math::名称空间下,但是在“SetValueTtype”对话框的“其他”选项卡中也可以找到其他数据结构。GeoLocation是内置的高级数据结构的一个很好的例子。如您所见,单个geoLocation值存储其他数据结构,例如Math::float4和Math::uint4,它还存储数组数据类型,例如arrayfloat和arrayuint,甚至包含一个枚举类型!
GeoLocation数据结构,在哪里找到以及它所拥有的成员
这是可以与值节点一起使用的技巧。您可以使用数据类型的非数组版本来设置其类型,如果您插入与其输入相同数据类型的数组,那么Bifrost的自动循环功能将启动,您可以访问所有数组的数据结构的成员。相反,如果直接在值节点上设置数据类型的数组变量,则+图标消失,并且无法访问其成员,就像在第一个值节点上看到的那样。这就是为什么我建议始终将数据类型的非数组版本与值节点一起使用的原因。
在单值GeoLocation值节点上自动循环播放
第3部分:自定义数据结构
是时候学习如何制作我们自己的自定义数据结构了!但是在此之前,我想谈几件事,关于何时,为何使用它们以及如何最大程度地利用它们。首先让我向您展示我自定义数据结构之一,该结构是我在MJCG化合物2.0中提供的ivy生成器内部使用的。
如您所见,成员很多。在常春藤求解器内部,在每个成长步幅中,所有这些成员都将在几个不同的循环中进行多次迭代。为了使常春藤生长并生成线和叶实例的几何形状,这是必需的。
您能想象如果每个循环中每个成员都有一个端口,该复合物会是什么样?还有所有电线?它将变得一团糟,以至于在可视化编程环境中将变得难以管理。
在这种情况下,这种迭代的化合物上,每个数据结构我只需要使用一个状态端口,这使得该化合物更干净,更高效,因为增加状态/迭代端口的数量会导致很小的性能损失。
通过将每个子数据存储到Amino对象中可以完成相同的操作,但是我喜欢处理数据结构的另一个很棒的功能。在下图中,我展示了如何使用数据结构仅更新一个或几个成员,而保留所有其他成员。
如果仔细看,您会发现主结构的数据是通过output和value之间的连接保留的,只有leaf_size和stem_size插入第二值节点。通过使用这样的结构,我们不必在两个值节点之间连接每个成员。只有与输入连接的成员才会被覆盖,而该结构的所有其他成员保持不变。
如果要使用Amino对象执行相同的操作,则可以肯定以相同的方式在对象内部维护一些子数据,但是对于每个要更新的子数据,我们必须使用set_property或set_geo_property节点,这将产生更混乱的图。由于数据结构的原因,我们不需要处理任何此类问题。我们只是将更新的数据插入到我们想要的成员中。然后瞧瞧,没有混乱,没有性能损失。
仅更新某些数据结构成员,并保留其他成员
聊够了!是时候创建我们自己的了!首先创建一个JSON文件并给它一个适当的名称,然后将其放置在我们的自定义化合物库中。因为您的化合物将保留对该文件名称的引用,所以在开始时正确设置它而不要再次处理它是很重要的。万一您更改其名称,使用数据结构的化合物仍然可以正常加载,但是在Bifrost加载时,它可能会生成少量错误消息,因此请记住这一点。
我们的自定义数据结构的json文件
现在最重要的是自定义数据结构的.json文件的内容。如您所见,这些结构看起来与我们在自定义枚举教程中创建的JSON文件非常相似。不同之处在于,在这里,我们声明的是数据结构而不是枚举。这里有两件重要的事情,因此请务必仔细阅读。
在第13行,我们在此处设置自定义数据结构的名称空间。确保首先正确设置。如果您开始使用图形中的数据结构,后来又决定对其进行更改,则将不会加载所有正在使用它的化合物!而且它也可能阻止Bifrost加载!所以要小心。如果决定以后更改它,则必须编辑所有化合物的JSON文件,并手动替换所有出现的命名空间。
然后,在第16和17行,我们声明数据结构成员的名称和数据类型。在这里,您应该注意正确设置数据类型,否则,在加载Bifrost时,无效成员将不会成为数据结构的一部分。但是,成员比名称空间更安全地进行修改。如果您以后决定更改成员的名称或其数据类型,您的化合物仍然可以正常加载,但是连接到已修改成员的端口将断开连接,而其他成员仍将按预期工作。因此,您只需要重新连接几个端口即可。没什么大不了。
JSON文件准备好后,让我们重新加载Bifrost,获取一个值节点,然后在“SetValueTtype”对话框的“Other”选项卡中找到我们的自定义数据结构。选择类型,单击“确定”,然后瞧瞧!我们已经成功地将自定义数据结构加载到Bifrost中。从现在开始,它可以在从值节点节点到端口的任何地方使用。由于Bifrost的数据类型机制,您的自定义数据结构将可以用作数组。
我们在value节点上的自定义数据结构!
第4部分:结论
因此,本文结束了有关如何在Bifrost中设置自定义数据结构的教程。如果您是初学者,或者对Bifrost的可视化编程不太熟悉,我建议您不要使用它们,因为自定义数据结构将在高级和复杂的场景中使用。在大多数情况下,最好使用标准Amino对象并将数据存储为属性。但是,如果您觉得自己处于中级或高级水平,那么在进行更复杂的编程时,我绝对建议您使用它们!定制数据结构可以通过减少化合物上的端口和电线的数量来使可视化编程更加令人愉悦,并且在仅更新其成员之一时它们也可以派上用场。
最后,一个新的名为BifrostAddicts的Slack频道于几个月前诞生,它是寻求帮助并分享您的Bifrost实验的好地方。
欢迎加入这个汇聚世界各地的艺术家,技术家和Bifrost官方团队的聊天社区。并且特有一个中文频道。