好了，是时候用Python子进行一个实践练习了，我们将在这里做什么 Alright, it's time for a practical exercise with the Python sub and what we're going to do here
是一种感染效应。 is an infection effect.
因此，在几何图形中，我们将立即开始，并使用测试几何图形进行此练习 So in a geometry we'll get started right away and we'll do this exercise using a test geometry
就像你在那里看，你有一个小队，对我来说，是一个猪头，等等。 like if you're looking there you have a squad, to me, a pig head, etc.
我要拿一件东西。 I'm going to take a thing.
是的，告诉我。 Yeah, tell me.
我会把它放大一点，实际上你知道吗，让我们放弃 And I'm going to scale it up a little bit and actually you know what, let's drop the
衬衫 shirt.
所以我要在这里引爆这件事，是的，我想在这一点上我想结合起来 So I'm going to blast this thing right here and yeah, I think at this point I want to combine
在同一个网格上的所有东西都像在一个体积中一样，所以我只使用来自 everything on those same mesh like in one volume to do so I will just use a VDB from
多边形 Polygon.
是的，而且有点悲观，所以我们只需要把焦点缩小一些，比如 Yep, and it's kind of gloomy so we'll just reduce the focus of size something like
嗯，一零四零三也许可以，我会把它转换回多边形 hmm, one zero four zero three maybe okay, I will convert that back into Polygon
我们将转换VDB、yep和Polygon。 and we'll convert VDB, yep, and Polygon.
这就是我测试几何所需要的全部内容，我们想在这里做的是一个练习 So that's all I need for my test geometry and what we want to do here is an exercise
我们正在处理点和东西。 where we are working with points and stuff.
所以我将使用一个散射，一个散射一堆点。 So I will just actually use a scatter, a scatter a bunch of points.
这一个，它的曲柄，哦，也许是那样的东西。 This one and it's crank up to oh, maybe something like that.
请注意，你的点越多，创建效果的文本可能就越长，好吧， Note that the more points you have, the longer it might text to create the effect, well,
以产生效果。 to generate the effect.
所以这样的事情看起来并不太糟糕。 So something like that doesn't seem too bad.
对于感染，我们需要使用求解器。 And for the infection we're going to need to use a solver.
所以，如果你以前从未使用过解算器，我在这里的主要任务基本上是工作 So if you've never worked with a solver before the main I'm de here is basically to work
有了这个节点和它的作用，我们将做一个非常简单的练习，但如果你深入其中 with this node and what it does, we will do a very simple exercise but if you dive inside
你可以看到你有前一帧，你也可以使用不同的输入，但是 you see that you have previous frame and well you can use different input as well, but
它将考虑每一帧，并在执行过程中覆盖一个属性。 what it will do it will consider every frame and override an attribute as it goes.
所以它实际上非常有用，尤其是如果你不想做一些花哨的动力学 So it's actually very useful especially if you don't want to do some fancy dynamics
诸如此类的事情。 and stuff like that.
所以我们将做一个简单的测试，现在我们正在从球体转移颜色 So we'll do a simple test where we are transferring a color from a sphere for now just
向你展示使用这些东西意味着什么。 to show you what it means to use this stuff.
所以我们这里有一个球体，我要移动它，也许在它的头上。 So we have a sphere here, I'm going to move it, maybe on the head.
在那里的某个地方，在这里。 Somewhere there, here.
假设我们想转移一些颜色。 Let's say we want to transfer some color.
所以我们只给它分配黑色，这里，和白色。 So we'll just assign it black color here, here, and a white color here.
现在让我们在这里做一个转移属性。 Let's do a transfer attribute for now, here.
我们只想这样做来初始化颜色，就像这样。 We just want to do that to initialize the color, like something like that.
在那里，我们要做的是根据颜色来划分事物。 And in there what we'll do is split things based on the color.
让我们假设cd.air等于一个点，现在我们基本上可以有两个 So let's say something at cd.air equals one points and now we can basically have two
分支，我想做的是重新转换这个颜色。 branch for those guys and what I want to do is retransfer this color.
假设我想把它转移回原始几何体上。 Let's say I want to transfer that back on the original geometry.
所以只有一件事，是的，我应该接受这个输入，现在我认为默认情况下 So just one thing, yeah, I should have taken this input and for now I think by default
这个值有点太多了，让我们进行一些混合，使其有点模糊。 the value is a bit too much, let's do some blend with to get something a bit blurry.
然后我选择了这样的东西。 And then I go with something like that.
您应该做的是，在每一帧，它都会覆盖cd属性，存储 And what you should do is that at every frame it would override the cd attribute, store
然后重新点燃并重新转移，等等。 it and then resplit it and retransfer it, etc.
因此，如果我们从这里观察，它基本上应该是自己生长的。 So it should basically grow by itself if we are looking from here.
是的，正如你所看到的，只有几个节点，我们已经有了感染效应 Yeah, and as you can see just with a few nodes we already have an infection effect, which
是一个非常简单的问题。 is a very simple one as it is.
我们可以通过增加这样的混合物来加快速度，让我们看看。 We could speed it up by increasing the blend with something like that, let's see.
是的，我们得到的东西稍微快一点。 Yeah, and we get something a little bit faster.
因此，当涉及到感染时，应该是大致相同的逻辑。 So it should be pretty much the same logic when it comes to the infection.
现在我们想使用一个类似的系统来进行属性转移和拼接，我们将 Now we want to use a system like that with attribute transfer and splining stuff, we'll
在一个Python潜艇上做所有事情。 do everything on the one Python sub.
但解算器的通用ID在这里。 But the general ID with the solver is here.
所以我要摆脱它。 So I'm going to get rid of that.
事实上，我们可以保留颜色，这会很方便。 Actually, we can keep the color, that's going to be handy.
因此，对于我们要做的事情，我们需要像处理一样初始化感染 So for what we're going to do, we need to initialize the infection just like we did with
球体。 the sphere.
但在这里，我们只需要一点，几点就可以做到这一点。 But here we will do that just with one point, a couple of points.
所以让我们按下回车键进入点模式，我们可以在手上选择一个点， So let's press enter to be in point mode and we'll select maybe a point on the hand,
也许一个在脚上，也许一个放在胸部。 maybe one on the feet and maybe one on the chest.
让我们创建一个小组，是的，也许小组实际上应该在这里。 Let's create a group and yeah, maybe the group should be here actually.
所以我们有一组要点，我们将称之为开始。 So we have a group of points, we're going to call it start something like that.
基本上，我们的感染将基于这些点。 And basically our infection will be based on those points.
所以，在进一步讨论之前，我想提一下，这个练习是理论性的。 So before going further, I want to mention that this exercise is kind of theoretical.
我认为实际上有更容易的方法来制造感染，比如使用 I think practically there would be way easier way to create an infection like using the
火山蔓延。 pyro spread.
这个家伙就在这里，我认为这是一个节点，在连帽衫ninyntine中介绍的。 This guy right here, which is a node introduced, I think, in hoody ninyntine.
但是，是的，我在这里的目标主要是向您展示如何使用Python和 But yeah, my goal here is mostly to show you how you can do things using Python and the
特别是Python。 Python sub specifically.
所以，是的，我的目标是给你思考的过程和不同的功能 So yeah, my goal here is to give you the thinking process and the different function that
用于创建这种效果。 are used to create this kind of effect.
因此，在没有更多悬臂刺拳的情况下，让我们进入解算器，创建一个Python So without any more jib jabber, let's go inside the solver and we'll create a Python
潜艇。 sub.
Python sub，我们将开始我们的代码。 Python sub and we'll get our code started.
好吧，那我们想做什么？ All right, so what do we want to do?
我们有一个引用当前节点的几何体类。 We have this geometry class that is referencing the current node.
我们首先要做的是获取我们开始小组的内容。 And what we want to do here first is get the content of our start group.
因此，我们将创建一个可行的调用grp，在其中，我们只需使用 So we'll create a viable call grp and in there we'll just call this group by using the
函数查找点组，组的名称为start。 function find point group and the name of the group is start.
是的，我会错过geo.find.group，因为我们想指定我们想要的几何体 Yeah, I'll miss geo.find.group because we want to specify that the geometry where we want
找到点是当前的几何体，也就是那个位将移动d的对象。 to find the point is the current geometry, which is who that bit will move d.
所以，是的，如果你还记得过去的教训，那应该很简单。 So yeah, if you remember the past lesson, that should be pretty straightforward.
从这里开始，我们要做的是循环通过该点，并使用函数 And what we want to do from here is loop through the point and use the function that is called
最近的点。 nearest points.
所以，如果你还没有看过这节课，一定要看看，因为我在解释 So if you haven't check out this lesson, definitely check it out because I'm explaining
这个功能是如何工作的，它背后的逻辑是什么。 how this function is working and what's the logic behind it.
所以，是的，你肯定需要看上一课才能理解本教程。 So yeah, definitely you will need to see the previous lesson to understand this tutorial.
所以，是的，我们将对这一点做一个循环。 So yeah, we'll do a loop through this point.
所以我们将在grp.pl中为pt做这件事，如果你记得很清楚，当涉及到寻找最近的 So we'll do for pt in grp.pl and if you remember well when it comes to finding the nearest
点，我们想定义一些东西，比如点的位置。 point, there are a few things we want to define like the position of the point.
所以我们只说，我们将有一个名为pause的变量，它存储这些的位置 So we'll just say we'll have a variable called pause that is storing the position of those
一个。 ones.
所以pt.pl的位置。 So pt.pl position.
是的，从这里开始，我们可以开始创造一个可行的、接近得分的 And yeah, from here we can start creating a viable that will be near pts that will
正在存储离起始组更近的所有点。 be storing all the points that are closer to the start group.
所以我们只说go.nearerspoint。 So we'll just say go.nearerspoint.
我们需要定义的第一件事是我们要看的点的位置。 The first thing we need to define is the position of the point that we want to look at.
然后我们需要看的点的数量与此最接近的点是什么 And then the amount of points that we need to look what are the closest points to this
当前点。 current point.
好吧，我们要说我们想要三到四个。 Well, we're going to say we want three or four of them.
我们在几何体中有一个组吗？我们想在那里包含效果，而不是 And do we have a group in the geometry there where we want to contain the effect not
准备好的 ready?
所以我们只说没有。 So we'll just say none.
最后，我们希望这种感染能达到什么程度？ And finally, what's the distance that we want this infection to reach?
喜欢0之类的东西。 Like something like 0.
我不知道，0.3，让我们看看。 I don't know, 0.3, let's see.
是的，到目前为止什么都没有发生，因为我们只是在寻找分数，但不是 And yeah, so far nothing is happening because well, we are just looking for points, but not
用它做任何事情。 doing anything with it.
也许我们想将其存储在一个组中，或者存储我们已经拥有的颜色属性 Maybe we want to store that in either a group or maybe store a color attribute that we already
定义 defined.
所以颜色属性被称为cd。 So the color attribute is called cd.
所以基本上，我们将遍历它找到的所有点，并存储一个绿色。 So basically we will loop through all the points that it found and store a green color.
所以让我们这样做吧。 So let's do that.
我们说，对于近pt中的近pt，我们想要实际分配颜色。 We say for near pt in near pts, we want to actually assign the color.
为此，我们只说接近pt.set属性值，这是我们已经知道的函数 So to do that, we'll just say near pt.set attribute value, which is function that we already
在过去的课程中看到的。 seen in the past lessons.
我们首先需要的是写入值的属性。 And the first thing we need is the attribute that we want to write the value in.
然后是值，所以我们想要的值可能是一个topal，我们会 And then the value, so the value we want probably something like a topal and we'll
说一些像绿色的东西。 say something like a green color.
它不起作用，主要是因为出于某种原因，我们实际上需要获得当前值。 And it's not working mostly because we actually need to get the current value for some reason.
然后将当前值指定给某个位置。 And then assign this current value somewhere.
就好像它必须以某种方式将当前值包含在这个值中。 It's like it has to contain the current value somehow within this value right here.
所以我们应该如何做到这一点，我想我们只需要创建一个名为cd或cd的变量。 So how we would do that, we would just create a variable called cd or cd, I guess.
我们将在pt附近说属性值cd。 We'll say near pt that attribute value cd.
所以这应该得到当前的，当前的颜色。 So this should get the current, the current color that we have.
现在这很好，但我们需要在这里以某种方式引用它，当前的颜色应该 Now that's great, but we need to reference it somehow in here the current color should
是黑人。 be black.
所以理论上我们应该可以说我们想要得到这个topal的第一个索引。 So in theory we should just be able to say we want to get the first index of this topal.
现在它确实有效了。 And now it works actually.
如果我们仔细观察我们的观点，我不确定你是否看到了 And if we look closely toward the points that we had, I'm not sure if you've seen
好吧，但在这里我们可以看到一些绿色的点。 well, but here we can actually see some green points.
也许我可以把一些副本应用到要点上，这样我们就可以更好地了解发生了什么。 Maybe I could apply some kind of copy to point just so we see a bit better what's going on.
复制到点，我们将创建大小恐惧。 Copy to point and we'll create the size fear.
只需激活打包姿势。 Just activate the packing stance.
是的，打包姿势。 Yep, packing stance.
我想我们会降低尺寸标准。 And we'll reduce the size criteria I guess.
我们还是有点太过分了。 Let's still a bit too much.
现在我们有一个冒泡的家伙。 Now we have a bubble guy.
我们看到，我们在定义起始组的地方有一些绿点。 And we see that we have some green points where we define the start group.
所以这里有一个，这里，等等。 So there is one here, here, etc.
如果我们试着阅读动画，那么，到目前为止什么都没有发生。 And if we try to read the animation, well, nothing's happening so far.
所以，是的，我想我们需要让这种东西感染。 So yeah, I guess we need to have this thing infecting.
问题是为什么它没有感染？ The question is why isn't it infecting?
原因是因为我们没有这样做，我们为这个起始组分配了一种颜色，即 The reason is because we are not doing, we assign a color to this start group, which is
这个GRP变量。 this GRP variable.
但我们并没有以任何方式凌驾于这一群体之上。 But we are not overriding this group by any way.
我们只是在指定一种颜色。 We are just assigning a color.
因此，在每一帧中，它都将保持不变。 So at every frame, it will just remain the same.
所以我们需要做的是说，我们在这里的这些新观点应该是其中的一部分 So what we need to do is actually say those new points that we have here should be part
新开始组的。 of the new start group.
所以我们最终需要在这个小组中增加一点。 So we need to add point in this group in the end.
所以我们可以试试GRP.ad，NRPT之类的东西。 So we could try something like GRP.ad, NRPT.
从理论上讲，我们应该开始看到一些颜色在传播。 And in theory, we should start to see some colors spreading.
对 Yes.
所以它是有效的，但你可能会意识到它实际上非常慢。 So it's working, but you may realize that it's actually super slow.
因此，确保该解算器不会变得太慢的一种方法是 So one way to make sure that this solver doesn't get too slow would be instead of looking
通过每一个点，当前点的邻居。 through every single point, the neighbors of the current points.
它将把新发现的点存储到一个临时组中，该组基本上 It would be to store the newly found points into a temporary group that will basically
看看目前正在发生的感染，而不是已经发生的感染 just look at the current infection happening and not the one that are already done in the
过去，如果这有道理的话。 past, if that makes sense.
因为在每一帧中，它都在评估感染开始时发生的事情， Because at every frame, it's evaluating even what's happening on the beginning of the infection,
我们对此不感兴趣。 which is no interest for us.
因此，优化该求解器的一种可能方法是将其存储在一个可行的、称为感染的环境中。 So one possible way to optimize this solver would be to store in a viable, will call infection.
已经感染的点的当前状态，说明这些点是否已经感染 The current state of the point that are already infected to say if those points are already
被感染了，我不希望他们成为首发组的一员。 infected, I don't want them to be part of the start group.
因此，让我们使用属性create创建一个自然静音。 So let's create a natural mute using attribute create.
我们将把这个属性称为感染。 And we'll just call this attribute infect.
默认值为零，因为默认情况下所有点都不应该被感染。 And the default value would be zero, because all the points by default shouldn't be infected.
所以我们看到我们有一个属性，叫做感染值为零。 So we see we have a attribute called infect value of zero.
我们在这里需要做的实际上是在这几点内评估这个属性 And what we need to do here is actually to evaluate this attribute within this points
在这里，要做到这一点，我们只需要做与我们在这里所做的相同的逻辑 right here, to do that we'll just do the same logic than what we did here with this
靠近pt.atredute的东西。 near pt.atredute thing.
所以让我们复制一下。 So let's just copy.
我们将把它存储在一个可行的呼叫感染中。 We'll store that in a viable call infect.
是的，接近预期值，等等。 Yep, near pt atred value, etc.
如果我们愿意，我们可以放一个评论，说评估当前属性。 If we want, we can put a comment that say evaluate current attributes.
所以，是的，我们在这里做的是评估。 So yeah, what we are doing here is evaluate.
事实上，现在我们需要在通过时检查这种感染是否等于1。 In fact, now we need to check if this infect is equal to one while we pass.
但如果它等于零，现在意味着当感染等于零时，这一点 But if it's equal to zero, now it means that when infect equals zero, that this point
还没有被感染，我们可能需要它成为这个群体的一部分。 hasn't been infected yet, and that we may need it to be part of this group start.
为此，我们将创建一个临时列表，并调用该列表。 So to do that, we'll create a temporary list that we'll call.
我不知道，新来的。 I don't know, new pt.
我们会说，如果感染等于零，那么在pt附近发生了新的pt。 And we'll say if infect equals zero, then new pt that happened near pt.
因此，如果该点被感染，您可以将此近PT添加到新PT列表中。 So if the point is infected, you add this near PT inside this new PT list.
现在发生的事情是，我们将清除这个群体。 And what's happening here is that we will just clear the group.
因此，我们希望删除该组中添加的所有点。 So we want to remove all the points that have been added inside this group.
所以我们只说grp.clear，这应该会完全清除该组。 So we'll just say grp.clear and that should clear completely the group.
让我们来看看。 So let's have a look.
你可以看到，如果我检查这个起始组，它是一个零元素， You can see that if I'm checking out this start group that was a zero element in it,
有零点，因为我们正在清除它。 there is zero point because we are clearing it.
所以我们要做的就是把包含在PT附近的所有点相加。 So what we'll do is just add all the points that are contained in near PT.
现在，如果这一点还没有被感染，那就是加入这个群体。 Now if this point hasn't been infected, is adding to the group.
但是，对于解算器的下一次迭代，我们需要指定该点已被感染。 But then for the next iteration of the solver, we need to specify that this point has been infected.
所以我们要做的只是说，PT，在3B。 So what we'll do is just say, here PT, that set at 3B.
我们将这个感染点的值设置为1。 And we'll set the value of this infected point to 1.
所以我们只说，事实上，1。 So we'll just say, in fact, 1.
所以它不再起作用了，因为我们需要实际使用这种感染物质。 So it's not working again because we need to actually use this infect stuff.
所以我们需要参考这个当前值并加一个加1。 So we need to reference this current value and add a plus 1.
现在理论上，这种情况应该会适当传播，因为我们正在克服这种感染特性 And now in theory, that should spread properly because we are overriding this infection attribute
这将决定我们是否应该这样做。 that will drive whether or not we should.
事实上，这是一个新的起点。 Actually, it happened the new points into this start group.
如果我们现在播放动画，这应该会奏效。 And if we play the animation now, this should work.
事实上，我已经意识到了国内。 And actually, I've realized the domestic.
我不想用近PT代替，但这个列表称为新PT，而不是近PT。 I don't want to replace by near PT, but this list called new PT, not near PT.
所以新PT，我觉得应该不错。 So new PT, and I think should be good.
正如你所看到的，事情现在应该运行得更快了。 And as you can see, things should run significantly faster now.
因此，它似乎对这类东西进行了更多的优化。 So it seems much more optimized for this kind of stuff.
我们这里和那里有一些黑点。 We have some black dots here and there.
它留下了一些黑点。 It's leaving some black points.
它可能没有找到足够的点来连接这些点。 It's possible that it's not finding enough points to connect those.
因此，也许解决方案的一部分是增加这一点。 So maybe part of the solution would be to increase that.
对 Yes.
所以，如果你看到一些黑点，也许你应该增加这个值。 So if you see some black dots, maybe you should just increase this value.
因此，如果我们从这里看，我们会发现这种感染实际上相当无聊。 So if we're looking from here, we see that this infection is actually pretty boring.
也许我们想要一个很好的尺度衰减项，就像球体会随着它们的增长而缩放一样。 Maybe we would want a nice fading terms of scale, like the sphere would scale as they grow.
也许我们会想要一些噪音分手。 And probably we would want some noise breakup.
所以它也不会以如此统一的方式生长。 So that it doesn't grow in such a uniform way as well.
让我们看看如何做到这一点。 So let's see how we can do that.
所以首先有一件事，我想先解决积分的边缘问题。 So one thing first, I want to tackle the edge of the points first.
感染点，当一个点变绿或获得感染值时的ID The infected points, the IDs that when one point is turning green or get an infect value
在这种情况下，我们可以在这些家伙的每帧加一。 of one in that case, we can add up plus one at every frame on those guys.
因此，我们首先需要初始化属性。 So the first thing we need is to initialize the attribute.
所以我们可以复制这个属性，创建并称之为边。 So we can just copy this attribute, create and we'll call that edge.
我们会说它不是一个浮点值，而是一个整数，因为它是基于帧的。 We'll say it is not a float but an integer, since it's based on the frame.
是的，在这一点上，我们准备在那里做一些事情。 And yeah, at this point we are ready to do some things in there.
在Python中，我们的性能达到了某种极限，因为我们 And here in Python, we are kind of reaching some limiting term of performance because we
都在看每一帧的所有点，这让事情变得非常困难 are looking through all the points at every frame, which makes things pretty difficult
烹饪以保持它，而Vex自然会对所有的 to cook for holding it, while Vex is naturally running any kind of operation on all the
点。 points.
因此，这是Vex的优势，而Python需要更安全、更具解释性、更具体 So that's a strength that Vex has while Python needs to be more safe, explanatory, specify
循环通过某一范围的点或所有点。 to loop through a certain range of point or all point.
好吧，你知道了，这就是我们在这里所做的，关于这个小组积分，等等。 Well, you get the idea that's what we've been doing in here with this group points, et cetera.
Vex中的经典方法是查看所有点。 The classic way in Vex would be to look through all points.
因此，如果我们尝试做完全相同的事情，我们会在geol.pons中为PT做一些类似的事情， So if we try to do the exact same thing, we would do something like for PT in geol.pons,
穿过这个几何体的所有点。 through all the points of this geometry.
我们需要得到边缘属性和感染属性。 And we would need to get the edge attribute and the infect attribute.
所以我们已经有了这条线。 So we already have this line right here.
我们不要忘记逗号，这里我们要改变的不是PT附近，而是PT。 Let's not forget the comma and here we're going to change not near PT but PT.
这就是我们的变量声明。 That's our variable declare right here.
当对边缘进行采样时，我们会做完全相同的事情。 And while sample the edge, then we would do the exact same thing.
我们需要做的是建立一个条件，即如果有效，等于1或更大 And what we would need to do is set up a condition that's a if-in-effect, equal one or greater
大于零。 than zero.
在这种情况下，我们想为edge设置一个属性值，该值加上plus的值 Well, in that case, we want to set an attribute value for edge that add the value of plus
一 one.
这正是我们在这里所做的。 So this is precisely what we did here.
所以我们可以复制并调整代码。 So we could just copy that and adjust the code.
这就是设置属性值的PT。 So that would be PT that set attribute value.
它在边缘，值将是page，也就是这个变量，当前值 It's on the edge and the value would be page, which is this variable, the current value
加一。 plus one.
好吧 All right.
当然，有一些事情它不喜欢，我做错了什么？ So there's something it doesn't like, of course, what did I do wrong?
第28行。 Line 28.
对 Yes.
好的，属性值边缘。 Okay, attribute value edge.
哦，是的，不，只是因为我们在1004帧。 Oh yeah, no, it's just because we are at frame 1004.
我们需要回到第一帧。 We need to go back at the frame one.
否则没有检测到。 Otherwise it wasn't detected.
我们创建的边缘属性。 The edge attribute that we created.
所以，是的，不，一切都很好。 So yeah, no, it's all good.
如果我们开始运行这个求解器，我们会发现事情会慢得多， And if we start running this solver, we see that things are much, much, much more slow,
主要是因为在每一帧中，它都试图观察所有的点，甚至是黑色的点 mostly because at every frame it's trying to look at all the points, even the black ones
并试图找出它们是否重塑了边缘值。 and try to find if they reshape edge value.
即便如此，如果我们仔细查看所有这些，绿色的，在这种情况下， And even then if we would look through all those ones, the green ones, in that case,
随着时间的推移，它仍然会变得更慢，因为旧的几何形状会被感染。 it would still get slower over time as the old geometry gets infected.
所以这也不太好。 So that's not great either.
但正如你所看到的，如果我们真的检查电子表格，我们有这个边缘属性 But as you can see, if we actually check out the spreadsheet, we have this edge attribute
现在，它随着时间的推移而增长，而一些没有被感染的人则保持着价值 now and it's growing over time, while some that are not infected, stay with the value
0的，就像那些家伙一样。 of 0, like those guys.
所以，如果我们真的被感染了，那么它就会停止生长。 So if we actually get infected and then it's done growing.
所以，是的，这是一般的想法。 So yeah, that's the general idea.
我们将使用这个边来驱动球体的比例。 And we would use this edge to drive the scale of the sphere.
事实上，我可以在这里给你看。 I could show you that here, actually.
所以我们可以做一点准备。 So we could just do a point of up for that.
在那里，我们只会说，我想进口边缘。 And in there, we'll just say, I want to import edge.
因此，让我们导入边缘属性。 So let's import the edge attribute.
我们想重新映射它，馈送范围并将该属性导出为p缩放。 We want to remap it, feed range and export that attribute as a p-scale.
基本上，我们会在这里宣传这些人，以定义这个阶段的设置。 And basically we'll promote those guys right here to define the settings of this stage.
是的。 Yep.
让我们看看，如果我们增加这个最大值，现在因为我们正在重新映射 And let's see, if we increase this maximum value, and now because we are remapping the
边缘属性，我们得到了这个很好的渐变比例。 edge attribute, we are getting this nice fade in the scale.
实际上，我们越是增加这个值，我们的衰减就越大 And actually the more we would increase this value, the more we will get the fade fall-off
有价值的东西。 value kind of thing.
所以，是的，你增加的边的最大输入值越多，就越多 So yeah, the more you are increasing this maximum input value of the edge, the more
你会掉下来的。 fall-off you will get.
正如你所看到的，事情变得更加顺利。 So as you can see, things get much smoother.
如果它太多了，我会说它没有那么有趣，价值也很小。 If it's too much, I would say it's not as interesting and having a small value.
可以 Okay.
那太好了。 Well, that's great.
但如果我们只关注这一领域，我们可以优化代码以确保 But if we are focusing just on this area, we could optimize the code to make sure that
事情进展得更快。 things run lot faster.
所以我们有多种方法可以做到这一点。 So there are multiple ways we could do that.
我们可以使用最近的点来关注电流周围的边缘 We could just use the nearest point to focus on the edge around what's in the current
启动组，或者我们也可以使用Vex。 start group or we could also use Vex.
那么，这在Vex是如何运作的呢？ So how would that work in Vex?
比方说，我们想更换这个部件，使其更加优化。 Let's say we want to replace this part to make it more optimized.
我们可以使用网络重新启动的角度，在那里我们可以开始在Vex中编写脚本。 We could use a net reboot angle and in there we can start scripting in Vex.
在Vex中，你基本上会说，所以我只想通过输入以下内容来禁用这些功能 And in Vex you would basically say, so I'm just going to disable those by entering this
三个引号。 triple quotation mark.
所以应该忽略。 So there should be ignored.
实际上，我应该加一个引号。 Actually, I should put single quotation mark.
是的。 Yep.
在Vex中，如果在括号之间，我们会做完全相同的事情 And in Vex, what we would do to do the exact same thing would be if in between parenthesis
条件，如果等于1，我想加，我想增加一个值 the condition, which would be if at, in fact, equal one, I want to add, I want to add a value
的加一在边属性上。 of plus one on the edge attribute.
哎呀。 Oops.
是 啊 Yeah.
诸如此类的事情。 So something like that.
实际上，这将比Python代码运行得更快。 And actually this would run much much more faster than the Python code.
因此，正是因为这个原因，使用Vex来操纵点通常更容易 So you have for this exact reason it's usually easier to use Vex to manipulate points
和颗粒。 and particles.
正如您所看到的，边属性正确地生成了与Python中完全相同的结果。 And as you can see, the edge attributes properly generated exactly the same result than in Python.
但是，在这种情况下，我还想向您展示如何在Python中优化它。 But well, in that case, I want to also show you how we can optimize that in Python.
因此，我想尝试将这个边缘整合到 So instead of this green text that we had here, I want to try to integrate this edge in
这个循环可以优化事情。 this loop to kind of optimize things.
所以我们可以很快尝试一下。 So we could try that real quick.
我们需要得到边值，让我们把这个变量更新到PT附近，在这里说， We need to get the edge value and let's update this variable to near PT and say in here,
如果事实上，等于1，在这种情况下，我们想像以前一样加一个值加一 if in fact, equal one, in that case, we want to add a value of plus one just like we did
到这个边缘。 here to this edge.
给，PT，是的，H加一，我应该很好。 Here, PT and yeah, H plus one, I should be good.
所以让我们再试一次。 So let's try again.
代码运行得很快，但正如您所看到的，如果我们仔细查看 The code is running pretty fast, but as you can see, if we are looking through this
电子表格，我们的优势在某个时候基本上停止了增长。 spreadsheet, we have an edge that basically stopped growing at some point.
那么，为什么这种边缘停止生长呢？ So why does this edge stop growing?
这是因为在这里，我们看到的是更接近内部的点 It's because in here, we are looking through the point that are closer to the ones inside
这个启动组。 this start group.
但由于我们实际上正在清除这个组，只添加最新的点，好吧，在 But since we are actually clearing this group and adding only the newest point, well, in
在这种情况下，这意味着它们只是暂时影响边缘，而且只是暂时的 that case, it means that they are only temporary affecting the edge and only temporary
影响组启动。 affecting the group start.
因此，这是一种在Python中工作的优化方式。 So in that way, it's an optimized way to work in Python.
实际上，这些值5，6可能足以达到我们想要的效果。 And actually those value of 5, 6 might just be enough to do the effect we want here.
所以，如果我们看看这里的情况，我们可以增加到5，也许是6，我们仍然可以得到 So if we look at what we have here, we can increase to 5, maybe 6, and we still get fairly
与之前的结果相同。 the same result than what we had before.
所以，正如你所看到的，我们仍然有一些不错的褪色。 So as you can see, we still get some nice fade.
但正如您可能注意到的，使用Python获得一些优化的结果有点棘手 But as you probably notice, it's a bit more tricky to get some optimized result using Python
对于这种效果，如果你不太担心的话，你总是可以用暴力手段 for this kind of effect, and you can always brute force things if you're not too concerned
大约是模拟的时候了，但好吧。 about the time of let's say simulations, but well.
现在，我们想为这个感染系统增加一个功能，那就是 Now there's one more feature we want to add to this infecting system, which would be some
传播中的噪声变化。 noise variation in the spread.
因此，需要注意的一件事是，这些东西现在在 So one thing to be aware of is how fast those things are traveling right now in the
最大距离，我们的值为0.3。 max distance, we have a value of 0.3.
因此，我们需要为最大距离寻找一个切换点，以便 So we would need to look for a switch spot for the max distance that would allow us to
开始模拟，但同时发出距离的变化 start the simulation, but at the same time giving off variation in terms of distance to
得到一些不错的噪音分手。 get some nice noise breakup.
所以，如果我们降低数值，比如说0.1，仍然运行得相当快，让我们试着降低 So if we lower things, let's say to 0.1, still traveling fairly fast, let's try to decrease
实际上，我要把它减少到4，让我们开始减少到0.0。 actually, I'm going to reduce that to 4, and let's start decrease to 0.0 for in here.
所以它还是有点多，让我们减少到2。 So it's still a bit much, let's reduce to 2.
正如你所看到的，这个值是2.0，我们甚至还没有开始感染。 As you can see, this value is 2.0, and we don't even get the infection started.
所以介于两者之间，可能是0.0.3。 So there's something in between, maybe 0.0.3.
我们上涨了0.3。有效，但还是有点快，让我们试试2.5。 We're up on 0.3. works, but still a bit fast, let's try 2.5.
所以28似乎是可行的，正如你所看到的，我们已经得到了一些更有趣的东西 So 28 seems like it would work, and as you can see, we already get some more interesting
效果是，有些点不会被感染，因为距离太低。 effect, some points doesn't get to be infected because the distance is too low.
因此，理想情况下，这就是我们想要得到的，但更广泛的分手是由 So that's what we want to get, ideally, but with much more broad breakups, provoked by the
噪声，并且看起来对于这个特定尺度的0.028的值将起作用。 noise, and it looks like this value of 0.028 for this specific scale would work.
在您的情况下，可能会有一些非常不同的东西，这取决于您的模型的规模。 In your case, there might be something very different, depending on the scale of your model.
所以，是的，让我们看看，但如果你开始看到一些东西破裂了，看起来更像 So yeah, let's see, but if you start to see something breaking up and looking much more
嘈杂，这是一个好的开始。 noisy, it's a good start.
如果你开始降低这个最大值，你也可以得到一些非常有趣的效果， If you start lowering this max point, you can also get some pretty interesting effect,
事实上 actually.
是的，它看起来几乎像一棵藤蔓，你知道吗？ Yeah, it almost looks like a vine, you know?
所以这很酷。 So it's pretty cool.
这有点酷。 It's kind of cool.
在我的情况下，我将回到这个值，最大值为4。 In my case, I'm going to go back to this value and a maximum of 4.
像这样的事情作为一个起点，我们将让这种噪音继续下去。 Something like that as a starting point, and we're going to get this noise going.
对于这种噪声，我们需要对其进行初始化。 For this noise, we need to initialize it.
我只是想在这个散射之后创建它。 I just going to create it after this scatter.
所以我们只需要用一个点来表示，因为我认为这比尝试更容易 So we'll just use a point of up for that, because it's, I think, easier than trying to do
一些vx。 some vx.
所以让我们把这个家伙放在这里。 So let's put this guy in here.
我使用的是湍流噪音，完全可以随意使用任何你喜欢的噪音 I'm using a turbulence noise, feel free to use any kind of noise you like, entirely
作为噪波或单纯形，或任何您想要的，统一噪波。 as a noise or simplex, or whatever you want, unify noise.
我会把它输出成一种自然的冷噪音，我们必须重新映射一点 And I'll export that into a natural-buted, cold noise, and we'll have to remap a bit
这些值也适用于您的进给范围，以控制最大距离。 those value as well for your feed range to get the control over the maximum distance.
所以，是的，我们会提拔那些家伙。 So yeah, we'll promote those guys.
同时，让我们用方便的颜色来可视化这个噪声。 And also, let's visualize this noise in the color that would be handy.
我的意思是，他们只是想推广一些参数。 I mean, they are just going to promote some parameters.
所以这种情况下的噪声值可能有点宽。 So the noise value in this case might be a bit broad.
让我们试着减少它。 Let's try reducing it.
我们可能也需要一点对比度。 We're going to probably have to feed a little bit with the contrast as well.
让我们试试这样的东西。 Let's try something like that.
所以这里的想法是，既然我们有一个黑白值，这意味着 So the idea here in this case is that since we have a black and white value, it means
那一个是完全黑色的，点将停止传播，因为最大距离是 that one is totally black, the points would stop propagating because the max distance is
零，当它是白色时，它是最大值。 zero, and when it's white, it's the maximum value.
所以，是的，在这种情况下，当它是黑色的时候，我们可能会被挡在这里。 So yeah, in that case, when it's black, we might be a bit blocked in here.
所以，这可能值得尝试与粗糙分手，只是为了 So that might be worth trying to have some breakup with roughness, just so that there
仍然有一些传播的机会。 is still some chance for propagation.
所以让我们试试这样的东西。 So let's try something like that.
如果我们愿意，你甚至可以伸展它。 You can even stretch it if we want.
是的，在这种情况下，感染的形状应该是这样的。 Yeah, in this case, the shape of the infection should look like something like that.
是的，让我们看看。 Yeah, let's see with that.
所以在最小和最大输出值中，我们应该尝试找到这个值 So in the minimum and max output value, we should try to find this value that we were
玩。 playing with.
这大概是2.8或7。 So that was something like 2.8 or 7.
至少，我们会做一些不像65岁那样的事情。 And in the minimum, we would do something not as much like 65, maybe.
所以现在颜色很难看到，但还是可以的。 So now the color is very hard to see, but that's still okay.
让我们看看。 Let's see.
现在我们需要如何在代码中实现这一点，编写求解器。 Now how we need to implement that in the code, writing the solver.
所以在这里，我们需要把这个噪音称为这个级别。 So in here, we need to actually call this noise at this level.
为了做到这一点，我们只需要重用属性值函数，dt-dot属性值。 So to do that, we'll just reuse the attribute value function, dt dot attribute value.
美好的 Nice.
所以现在我们把这种噪音称为可行的噪音，我们只需要替换它 So now that we call this noise into this noise viable, we just need to replace this
该噪声的最大距离。 maximum distance by this noise.
希望这能奏效。 And hopefully there should work.
是的。 Yep.
所以它看起来已经大不相同了。 So it's looking already fairly different.
我想说，也许我们可以试着用最小和最大的输出打更多的比赛，以获得一些东西 I would say probably we could try to play more with the min and max output to get something
就我们的噪音而言更明显一些。 a bit more visible in term of our noise.
我想，这将是一个有点难以想象的。 This one's going to be a bit tricky to visualize, I guess.
所以，如果我们想正确地想象这一点，我想说，也许我们需要再做一次 So if we want to visualize that properly, I would say maybe we would need to do another
馈送分支，并实际调用这个最小值作为源最小值和最大值 feed branch right here and actually call this minimum value as a source min and this maximum
值作为源最大值。 value as a source max.
现在我们正在妥善恢复一切。 And now we are restoring everything properly.
所以我们可以在这里安全地调整我们的最大和最小输出，并可视化这种噪音 So we can safely adjust our max and min output here and visualize the kind of noise stuff
如果我们改变这个最小和最大输出，就会发生这种情况。 happening if we change this min and max output.
所以，是的，这应该很有帮助。 So yeah, that should be helpful.
让我们试试这样的东西。 Let's try something maybe like that.
事实上也不算太糟。 And it's not too bad actually.
所以，如果我们仔细观察这个家伙，它的价值实际上很小。 So if we are looking through this guy, the value is just very small actually.
这增加了这一点。 That's increased that.
所以我觉得这个最小值还是太多了。 So I kind of feel like this minimum value is still too much.
让我们减少它。 Let's reduce it.
是的，现在可能有点太低了。 And yeah, probably it's a bit too low now.
只有这种饲料开始感染。 Only this feed that's started to infect.
这真的取决于你把起点设定在哪里，因为如果是在 It really depends where you set your starting point because if it's on the areas that's
实际上，噪音很黑，它可能不会增长得足够快。 actually black on the noise, it's not going to probably grow fast enough.
你知道，也许就在这里，我们需要从这一点开始挑选一些要点 You know, maybe right here, we would need to pick some points that are starting on this
白色表面。 white surface.
所以这不是真正的程序。 So that's not really procedural.
那将是一些。 That would be some.
所以问题是，理想情况下，我们希望我们的起点设置在白色 So the problem is that so ideally we would want our starting point to be set on a white
地区 area.
所以我们可以通过使用一个表达式在程序上做到这一点。 So we could do that procedurally actually just by using an expression.
因此，在一个组表达式中，我们将创建这个起始组，它将基于点 So in a group expression we'll create this start group and that would be based on points
我们会说是否有噪声，或者说cd.r大于0.9。 and we'll say if noise or let's say cd.r greater than 0.9 than you select.
是的。 Yep.
所以这太多了。 So that's way too many points.
当然，我不知道，加上另一个条件，我们会说相交。 Of course, I don't know, add another condition and we'll say intersect.
我们要说的是加上小于100的ptnum。 And what we'll say is add ptnum smaller than 100.
现在我们有几点。 So now we have a few points here and there.
也许我们可以将事情随机化，以确保它更有趣。 Probably we could randomize things to make sure that it's a bit more interesting.
让我们将点顺序随机化。 Let's randomize the point order random.
正如你所看到的，我们选择了34个点。 As you can see, we have 34 points selected.
我们总是可以减少这种情况。 We can always reduce that.
如果我们需要更少，现在我们有20个。 If we need less, now we have 20.
现在我们有六个。 Now we have six.
所以，是的，为什么不呢。 So yeah, why not.
让我们试试看。 Let's try that.
所以实际上我忘了重新激活我的颜色。 So actually I forgot to reactivate my color right there.
这个颜色，我们把它放在后面，否则我们不能基于颜色创建这个组。 This color, let's put it after otherwise we can't create this group based on color.
如果全是黑色的。 If it's all black.
可以 Okay.
我们也需要这种感染属性。 And also we need this infect attribute.
所以让我们把它加回来。 So let's add it back.
是的，正如你现在所看到的，我们应该准备好再次食用感染。 And yeah, as you can see now we should be ready to start eating infection again.
是的，事实上，它看起来很有趣。 And yeah, it's looking pretty interesting, actually.
所以我们可以尝试更少的分数。 So we could try less points.
这意味着我们会留下来拥有那么多。 That means we'll stay to have that many.
可能在我要重命名的这个点动词里面，实际上，我们只是重命名 And probably inside this point verb that I'm going to rename actually, we'll just rename
那个要点动词。 that point verb.
所以它看起来不错。 So it's looking nice.
我们可以放一个绿色，只是为了确保我们知道在哪里看。 We can put a green color just to make sure that we know where to look at.
我会减少的。 I'm going to reduce that.
如果你慢如你所见，它就会被卡住。 And if you slow as you can see, it's stuck by getting.
所以，是的，让我们增加一点。 So yeah, let's increase a bit more.
因此，需要大量的迭代才能真正获得有趣的东西。 So there's a lot of iteration to actually get something interesting.
是的，那个，那个，结果其实很酷。 And yeah, that's, that's, result is actually pretty cool.
我喜欢那里发生的事情。 And I like what's happening there.
所以，让我们想象一下这些恐惧。 So let's visualize with those fears.
我们可以把它放在原始几何体的顶部。 We could tub that on top of the original geometry.
它在哪里？ Where is it?
我会是这个家伙。 I would be this dude.
非常感谢。 Thank you.
所以，是的，这是一件非常有趣的事情。 So yeah, that's a pretty fun stuff.
尝试一个非常有趣的效果。 A pretty fun effect to try.
因此，如果我们愿意，我们也可以影响基于边缘的颜色。 So if we want, we could also affect the color based on the edge.
如果我们想更疯狂一点。 If we want to be a bit more crazy.
因此，如果我们愿意，我们可以影响颜色，并根据边缘进行良好的渐变。 So if we want, we could affect the color and get a nice fade to based on the edge.
所以从属性运行。 So run from attribute.
让我们称之为edge。 And let's call edge.
也许让我们试着用一些黄色和绿色的。 And probably let's try to play with some yellow and green.
看看它看起来怎么样？ See how it looks?
也许我们需要增加。 Probably we need to increase that.
也许让我们做一些类似的事情。 And let's probably do something like that.
我将在聚会电话中试用VDD。 I'm going to try VDD from a party call.
所以你给了一个好的视角另一个。 So you give a good view another.
我希望你已经了解了这些内容。 I hope you've gotten to this content.
这有点有趣。 That's kind of interesting.
我们努力使事情顺利进行。 We try to get the smooth.
并将其转换回多边形。 And convert that back to polygon.
所以，是的，只是提出我的想法，你可以如何使用这种感染。 So, yeah, just render my idea how you can use this infection.
让我们看看。 Let's see.
所以，对于网格，它的生成速度要慢得多，所以我将进行播放预览。 So, with a mesh, it's much slower to generate, so I'll do a playblast.
这就是我得到的。 And that's what I got.
所以，这很整洁。 So, that's pretty neat.
这是一个有趣的效果。 That's an interesting effect.
我希望你喜欢这个教程。 I hope you liked this tutorial.
当然，正如我一开始所说，有一些方法可以产生今天这样的效果。 Of course, there would be ways your way, as I said, at the beginning, to generate an effect like that nowadays.
但希望它能为您提供一些关于如何使用Python来操作它的好主意。 But hopefully, it gives you some good ideas on how you can use Python to manipulate that.
这就是我的目标。 And that was my goal here.