数据修改和处理的顺序由“输出”子操作符定义。“输出”子操作符使数据得到修改。“输出”子操作符从数据流中位于其上方的子操作符拉出粒子数据,并将数据设置为粒子属性。
具有相同“执行顺序”值的“输出”子操作符处理相同的输入数据。当“执行顺序”值相同时,“优先级顺序”值定义“输出”子操作符从上游拉出数据的顺序。仅当拉出所有数据后,数据才会应用于粒子属性。
如果子操作符具有不同的“执行顺序”值,则它们可能处理不同的输入数据,即使它们从相同的“输入”子操作符中拉出数据也是如此。这是因为执行顺序较低的“输出”子操作符可能更改某些粒子属性中的数据。当执行顺序较高的“输出”子操作符拉出数据时,这些数据已经被修改。
请考虑以下示例:当粒子进入某个事件时,您需要计算所有新粒子的初始值。然后需要修改每一帧中的粒子属性(无论事件中的粒子是新粒子还是旧粒子),在此修改过程中,需要设置所有粒子的初始值。
在这种情况下,您有两个数据流:第一个流用于计算初始值;第二个流用于修改粒子属性。第一个流的“输出”子操作符的“执行顺序”应为 1,且极有可能其过滤器输入将被设置为“输入标准”“事件中的新粒子”。第二个流的“输出”子操作符的“执行顺序”应为 2。
考虑另一种情况:您希望分析所有粒子的速度数据,然后,根据某些条件,您希望定义粒子的两个子集,每个子集的速度将以不同的方式进行修改。在这种情况下,您需要使用两个具有相同执行顺序的“输出”子操作符。这样,您就可以保证每个输出的初始输入速度值是相同的。
另外,由于“数量更改”子操作符更改了粒子的数量,所以该子操作符不能与任何其他子操作符共享“执行顺序”值。程序中的保护措施可防止您进行共享。
此外,“执行和优先级顺序”组也具有“前/正常/后”单选按钮。该选项在较高的级别上定义处理顺序。如果将顺序设置为“前”,则在执行当前事件中的任意操作符前,此输出已完成。如果将顺序设置为“正常”,则“输出”子操作符按常规顺序执行,即在同一事件中,在其他操作符之间进行。如果将顺序设置为“后”,则当该粒子系统中所有的操作符和测试完成各自在积分步长中的工作时,才处理输出。
有关说明“前/正常/后”用法的示例,请打开附带的文件 CollisionAsBody.max。
此示例使用“数据”操作符来产生“开销低且快速”的全体碰撞。正如您所知,涉及到碰撞和导向器,3ds Max 中的粒子系统将粒子作为点实体进行处理。因此,如果粒子图形的大小可见,图形就会穿透导向器表面,这将会破坏总体视觉效果。该示例显示了如何关联粒子数据,从而根据互相穿透的数量来偏移粒子位置。
首先,我们创建一个自定义数据通道来存储实数值,因为需要位置偏移来避免穿透。对于所有新粒子,我们将此值的初始值设置为零(请参见数据块 01)。
当所有其他操作符和测试完成各自的工作后,我们会计算渗透的数量,并在“后”阶段中偏移粒子位置。这样,粒子位置进行了调整,以防止穿透,且粒子将准备好进行渲染。右侧的“输出”操作符在“后”阶段中执行各自的工作。
然后,在“前”阶段,我们需要将粒子移回到它们无偏移的位置,让碰撞检测继续进行,就如同未发生偏移。
历史依赖型
粒子系统本质上为历史依赖型。也就是说,要能够确定粒子系统在诸如第 100 帧上的状态,该软件需要计算自第一个粒子产生后,所有先前帧的状态。这是因为粒子属性(例如,粒子的位置)所发生的更改随着其他参数(例如,速度)持续更改而不断积累。
但是,对于某些特定的设置,一些特定的属性不是历史依赖型,且可以从粒子的当前状态进行计算。例如,当粒子“注视”摄像机等物体时,粒子的方向,或跟随粒子的速度。此时,粒子的方向取决于粒子的位置(如朝向摄影机时),或粒子的速度。在这种情况下,要计算粒子当前的方向,您无需了解粒子的全部历史;只需了解它们当前的速度或位置即可。
在这种情况下,用于计算粒子方向的操作符不是历史依赖型。当系统为了到达当前帧而穿过之前所有帧时,操作符不需要执行任何操作。该操作符只需在最终帧上进行操作,以分析最终帧里粒子的位置/速度,并计算相应的粒子方向。
如果您确定“输出”子操作符的结果不取决于粒子的历史,您可以禁用“历史依赖型”选项。这可以加快整体计算,因为它会使“数据”操作符仅在最后一帧上操作。
,