TiXL 节点详解:BlendVector3——多向量循环插值(Lerp)混合器
【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3
本文以 TiXL 开源实时动态图形软件(tooll3)内置节点BlendVector3(Lib.numbers.vec3命名空间)为核心,完整解析其输入输出、底层插值算法与多输入收集机制,并结合仓库源码 BlendVector3.cs 说明它如何把单个标量F拆解为"循环索引 + 混合相位",实现对任意数量三维向量(位置、方向、缩放等)的无缝循环过渡。读完本文,你将掌握该节点的全部参数语义、与LerpVec3的选型差异,以及用曲线或振荡器驱动F制作循环位移动画的完整方法。
节点概览:BlendVector3 究竟做什么
根据官方文档 BlendVector3.md 的定义:
Blends (lerps) two vectors.—— 在两个向量之间做线性混合(lerp)。
与常见的两点 lerp 不同,BlendVector3 的实现实际上支持任意多个输入向量:它在输入列表上以F为游标循环寻址,先锁定两个相邻向量,再在二者之间按小数相位做线性插值。F每增加 1,游标就前移一个向量;当F超出输入数量时自动回绕(wrap around),形成可无限循环的过渡序列。
该节点属于 Lib.numbers.vec3 数字运算子命名空间,输出类型为System.Numerics.Vector3,可直接驱动 TiXL 中任何接受 Vector3 的输入,例如对象位置Translation、网格Scale、旋转轴向量等。
输入与输出参数速查
原文档给出了节点完整的参数契约,下表在此基础上补充了类型、默认值与语义说明:
| 名称 | 相关性 / 类型 | 说明 |
|---|---|---|
| Vectors | Vector3 必需(多输入槽) | 参与混合的向量序列,可连接任意数量的 Vector3 信号源;多输入由MultiInputSlot<Vector3>实现,详见下文 |
| F | Single(浮点标量) | 混合游标:整数部分决定选中序列中的哪一对相邻向量,小数部分决定两者间的混合比例;默认值0.0 |
| Result(输出) | System.Numerics.Vector3 | 混合结果,类型与输入一致 |
节点会话默认值记录在 BlendVector3.t3 中:Vectors默认{X:0, Y:0, Z:0},F默认0.0。未连接任何输入时,输出为Vector3.Zero。
核心算法剖析:F 如何被分解为"索引 + 相位"
BlendVector3 的求值逻辑非常精炼,完整实现位于 BlendVector3.cs:
Result.Value = Vector3.Zero; var collectedTypedInputs = Vectors.GetCollectedTypedInputs(); var count = collectedTypedInputs.Count; if (count == 0) return; var f = F.GetValue(context); var index1 = (int)MathUtils.Fmod((int)f, count); var index2 = (int)MathUtils.Fmod((int)(f + 1), count); var mix = MathUtils.Fmod(f, 1); Result.Value = MathUtils.Lerp(collectedTypedInputs[index1].GetValue(context), collectedTypedInputs[index2].GetValue(context), mix);算法分三步完成,每一步都对应一个明确语义:
- 收集输入:
Vectors.GetCollectedTypedInputs()取出当前所有连接的 Vector3 输入,数量记为count;若为 0 则输出零向量。 - 索引分解:把
F的整数截断值对count做取模,得到起点索引index1;(int)(f + 1)取模得到终点索引index2。由于使用了 floor 取模,两个索引始终落在合法的[0, count-1]区间内。 - 相位混合:
mix = Fmod(f, 1)提取出F的小数部分,作为两个向量之间的线性插值系数。
其中MathUtils.Lerp与MathUtils.Fmod定义在 MathUtils.cs:
public static float Lerp(float a, float b, float t) { return a + (b - a) * t; } public static float Fmod(float v, float mod) { return v - mod * (float)Math.Floor(v / mod); }三维版本 Lerp(Vector3, Vector3, float) 对 X、Y、Z 三个分量分别套用上述公式,因此混合是逐分量独立进行的。而Fmod采用Math.Floor的 floor 取模语义(区别于 C#%的截断取模),这正是F取负值时仍能正确回绕、mix始终落在[0, 1)的关键。
F 值的行为速览
以 4 个输入向量 V0、V1、V2、V3(count = 4)为例:
| F | index1 | index2 | mix | 输出 |
|---|---|---|---|---|
| 0.0 | 0 | 1 | 0.0 | V0(完全落在 V0) |
| 0.5 | 0 | 1 | 0.5 | V0 与 V1 各半 |
| 1.5 | 1 | 2 | 0.5 | V1 与 V2 各半 |
| 3.8 | 3 | 0 | 0.8 | V3 与 V0 之间 80% 偏向 V0 |
| 4.0 | 0 | 1 | 0.0 | 回到 V0,实现无缝循环 |
| -0.5 | 0 | 1 | 0.5 | V0 与 V1 各半(负向等价回绕) |
由此可见,F不需要被限制在[0, 1]或[0, count]内:你可以让F无限增长(或递减),BlendVector3 会自动把游标循环回列表起点,非常适合做"扫描灯带""轮播位置""循环换色"这类周期性动画。
边界情况
- 零输入:
count == 0时立即返回Vector3.Zero,不会发生越界。 - 单输入:
count == 1时index1 == index2 == 0,任意F下输出恒等于该向量,节点等价于直通。 - 负 F:得益于
Fmod的 floor 语义,负游标同样得到合法的非负索引与[0,1)相位,可反向"倒放"整个序列。
MultiInputSlot:为什么 Vectors 能连接多个向量
Vectors在源码中声明为MultiInputSlot<Vector3>(见 BlendVector3.cs),这是 TiXL 运算符框架中的多输入槽。其收集逻辑定义在 MultiInputSlot.cs:GetCollectedTypedInputs()遍历InputConnections,若某条连接本身是多输入槽输出,还会递归展开其中的全部子输入,最终把所有终端信号源平铺为一个有序列表返回。
这意味着你可以:
- 直接把多个
Vector3节点的输出依次连到Vectors上; - 也可以把一个"向量列表"类的输出整体接入,自动展开成多个独立向量;
- 输入顺序即列表顺序,直接决定
F游标遍历的先后次序,调整连线顺序即可改变循环方向。
与 LerpVec3 的选型区别
原文档明确提示 "Also see LerpVec3"。二者都做向量插值,但适用场景差异明显。LerpVec3的实现见 LerpVec3.cs,对比要点如下:
| 维度 | BlendVector3 | LerpVec3 |
|---|---|---|
| 输入向量数 | 任意多个(多输入槽) | 恰好两个(A、B) |
| 混合游标 | 单个F,循环寻址 + 小数混合 | 单个F,仅作为 A→B 的插值系数 |
| 越界处理 | 自动回绕循环 | 可选Clamp开关,开启后F被限制在[0,1],默认关闭(不钳制) |
| 底层插值 | MathUtils.Lerp(逐分量,a + (b-a)*t) | Vector3.Lerp |
| 典型用途 | 多个状态间的周期性轮播、序列过渡 | 两个明确状态间的单次过渡(如开关门、淡入淡出位移) |
选型建议:如果你需要在两个固定向量之间精确过渡且希望主动钳制系数,用LerpVec3;如果你要在一串位置/方向/缩放之间做无缝循环动画,或不想操心F的取值范围,用BlendVector3更合适。
实战:驱动 F 制作四位置循环动画
以"让一个物体依次经过 4 个位置并循环往复"为例:
- 在图中放置 4 个
Vector3节点,分别填入 4 个目标位置(例如(0,0,0)、(2,0,0)、(2,0,2)、(0,0,2)),依次连接到BlendVector3的Vectors多输入。 - 将
BlendVector3.Result输出连接到目标物体的Translation输入。 - 为
F提供随时间递增的驱动信号:接入Oscillate(三角波/锯齿波)或随时间累积的曲线值;当F从 0 增长到 4 时,物体恰好遍历 4 个位置并回到起点,之后继续循环。 - 若希望匀速等分时间,可让驱动信号在
[0, 4)内线性递增(例如将归一化时间乘以 4);若希望"快慢节奏"则由曲线形状决定,因为mix仅取F的小数部分,曲线斜率即过渡速度。
该节点在仓库示例项目中亦有实际引用,例如 IkChainExample.t3(IK 链示例)与 DrawMeshChunksAtPointsExample.t3(按点批量绘制网格示例),可作为阅读参考。
相关节点与延伸阅读
BlendVector3 属于 Lib.numbers.vec3 向量运算家族,同命名空间下常用于组合搭配的节点包括:
- LerpVec3— 双输入线性插值(可钳制)
- AddVec3/SubVec3— 向量加减
- ScaleVector3— 向量缩放
- RotateVector3— 绕轴旋转
- Magnitude/NormalizeVector3— 向量长度与归一化
- PickVector3— 从多路输入中按索引单选(与 BlendVector3 的"平滑混合"互为补充,适合做硬切换)
若需深入实现细节,建议直接阅读 BlendVector3.cs 与通用插值工具 MathUtils.cs;想了解多输入槽的完整收集与失效机制,可查阅 MultiInputSlot.cs。
【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考