最近我对节点编辑感兴趣,并且我引用了编辑器,例如在Maya,Blender,Substance Painter中看到和使用的编辑器,以及也在Unreal Engine 4。
我的代码分为两部分,一部分处理UI(创建节点,移动节点,附加节点)另一部分,我现在正在处理的是基本上读取图形的解释器
这里有一个屏幕截图,显示了由边缘连接的三个节点(它们的指向总是这样:粉红色 - >绿色)。一个节点可以有多个参数(绿色码头)和多个返回值(绿色码头)。
为了清楚起见,我有一个对象在屏幕上发生变化时更新(节点连接,节点创建/删除)。我想创建一个解释/读取图形的算法,以便运行节点描述的程序。
我发现this reddit thread帮助我理解了这个问题。但是,我仍然没有足够的信心开始为它编写代码。
我假设需要有一个起始节点,一些东西可以启动图形的读取但是我面临的问题是当它变得更复杂时,例如具有多个输入节点的图形。
(Bellow图像的注释为红色。)
答案 0 :(得分:1)
有关节点图的更多详细信息:
绿色码头是来自其他节点的变量,因此它们是 必然是前一节点输出的对象。另一方面 方形码头是常数。
我将“控制对象”称为包含图表中停靠点之间所有链接的对象。
- 开始算法 -
搜索所有输入节点,表示左侧没有链接的所有节点(无参数)。
这张图上有五个:A,B,C,E和K左边只有恒定的底座:A1,B1,B2,C1,E1,E2,K1和K2都是 定义的变量。
节点是函数,输入节点是没有参数的函数。不需要其他值,因此我们可以计算 这五个节点的输出。
这些输出是A2,B3,C2,E3,E4,K3。
使用我们的控制对象,我们知道哪些码头连接到这四个输出
他们像这样链接:A2 - > D1; B3 - > D2; C2 - > D3; C2 - > F1; E3 - > G2; E4 - > J1; K3 - > N3
注意:连接多个绿色码头的粉色码头将被处理,就像有多个相同的粉红色码头一样。这里,例如,节点C的输出C2可以被视为C2和C2'(因为C2链接到D3和F1)。总的来说,我们有7个链接进行分析。
再次使用我们的控制对象,我们将查看这7个链接的最终位置。
它们以D,F,G,J和N节点结束
他们最终在五个不同的节点上。现在,我们可以计算D输出,F输出,G输出,J输出和N输出吗?要么 我们还需要其他我们现在没有的变量吗?
节点D有三个参数,只是我们有三个参数:D1,D2,D3所以我们可以计算D的输出权 现在:D4 节点F只有一个参数,我们有F1,我们可以计算F的输出:F2 节点G有两个参数,但我们只有G2,我们无法计算G的输出=>将G2存储在控件对象的G等待队列中 节点J同样我们有J1而不是J2 =>将J1存储在控件对象中的J等待队列中 节点N有三个参数但我们只有N3
在此步骤结束时,我们计算了D4和F2,并在控制对象中存储了以下值:N3(尚未使用) 因为我们还没有N1,N2),G2(因为我们没有G1)和 J1(因为我们没有J2)。现在让我们来看看D4和F2的结束点 达
D4最终在G节点上:在G1底座上(因此D4底座中的对象等于G1中的对象) F2最终在J节点上:在J2基座上(在此处相同)
我们可以计算G和J吗?
对于G,我们在2上有2个参数,所以我们可以得到G3 对于J,我们在2上有2个参数,所以我们可以得到J3
检查G3和J3的结束位置
H,I和L节点
我们可以计算它们吗?
H有两个参数:H2等于G3,另一个是set =>我们计算H3 我有两个参数:I1等于G3,另一个是set =>我们计算I3 L只有一个参数:L1 =>我们计算L2
H3,I3,L2最终在哪里?
M和N
我们可以计算M和N吗?
M有两个参数,我们有M1和M2 =>我们可以计算M3 N具有三个参数,我们从存储在N的参数阵列中的第一步中得到N3,并且N2等于L2 =>我们无法计算N
我们还有一个顶点需要整理:M3
它转到N,M3 = N1
我们可以计算N?
现在我们可以因为我们有N1,N2,N3 =>我们可以计算节点N(在这种情况下没有输出)
没有更多顶点要排序
- 结束算法 -
答案 1 :(得分:0)
之前的答案存在的问题是它只涉及简单/线性程序。换句话说,它无法处理条件检查等操作:if, else
以及大多数循环:for
和while
。根据我与mapofemergence的讨论,我决定在这个问题上工作,以便创建一个更通用的解释器,可以编译几乎任何图形结构。所以,这是节点图解释器的更新!
我一直在寻找虚幻引擎文档,我发现了一些关于节点图如何工作的非常酷的东西。基本上,它们在称为execution links
的节点之间具有不同类型的链接。此外,它们还有其他类型的节点control nodes
来处理条件和循环。所以在这个答案中,我将着眼于如何实现它们以及解释器如何运行以运行它们。
让我们举两个简单的例子:
// CODE A
total = 0
for(i = 0; i < 10; i++) {
total++;
}
print(total)
和
// CODE B
total = 0
for(i = 0; i < 10; i++) {
total++;
print(total);
}
第一个显示total
,第二个显示每个循环。
现在我们如何用节点实现它?
loop node
:看到紫色码头?这是执行停靠站,它表示订单。这很酷,因为它告诉解释器确切地在每个循环上做什么。
CODE A
:CODE B
: CODE B
要求我们添加&#34;回调&#34;停靠loop node
:
此处CODE B
:
本质上,解释器(版本2!)的工作原理如下:
当调用loop node
时(我们必须在loop
节点的左侧添加紫色停靠点才能调用它),解释器将遵循其现有的控制链接(紫色链接)并且线性地工作,当时一个节点。
在我们的示例CODE A
中,loop node
首先附加到add
,首先必须解析所有依赖项,然后再转到控制链接附加的下一个节点(此处为print
})。这对应于BLOCK 1
(参见最后一张图片)。
节点add
必须提取变量total
,无需计算其参数所需的进一步计算,所有参数都已解决(另一个设置为1
)。因此,计算add
的输出并找到附加到它的节点:我们在右侧附加了一个节点total
(它是set
函数,另一个是{ {1}})。移至此节点并继续:没有任何节点连接到此节点=&gt;移动到通过控制链接链接的第二个节点:BLOCK 2。
节点有一个参数,它拉动变量get
并运行它的函数,因此,打印变量total
(由前一个节点增加1)。
要理解两件事:
1 - 有两种类型的链接:total
和data links
,前者用于第一个解释器,后者在此帖中引入。
2 - 此解释器将在
之间切换直接解释:
在通过控制链接(紫色链接)导航时,解释将是直接的(在control links
解释器就是这样:CODE A
- &gt; loop node
- &gt; add node
)
每当控制链接连接的节点将其输出连接到其他节点时。 (在 print node
中,CODE A
附加在add node
节点的右侧
间接解释:在解析由控制链接附加的节点上的依赖关系时,解释器必须向后工作才能找到节点的参数。 (在total
在这里,必须对此解释器进行一些修改:
我不确定在每次迭代后如何更新添加节点的输入总数
以下是我们如何解决此问题:CODE A
不应该有执行引脚,而ADD
节点应该有一个。这是运行SET
的正确图表:
让我们回顾一下:
此外,实际变量对象(我们将在这里调用CODE A
,它只是一个变量数组)将用于存储图中使用的所有变量。在context
中,仅使用了CODE A
:
title
节点只会从GET
total
context
节点将在数组SET
内分配给定的值
在我尝试在JS中实现它之前,我想查看另一个例子:
context