在Vuforia的所有功能中,虚拟按钮是唯一一个交互的功能,而且这个功能相当精彩,使用它可以开发很多有趣的应用。
使用虚拟按钮demo,会有两个疑问:
1、按钮位置怎么确定的?
2、按钮怎么检测到的?
首先给大家介绍按钮位置的确定。
有两种方式:
1、自己通过公式计算。
对于这种方式,只用做研究使用。实际开发过程中,不需要这么复杂。但是计算方法还是贴出来,以供参考。
在群里看到很多人在问虚拟按钮实例中的按钮坐标是怎么计算出来的,今天就给大家讲讲计算原理!
问题:虚拟按钮这个位置坐标怎么确定的?
见上图,原点在左上角,竖直方向为Y轴,水平方向是X轴,且是(1500,1050)像素。按钮的尺寸是(200,75)。
下表中原始像素坐标分别为按钮矩形框中左上角和右下角的坐标值。
右边一列是经过尺寸转换之后图片标志的坐标值。那么它是经过怎样的变换得来的呢??
下面这幅图展示了该SDK中3D坐标系。而上表右边的数据就是讲原始坐标系转化成3D坐标系得出的值。大家可以看到3D坐标系的原点在Image的中心,因此不难解释上表中会出现负值。
下面给大家列出相应的计算公式。
计算比较简单,用相似比就可以了,不过大家注意单位的转换。
利用相似关系:
90/750 =(123.5-X)/123.5
利用这个公式计算出X是108.68
同理,可以计算出Y值,再判断正负,所以得出坐标值(-108.68,-53.52)
2、SDK自动计算。
这里使用unity3d开发。
复制代码
private Vector2 top;
private Vector2 bottom;
#region UNITY_MONOBEHAVIOUR_METHODS
void Start()
{
// Register with the virtual buttons TrackableBehaviour
VirtualButtonBehaviour[] vbs = GetComponentsInChildren<VirtualButtonBehaviour>();
for (int i = 0; i < vbs.Length; ++i)
{
vbs.RegisterEventHandler(this);
vbs.CalculateButtonArea(out top,out bottom);
Debug.Log(vbs.VirtualButton.Name+"---->"+top.x+":"+top.y+"----->"+bottom.x+":"+bottom.y);
}
// Get handle to the teapot object
mTeapot = transform.FindChild("teapot").gameObject;
// The list of active materials
mActiveMaterials = new List<Material>();
}
计算结果:
分别对应以下几个Virtual Button:
其实,在实际项目中,不需要计算按钮位置,直接使用Virtual Button的prefab即可。
在unity3d平台下,主要涉及到一个类和一个接口:
VirtualButtonEventHandler和IVirtualButtonEventHandler。这里是我自定义的一个类,但是必须要实现这个接口。
其中这个接口包含两个方法:
public void OnButtonPressed(VirtualButtonAbstractBehaviour vb)
public void OnButtonReleased(VirtualButtonAbstractBehaviour vb)
跟普通按钮一样,点击和释放的两个功能。
这段代码大概的执行流程如下:
1、实现接口,重载接口方法
2、查找所有的VirtualButtonBehaviour组件,可以将其理解为一个Button,然后每个button需要注册事件,
3、根据不同的button名称处理不同的事件
其实程序执行就这三步。
复制代码
public class VirtualButtonEventHandler : MonoBehaviour,
IVirtualButtonEventHandler
{
#region PUBLIC_MEMBER_VARIABLES
/// <summary>
/// The materials that will be set for the teapot model
/// </summary>
public Material[] m_TeapotMaterials;
#endregion // PUBLIC_MEMBER_VARIABLES
#region PRIVATE_MEMBER_VARIABLES
private GameObject mTeapot;
private List<Material> mActiveMaterials;
#endregion // PRIVATE_MEMBER_VARIABLES
#region UNITY_MONOBEHAVIOUR_METHODS
void Start()
{
// Register with the virtual buttons TrackableBehaviour
VirtualButtonBehaviour[] vbs = GetComponentsInChildren<VirtualButtonBehaviour>();
for (int i = 0; i < vbs.Length; ++i)
{
vbs.RegisterEventHandler(this);
}
// Get handle to the teapot object
mTeapot = transform.FindChild("teapot").gameObject;
// The list of active materials
mActiveMaterials = new List<Material>();
}
#endregion // UNITY_MONOBEHAVIOUR_METHODS
#region PUBLIC_METHODS
/// <summary>
/// Called when the virtual button has just been pressed:
/// </summary>
public void OnButtonPressed(VirtualButtonAbstractBehaviour vb)
{
Debug.Log("OnButtonPressed::" + vb.VirtualButtonName);
if (!IsValid())
{
return;
}
// Add the material corresponding to this virtual button
// to the active material list:
switch (vb.VirtualButtonName)
{
case "red":
mActiveMaterials.Add(m_TeapotMaterials[0]);
break;
case "blue":
mActiveMaterials.Add(m_TeapotMaterials[1]);
break;
case "yellow":
mActiveMaterials.Add(m_TeapotMaterials[2]);
break;
case "green":
mActiveMaterials.Add(m_TeapotMaterials[3]);
break;
}
// Apply the new material:
if (mActiveMaterials.Count > 0)
mTeapot.GetComponent<Renderer>().material = mActiveMaterials[mActiveMaterials.Count - 1];
}
/// <summary>
/// Called when the virtual button has just been released:
/// </summary>
public void OnButtonReleased(VirtualButtonAbstractBehaviour vb)
{
if (!IsValid())
{
return;
}
// Remove the material corresponding to this virtual button
// from the active material list:
switch (vb.VirtualButtonName)
{
case "red":
mActiveMaterials.Remove(m_TeapotMaterials[0]);
break;
case "blue":
mActiveMaterials.Remove(m_TeapotMaterials[1]);
break;
case "yellow":
mActiveMaterials.Remove(m_TeapotMaterials[2]);
break;
case "green":
mActiveMaterials.Remove(m_TeapotMaterials[3]);
break;
}
// Apply the next active material, or apply the default material:
if (mActiveMaterials.Count > 0)
mTeapot.GetComponent<Renderer>().material = mActiveMaterials[mActiveMaterials.Count - 1];
else
mTeapot.GetComponent<Renderer>().material = m_TeapotMaterials[4];
}
private bool IsValid()
{
// Check the materials and teapot have been set:
return m_TeapotMaterials != null &&
m_TeapotMaterials.Length == 5 &&
mTeapot != null;
}
#endregion // PUBLIC_METHODS
}
但是在这三步之前,还有一个工作必须要完成,就是在场景中配置虚拟按钮(VB)。
在Unity3D中,VirtualButton组件也是作为一个Prefab存在,只需要将其拖拽到对应的ImageTarget下,作为其子类,然后在scene中手动设置其位置和大小即可。
其次需要对起进行行为设定,主要是VirtualButtonBehaviour这个脚本。
主要有两个属性,一个name,一个Sensitivity 设置。
Name对应脚本中事件触发的判断,敏感度设置有三个选项,分别是低中高,越高越容易被识别,我一般设置我High。
然后在
复制代码
public void OnButtonPressed(VirtualButtonAbstractBehaviour vb)方法体中加一句判断就好:
case "test":// 该名称是由前面设置的
mActiveMaterials.Remove(m_TeapotMaterials[3]);
break;
请尊重所有作者的劳动,转载请注明原帖来自 AR学院 !
Unity开发: