从图中,我们可以明显的看出,抛掷时的速度波形要明显比平时的速度波形变化剧烈很多。而在抛掷算法中,也正是使用这一抛掷状态的特性——抛掷时速度的峰值和变化率,高于平时速度的峰值与变化率。以此作为抛掷的触发源。
在传统的手势定义中,可以通过右手节点的x坐标与脊柱节点的x坐标、或者右手节点的x坐标与右肩膀节点x坐标的差值来识别手势,当差值超过某一个设定值时,触发函数,判定当前挥手的手势已经做出,这样的方法称之为“设值碰撞法”。而在抛掷的算法中,用坐标的差值来判断手势是否做出是非常粗暴的算法设计。这样的算法虽然粗暴,但是简单有效。在游戏厅里,常有跳舞机这样的体感设备,其实现原理,就是通过光束遮挡。当用户的肢体挡住了光束,接收器接收不到光束,便触发了状态位,判定用户完成了这个动作。这样的“光束遮挡法”,与“设值碰撞法”的原理是一致的,但是前者稍微灵活一点,因为采用了人体的相对位置差值,而不像后者,整个舞台的位置是绝对不变的。
当得到了右手骨骼节点的空间三维坐标值,并且该坐标值每秒钟有30帧的变化,就可以算出右手节点实时三个方向上的分速度与分加速度大小。若以1/30秒为单位时间,那么每秒钟就需要计算30次。这样的运算频率太高,而且计算出来的值会过小,超出float类型所能接受的范围。虽然这样的计算最为精细,但是,会给计算机带来很大的运算量。为了提高运行效率,程序中,将一秒钟计算30次改为一秒钟计算10次,通过设定一个整型变量,让其自加,每加到3就重置并计算一次速度与加速度,就实现了每秒计算10次的效果。并且程序中不使用double类型类存储数值,用float来存放速度值与加速度值。
计算x,y,z三个方向的分速度与合速度的公式如下:(单位时间t在实际项目中使用1/10秒,经实践测试,低于1/10秒会出现float变量无法计算出数值的现象。1/10秒可以方便开发过程中理解公式,方便公式计算。其中dx、dy、dz为三个方向上单位时间内的位置坐标差值。)
Vx = dx/t;Vy = dy/t;Vz = dz/t;V=(Vx^2+Vy^2+Vz^2)^0。5。
速度是矢量,有了三个方向上的分速度就可以得到空间内的方向。有了分速度,进一步,可以得到右手三个方向上的加速度以及合加速度,加速度计算公式如下:(单位时间t同样取1/10秒,dVx、dVy、dVz为三个方向上速度单位时间内的差值。)
Ax = dVx/t;Ay=dVy/t;Az=dVz/t;A=(Ax^2+Ay^2+Az^2)^0。5。
在程序运行时,我们将这些数据打印到屏幕上,方便我们观察调试,如图4-7、图4-8所示。图4-7为程序刚开始运行,没有用户使用的情况,图4-8为有用户正在使用该程序并移动右手的情况。通过屏幕上的数据,可以观察到,用户右手的速度以及加速度信息在不断地变化着,当用户右手停止移动,保持相对位置不变时,数据的小数点左侧以及小数点右侧两位都为零。由于识别抖动,速度与加速度数据不会是整零。
人肢体的每一个动作,实际上都是变速运动,当用户在移动右手的时候,右手的速度和加速度都在快速的改变。但是,日常生活中用户对右手的移动,不会使右手产生过大的加速度,而在抛掷物体的情况下,右手会产生较大的加速度。通过实验,我们发现,一般情况下,人们在使用右手时的速度不会超过2m/s,而当抛掷物体时,右手的速度会超过7m/s。我们以右手的速度超过7m/s,加速度超过70m/s作为触发抛掷函数的开关。程序中设定了抛掷开关(throwSwitch),此开关为一个bool值,当其值为true时,用户才可以进行抛掷,当用户抛掷完一个物体之后,开关关闭,即其值变为false,需要用户按一下空格键,将开关打开,及throwSwitch值再次置为true,才能进行下一次的抛掷。当用户在进行抛掷时,其右手速度超过7m/s并且加速度超过70m/s时,触发抛掷函数,将初速度、方向、初位置赋予小球,并实例化小球,交由Unity3D的物理引擎模拟其运动轨迹。 Kinect体感设备虚拟抛掷盛接系统的设计+源代码(7):http://www.youerw.com/jisuanji/lunwen_92206.html