“LlSetKeyframedMotion”的版本间的差异
(创建页面,内容为“{{LSL Header|ml=*}}{{LSLC|Keywords}}{{LSLC|Flow Control}}{{LSLC|}} {{函数详情 |函数名 = Function: llSetKeyframedMotion( list keyframes, list options ); |参…”) |
|||
第5行: | 第5行: | ||
|函数名 = Function: llSetKeyframedMotion( list keyframes, list options ); | |函数名 = Function: llSetKeyframedMotion( list keyframes, list options ); | ||
|参数= 参数: | |参数= 参数: | ||
− | • list keyframes - 表格关键帧列表: | + | • list keyframes - 表格关键帧列表: |
向量位置(可通过[[KFM_TRANSLATION]]和[[KFM_DATA]]实现) | 向量位置(可通过[[KFM_TRANSLATION]]和[[KFM_DATA]]实现) | ||
旋转方向(通过[[KFM_ROTATION]]和[[KFM_DATA]]可选) | 旋转方向(通过[[KFM_ROTATION]]和[[KFM_DATA]]可选) | ||
浮动时间 | 浮动时间 | ||
每个关键帧都是相对于对象之前的变换进行解释的。例如,考虑以下关键帧列表:[<0,0,10>,ZERO_ROTATION, 5, <0, 0, 0>, ZERO_ROTATION, 5, <0, 0, -10>, ZERO_ROTATION, 5]。这将导致物体在5s的过程中向上移动10m。在接下来的5秒中,它会在这个位置停留5秒,然后向下移动10米。时间值必须是1/9。或更高版本。线速度和角速度将被限制在模拟器设置的限制(值TBD)。空列表将终止任何当前正在播放的键框动画。 | 每个关键帧都是相对于对象之前的变换进行解释的。例如,考虑以下关键帧列表:[<0,0,10>,ZERO_ROTATION, 5, <0, 0, 0>, ZERO_ROTATION, 5, <0, 0, -10>, ZERO_ROTATION, 5]。这将导致物体在5s的过程中向上移动10m。在接下来的5秒中,它会在这个位置停留5秒,然后向下移动10米。时间值必须是1/9。或更高版本。线速度和角速度将被限制在模拟器设置的限制(值TBD)。空列表将终止任何当前正在播放的键框动画。 | ||
− | + | • list options - 修饰符和未来选项 | |
− | • list options - 修饰符和未来选项 | ||
|返回值= 返回值:指定一个对象后面要跟随的时间、位置和方向列表。对象将在模拟器的关键帧之间平滑移动。与其他非物理或关键帧对象的冲突将被忽略(不会触发任何脚本事件,也不会发生冲突处理)。与物理对象的碰撞将被计算和报告,但是关键帧对象将不受这些碰撞的影响。(不过,物理对象将受到影响。) | |返回值= 返回值:指定一个对象后面要跟随的时间、位置和方向列表。对象将在模拟器的关键帧之间平滑移动。与其他非物理或关键帧对象的冲突将被忽略(不会触发任何脚本事件,也不会发生冲突处理)。与物理对象的碰撞将被计算和报告,但是关键帧对象将不受这些碰撞的影响。(不过,物理对象将受到影响。) | ||
第22行: | 第21行: | ||
[[KFM_CMD_STOP]], [[KFM_CMD_PLAY]], [[KFM_CMD_PAUSE]]。STOP将暂停动画并将其重置到开始位置。PAUSE将在不重置的情况下暂停动画。播放将恢复暂停或停止的动画。 | [[KFM_CMD_STOP]], [[KFM_CMD_PLAY]], [[KFM_CMD_PAUSE]]。STOP将暂停动画并将其重置到开始位置。PAUSE将在不重置的情况下暂停动画。播放将恢复暂停或停止的动画。 | ||
注意,如果在选项列表中提供了KFM_COMMAND,那么它必须是列表中唯一的选项,并且不能在设置关键帧列表的同一个函数调用中指定。 | 注意,如果在选项列表中提供了KFM_COMMAND,那么它必须是列表中唯一的选项,并且不能在设置关键帧列表的同一个函数调用中指定。 | ||
− | |||
支持区域间的移动;只要指定一个目标关键帧,它将把对象放在sim边界之外,它就会跨越。这似乎提供了相同的效果,暂停动画时,它是在中间的两个区域,但观众继续插值它的运动。它会跳回sim边界,并继续以相同的速度前进,尽管路径点之间的时间会因为sim的穿越而增加。确保将这一点考虑到系统中。 | 支持区域间的移动;只要指定一个目标关键帧,它将把对象放在sim边界之外,它就会跨越。这似乎提供了相同的效果,暂停动画时,它是在中间的两个区域,但观众继续插值它的运动。它会跳回sim边界,并继续以相同的速度前进,尽管路径点之间的时间会因为sim的穿越而增加。确保将这一点考虑到系统中。 | ||
− | |||
由于键框动作是一个prim属性,而不是局限于调用它的脚本,您可以使用多个脚本来控制、暂停或重新启动相同的键框动作,而不需要传递提供的原始关键帧列表。只需传递一个空的关键帧列表和KFM_COMMAND,后面跟着选项列表中的命令。 | 由于键框动作是一个prim属性,而不是局限于调用它的脚本,您可以使用多个脚本来控制、暂停或重新启动相同的键框动作,而不需要传递提供的原始关键帧列表。只需传递一个空的关键帧列表和KFM_COMMAND,后面跟着选项列表中的命令。 | ||
第229行: | 第226行: | ||
| rowspan="4" | [ [[integer]] command ] | | rowspan="4" | [ [[integer]] command ] | ||
| colspan="3" |设置命令 | | colspan="3" |设置命令 | ||
+ | |- | ||
| [[KFM_CMD_PLAY]] | | [[KFM_CMD_PLAY]] | ||
| 0 | | 0 | ||
| ? | | ? | ||
+ | |- | ||
| [[KFM_CMD_STOP]] | | [[KFM_CMD_STOP]] | ||
| 1 | | 1 | ||
| ? | | ? | ||
+ | |- | ||
| [[KFM_CMD_PAUSE]] | | [[KFM_CMD_PAUSE]] | ||
| 2 | | 2 | ||
第243行: | 第243行: | ||
| rowspan="5" | [ [[integer]] mode ] | | rowspan="5" | [ [[integer]] mode ] | ||
| colspan="3" |设置回放模式 默认为[[KFM_FORWARD]] | | colspan="3" |设置回放模式 默认为[[KFM_FORWARD]] | ||
+ | |- | ||
| [[KFM_FORWARD]] | | [[KFM_FORWARD]] | ||
| 0 | | 0 | ||
| ? | | ? | ||
+ | |- | ||
| [[KFM_LOOP]] | | [[KFM_LOOP]] | ||
| 1 | | 1 | ||
| ? | | ? | ||
+ | |- | ||
| [[KFM_PING_PONG]] | | [[KFM_PING_PONG]] | ||
| 2 | | 2 | ||
| ? | | ? | ||
+ | |- | ||
| [[KFM_REVERSE]] | | [[KFM_REVERSE]] | ||
| 3 | | 3 | ||
第260行: | 第264行: | ||
| rowspan="3" | [ [[integer]] fields ] | | rowspan="3" | [ [[integer]] fields ] | ||
| colspan="3" |设置关键帧包含什么数据 (默认为([[KFM_ROTATION]] | [[KFM_TRANSLATION]]) | | colspan="3" |设置关键帧包含什么数据 (默认为([[KFM_ROTATION]] | [[KFM_TRANSLATION]]) | ||
+ | |- | ||
| [[KFM_ROTATION]] | | [[KFM_ROTATION]] | ||
| 0x1 | | 0x1 | ||
| ? | | ? | ||
+ | |- | ||
| [[KFM_TRANSLATION]] | | [[KFM_TRANSLATION]] | ||
| 0x2 | | 0x2 | ||
| ? | | ? | ||
|} | |} |
2020年8月22日 (六) 07:52的最新版本
首页 | 函数 | 事件 | 类型 | 操作符 | 常数 | Flow Control | Script Library | Categorized Library | Tutorials |
函数名 |
---|
Function: llSetKeyframedMotion( list keyframes, list options ); |
参数:
• list keyframes - 表格关键帧列表: 向量位置(可通过KFM_TRANSLATION和KFM_DATA实现) 旋转方向(通过KFM_ROTATION和KFM_DATA可选) 浮动时间 每个关键帧都是相对于对象之前的变换进行解释的。例如,考虑以下关键帧列表:[<0,0,10>,ZERO_ROTATION, 5, <0, 0, 0>, ZERO_ROTATION, 5, <0, 0, -10>, ZERO_ROTATION, 5]。这将导致物体在5s的过程中向上移动10m。在接下来的5秒中,它会在这个位置停留5秒,然后向下移动10米。时间值必须是1/9。或更高版本。线速度和角速度将被限制在模拟器设置的限制(值TBD)。空列表将终止任何当前正在播放的键框动画。 • list options - 修饰符和未来选项 |
返回值:指定一个对象后面要跟随的时间、位置和方向列表。对象将在模拟器的关键帧之间平滑移动。与其他非物理或关键帧对象的冲突将被忽略(不会触发任何脚本事件,也不会发生冲突处理)。与物理对象的碰撞将被计算和报告,但是关键帧对象将不受这些碰撞的影响。(不过,物理对象将受到影响。) |
注意事项 |
---|
Specification
选项列表将支持以下标志: KFM_MODE后面跟着一个:KFM_LOOP, KFM_REVERSE, KFM_FORWARD,或KFM_PING_PONG将指定播放模式。默认为KFM_FORWARD。在提供关键帧列表时必须指定。 KFM_DATA后面是按位组合的:KFM_TRANSLATION和KFM_ROTATION。默认情况下,旋转和平移都必须提供。如果您指定了其中一个或另一个,您应该只在关键帧列表中包含转换或旋转。必须在提供关键帧列表时指定。 KFM_CMD_STOP, KFM_CMD_PLAY, KFM_CMD_PAUSE。STOP将暂停动画并将其重置到开始位置。PAUSE将在不重置的情况下暂停动画。播放将恢复暂停或停止的动画。 注意,如果在选项列表中提供了KFM_COMMAND,那么它必须是列表中唯一的选项,并且不能在设置关键帧列表的同一个函数调用中指定。 支持区域间的移动;只要指定一个目标关键帧,它将把对象放在sim边界之外,它就会跨越。这似乎提供了相同的效果,暂停动画时,它是在中间的两个区域,但观众继续插值它的运动。它会跳回sim边界,并继续以相同的速度前进,尽管路径点之间的时间会因为sim的穿越而增加。确保将这一点考虑到系统中。 由于键框动作是一个prim属性,而不是局限于调用它的脚本,您可以使用多个脚本来控制、暂停或重新启动相同的键框动作,而不需要传递提供的原始关键帧列表。只需传递一个空的关键帧列表和KFM_COMMAND,后面跟着选项列表中的命令。 此功能在附件中不起作用。 这个函数只能在非物理对象上调用。在未来,它可能会扩展到支持物理对象,但这更加复杂,因为碰撞可能会阻止物体准时到达目标位置。 当关键帧运动处于活动状态时,您不能使用脚本来移动linkset中的任何prim。如果你必须,首先暂停和重新启动KFM_CMD_PLAY时,完成。#例子 与化身的碰撞会影响物体的角度运动,它可能无法到达最终的旋转。 这个函数只能在链接集的根prim上调用。 这个函数要求链接集使用Prim等价系统。然而,它的关键帧对象将不会受到动力学惩罚,并可以有一个物理重量高达64。 llSetKeyframedMotion是根据帧来实现的,而不是实时的。为了避免偏离预期的位置和旋转,使用1/45的整数倍数的时间,例如20.0/45.0,40.0/45.0,90.0/45.0,等等。论坛线程KFM声称增量时间必须大于0.1秒;但是在实践中,delta时间稍微超过0.1就会在DEBUG_CHANNEL上产生错误。测试显示最小的增量时间大约是6/45(.13333)秒。 自然漂移仍然可能发生;为了获得最佳效果,使用moving_end来确定动画何时结束,并使用llSetPos来确认目标位置。或者您可以使用at_target或at_rot_target。 化身动画系统有一些缺陷,当你站在移动平台上时,可能会产生一些奇怪的动画(例如,在原地行走,脚对着骨盆)。我们希望在将来修复这些问题,但是这样做超出了该特性的范围。 与动态对象一样,使用此函数移动的对象被具有适当权限的化身(对象所有者、乘客等)选中时将暂停。当这样一个化身取消选择对象时,运动恢复,即使对象已经被KFM_CMD_PAUSE暂停。 关键帧运动在某些方面是一种prim性质。当KFM_LOOP或KFM_PING_PONG被启动时,该动作在脚本被删除后被保留。也就是说,prim将继续它的运动。它会生存下来,获取和复制。它将在服务器重启后继续存在。 区域间的流动远非完美。使用一个在弯曲路径上有大量帧的关键帧列表从sim 1交叉到sim 2会在交叉时出现明显的错误,当用[KFM_MODE, KFM_REVERSE]反转时,对象会留在sim 2中,永远不会返回到sim 1 |
示例 |
---|
//如果你的客户不是网格感知,请使用以下代码: llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); llSetKeyframedMotion( [<0.0, 0.0, 10.0>, 5, <0.0, 0.0, -10.0>, 5], [KFM_DATA, KFM_TRANSLATION, KFM_MODE, KFM_PING_PONG]); llSetKeyframedMotion( [<0.0, 0.0, 10.0>, llEuler2Rot(<90, 45, 180> * DEG_TO_RAD), 5, <0.0, 0.0, -10.0>, llEuler2Rot(<270, 225, 360> * DEG_TO_RAD), 5], [KFM_MODE, KFM_REVERSE]); Pause-Play llSetKeyframedMotion([],[KFM_COMMAND, KFM_CMD_PAUSE]); //修改这里的prim位置 llSetKeyframedMotion([],[KFM_COMMAND, KFM_CMD_PLAY]); Sample Script - Key Framed Follower 在某些情况下,旋转会产生运行时错误,除非它们被归一化。这个脚本演示了使用规范化目标旋转使用llKeyframedMotion创建追随者的方法——例如,考虑一下一辆车后面的一辆车。 integer isSensorRepeatOn; rotation NormRot(rotation Q) { float MagQ = llSqrt(Q.x*Q.x + Q.y*Q.y +Q.z*Q.z + Q.s*Q.s); return <Q.x/MagQ, Q.y/MagQ, Q.z/MagQ, Q.s/MagQ>; } default { state_entry() { llSetLinkPrimitiveParamsFast(LINK_ROOT, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX, PRIM_LINK_TARGET, LINK_ALL_CHILDREN, PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_NONE]); } touch_start(integer total_number) { isSensorRepeatOn = !isSensorRepeatOn; if (isSensorRepeatOn) { // PUBLIC_CHANNEL has the integer value 0 llSay(PUBLIC_CHANNEL, "Sensor repeat switched on!"); llSensorRepeat("", "91b39b5b-13b1-2517-273a-67360b842c02", SCRIPTED, 10.0, PI, 0.1); } else // { llSensorRemove(); // } } sensor(integer num_detected) { vector ownPosition = llGetPos(); rotation ownRotation = llGetRot(); vector detectedPosition = llDetectedPos(0); rotation detectedRotation = llDetectedRot(0); llSetKeyframedMotion( [(detectedPosition - ownPosition) + <-1.0, 0.0, 0.2>*detectedRotation, NormRot(detectedRotation/ownRotation), 0.12], []); } } Universal Hinged Motion in 8 Key Frames 该脚本将把一个盒子沿平行于该盒子y轴的一条边旋转 该脚本适用于任何prim方向 注意,每帧接受的最小时间是1/9S=0.11111111S,而不是0.1S float angleEnd=PI_BY_TWO; float speed=0.2; // m/S float steps=8.0; // number of Key Frames float step=0.0; list KFMlist=[]; vector V; integer open=TRUE; vector basePos; rotation baseRot; float motion_time( float mt) { mt = llRound(45.0*mt)/45.0; if ( mt > 0.11111111 ) return mt; else return 0.11111111; } default { state_entry() { llSetMemoryLimit(0x2000); llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); basePos = llGetPos(); baseRot = llGetRot(); vector v1 = 0.5*llGetScale()*llGetRot(); rotation deltaRot = llEuler2Rot(< 0.0, angleEnd/steps, 0.0>); while ( step < steps ) { V = v1*llAxisAngle2Rot(llRot2Left(llGetRot()), angleEnd*step/steps); V = v1*llAxisAngle2Rot(llRot2Left(llGetRot()), angleEnd*(step+1.0)/steps) - V; KFMlist += [V, deltaRot, motion_time(llVecMag(V)/speed)]; step += 1.0; } } touch_end( integer n) { llSetKeyframedMotion( [], []); if ( open ) { llSetPrimitiveParams([PRIM_POSITION, basePos, PRIM_ROTATION, baseRot]); llSetKeyframedMotion( KFMlist, []); } else { llSetKeyframedMotion( KFMlist, [KFM_MODE, KFM_REVERSE]); } open = !open; } on_rez( integer n) { llResetScript(); } } 在编辑了prim位置,旋转和/或大小脚本应该重置,以更新运动 Continuous Spin 下面的例子所做的事情与使用llTargetOmega(<0.0,0.0,1.0>,PI,1.0)使一个prim围绕z轴连续旋转相同,假设prim被设置为凸壳并且是非物理的。 integer gON; default { touch_start(integer total_number) { gON = !gON; if (gON) { // Make repeated rotations of PI/2 radians, each taking 0.5 seconds llSetKeyframedMotion([llEuler2Rot(<0.0,0.0,PI/2>), 0.5],[KFM_DATA,KFM_ROTATION, KFM_MODE,KFM_LOOP]); } else { llSetKeyframedMotion([],[]); } } } |
相关函数 |
---|
无 |
相关事件 |
---|
无 |
附录:(表格)
options flags | Additional Parameters | Description | |||
---|---|---|---|---|---|
[ KFM_COMMAND ] | 0 | [ integer command ] | 设置命令 | ||
KFM_CMD_PLAY | 0 | ? | |||
KFM_CMD_STOP | 1 | ? | |||
KFM_CMD_PAUSE | 2 | ? | |||
[ KFM_MODE ] | 1 | [ integer mode ] | 设置回放模式 默认为KFM_FORWARD | ||
KFM_FORWARD | 0 | ? | |||
KFM_LOOP | 1 | ? | |||
KFM_PING_PONG | 2 | ? | |||
KFM_REVERSE | 3 | ? | |||
[ KFM_DATA ] | 2 | [ integer fields ] | 设置关键帧包含什么数据 (默认为(KFM_ROTATION | KFM_TRANSLATION) | ||
KFM_ROTATION | 0x1 | ? | |||
KFM_TRANSLATION | 0x2 | ? |