查看“LlSetKeyframedMotion”的源代码
←
LlSetKeyframedMotion
跳转至:
导航
、
搜索
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
{{LSL Header|ml=*}}{{LSLC|Keywords}}{{LSLC|Flow Control}}{{LSLC|}} {{函数详情 |函数名 = 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 |示例= <pre> //如果你的客户不是网格感知,请使用以下代码: llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); </pre> <pre> llSetKeyframedMotion( [<0.0, 0.0, 10.0>, 5, <0.0, 0.0, -10.0>, 5], [KFM_DATA, KFM_TRANSLATION, KFM_MODE, KFM_PING_PONG]); </pre> <pre> 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]); </pre> '''Pause-Play''' <pre> llSetKeyframedMotion([],[KFM_COMMAND, KFM_CMD_PAUSE]); //修改这里的prim位置 llSetKeyframedMotion([],[KFM_COMMAND, KFM_CMD_PLAY]); </pre> '''Sample Script - Key Framed Follower''' 在某些情况下,旋转会产生运行时错误,除非它们被归一化。这个脚本演示了使用规范化目标旋转使用llKeyframedMotion创建追随者的方法——例如,考虑一下一辆车后面的一辆车。 <pre> 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], []); } } </pre> '''Universal Hinged Motion in 8 Key Frames''' 该脚本将把一个盒子沿平行于该盒子y轴的一条边旋转 该脚本适用于任何prim方向 注意,每帧接受的最小时间是1/9S=0.11111111S,而不是0.1S <pre> 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(); } } </pre> 在编辑了prim位置,旋转和/或大小脚本应该重置,以更新运动 '''Continuous Spin''' 下面的例子所做的事情与使用llTargetOmega(<0.0,0.0,1.0>,PI,1.0)使一个prim围绕z轴连续旋转相同,假设prim被设置为凸壳并且是非物理的。 <pre> 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([],[]); } } } </pre> }} 附录:(表格) {| class="wikitable" border="1" |- ! colspan="2" | options flags ! Additional Parameters ! colspan="3" | Description |- | rowspan="4" | [ [[KFM_COMMAND]] ] | rowspan="4" | 0 | rowspan="4" | [ [[integer]] command ] | colspan="3" |设置命令 | [[KFM_CMD_PLAY]] | 0 | ? | [[KFM_CMD_STOP]] | 1 | ? | [[KFM_CMD_PAUSE]] | 2 | ? |- | rowspan="5" | [ [[KFM_MODE]] ] | rowspan="5" | 1 | rowspan="5" | [ [[integer]] mode ] | colspan="3" |设置回放模式 默认为[[KFM_FORWARD]] | [[KFM_FORWARD]] | 0 | ? | [[KFM_LOOP]] | 1 | ? | [[KFM_PING_PONG]] | 2 | ? | [[KFM_REVERSE]] | 3 | ? |- | rowspan="3" | [ [[KFM_DATA]] ] | rowspan="3" | 2 | rowspan="3" | [ [[integer]] fields ] | colspan="3" |设置关键帧包含什么数据 (默认为([[KFM_ROTATION]] | [[KFM_TRANSLATION]]) | [[KFM_ROTATION]] | 0x1 | ? | [[KFM_TRANSLATION]] | 0x2 | ? |}
该页面使用的模板:
模板:LSL Header
(
查看源代码
)
模板:LSLC
(
查看源代码
)
模板:LSLGC
(
查看源代码
)
模板:Multi-lang
(
查看源代码
)
模板:函数详情
(
查看源代码
)
返回至
LlSetKeyframedMotion
。
导航菜单
个人工具
登录
名字空间
页面
讨论
变种
视图
阅读
查看源代码
查看历史
更多
搜索
导航
网站首页
知识百科
编辑帮助
最近更改
工具
链入页面
相关更改
特殊页面
页面信息