VuforialTargetMove.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using QFramework.MREditor;
  6. using QFramework;
  7. /// <summary>
  8. /// 根据ImageTarget 和对应锚点 计算物体的 pos 和 rot以及物体的显示关闭
  9. /// </summary>
  10. public class VuforialTargetMove : MonoBehaviour
  11. {
  12. /// <summary>
  13. /// 需要显示的物体 只负责显示
  14. /// </summary>
  15. // public Transform showObj;
  16. public List<Transform> showObjs = new List<Transform>();
  17. /// <summary>
  18. /// 每个ImageTarget 对应的锚点
  19. /// </summary>
  20. public List<TargetShowObj> listObjs = new List<TargetShowObj>();
  21. [HideInInspector]
  22. /// <summary>
  23. /// 识别成功时,图片位置信息
  24. /// </summary>
  25. public Transform targetObj;
  26. public bool is6Dof = true;
  27. public float interval = 2;
  28. public float closeInterval = 3600f;
  29. ///// <summary>
  30. ///// 每张图对应显示物体的 位置差
  31. ///// </summary>
  32. //public Vector3 posOffset;
  33. ///// <summary>
  34. ///// 每张图对应显示物体的 旋转差
  35. ///// </summary>
  36. //public Vector3 rotOffset;
  37. public bool isClose = false;
  38. private bool state = false;
  39. /// <summary>
  40. /// 识别成功 三秒后打开
  41. /// </summary>
  42. private float openT;
  43. /// <summary>
  44. /// 10秒后关闭
  45. /// </summary>
  46. public float closeT;
  47. /// <summary>
  48. /// 每次打开只执行一次
  49. /// </summary>
  50. private bool OnlySet;
  51. private float onleyT;
  52. /// <summary>
  53. /// 当前识别TargetObj 对应的点
  54. /// </summary>
  55. private int num;
  56. private List<float> listRotY;
  57. private int lBNumber = 0;
  58. private List<float> listPosX;
  59. private List<float> listPosZ;
  60. private List<float> listPosX2;
  61. private List<float> listPosZ2;
  62. private KalmanFilter kf;
  63. void Start()
  64. {
  65. //rotOffset = Vector3.zero;
  66. //posOffset = Vector3.zero;
  67. if (listPosZ == null)
  68. {
  69. listRotY = new List<float>();
  70. listPosX = new List<float>();
  71. listPosZ = new List<float>();
  72. listPosX2 = new List<float>();
  73. listPosZ2 = new List<float>();
  74. }
  75. kf = new KalmanFilter();
  76. kf.SetQ(0.01f);
  77. kf.SetQ(0.1f);
  78. }
  79. // Update is called once per frame
  80. void Update()
  81. {
  82. //GameManager.Instance.text3.text = isClose + " " + GameManager.Instance.isEditor;
  83. if (isClose)
  84. return;
  85. TargetMove();
  86. #region 3Dof Move
  87. //if (state)
  88. //{
  89. // // 记时三秒 打开
  90. // openT += Time.deltaTime;
  91. // if(openT > interval)
  92. // {
  93. // SetShowObjePos();
  94. // closeT = 0;
  95. // // SetShowObjRot();
  96. // if (OnlySet)
  97. // {
  98. // onleyT += Time.deltaTime;
  99. // if (showObjs[0].gameObject.activeSelf == false || onleyT > interval) // 第一次打开 或者 替换了其它识别点
  100. // {
  101. // OnlySet = false;
  102. // for (int i = 0; i < showObjs.Count; i++)
  103. // {
  104. // showObjs[i].gameObject.SetActive(true);
  105. // }
  106. // GameManager.Instance.text2.text = "Show";
  107. // SetShowObjRot();
  108. // GameManager.Instance.text2.text = "OnlySet";
  109. // GameManager.Instance.editorPanel.transform.position = targetObj.position + new Vector3(-0.2f, -0.3f, 0.1f);
  110. // GameManager.Instance.editorPanel.transform.eulerAngles = new Vector3(GameManager.Instance.editorPanel.transform.eulerAngles.x,targetObj.eulerAngles.y, GameManager.Instance.editorPanel.transform.eulerAngles.z);
  111. // GameManager.Instance.SetIsEditor(false);
  112. // UIKit.GetPanel<EditorPanel>().SelectSpoitObj(showObjs[0].name);
  113. // }
  114. // }
  115. // }
  116. //}
  117. //else
  118. //{
  119. // // ⏲十秒 关闭
  120. // closeT += Time.deltaTime;
  121. // GameManager.Instance.text2.text = closeT.ToString();
  122. // if (closeT> closeInterval)
  123. // {
  124. // DirectClose();
  125. // // GameManager.Instance.SetIsEditor(true);
  126. // }
  127. //}
  128. #endregion
  129. }
  130. private void TargetMove()
  131. {
  132. if (state)
  133. {
  134. // 记时三秒 打开
  135. openT += Time.deltaTime;
  136. if (openT > interval && openT < interval * 2.1f)
  137. {
  138. SetShowObjePos();
  139. closeT = 0;
  140. // SetShowObjRot();
  141. if (OnlySet)
  142. {
  143. onleyT += Time.deltaTime;
  144. if (showObjs[0].gameObject.activeSelf == false || onleyT > interval) // 第一次打开 或者 替换了其它识别点
  145. {
  146. OnlySet = false;
  147. for (int i = 0; i < showObjs.Count; i++)
  148. {
  149. showObjs[i].gameObject.SetActive(true);
  150. GameManager.Instance.text.text = showObjs[i].name;
  151. }
  152. GameManager.Instance.text2.text = "Show";
  153. SetShowObjRot();
  154. GameManager.Instance.text2.text = "OnlySet";
  155. // GameManager.Instance.uiMove.OpenEditor(transform);
  156. UIKit.GetPanel<EditorPanel>().SelectSpoitObj(showObjs[0].name);
  157. }
  158. }
  159. }
  160. }
  161. else
  162. {
  163. // ⏲十秒 关闭
  164. closeT += Time.deltaTime;
  165. // GameManager.Instance.text2.text = closeT.ToString();
  166. if (closeT > closeInterval)
  167. {
  168. DirectClose();
  169. // GameManager.Instance.SetIsEditor(true);
  170. }
  171. }
  172. }
  173. /// <summary>
  174. /// 显示
  175. /// </summary>
  176. /// <param name="targetObj"> 识别成功后的target物体 </param>
  177. /// <param name="num"> 显示物体下对应的点 </param>
  178. public void Show(Transform targetObj, int num)
  179. {
  180. openT = 0;
  181. onleyT = 0;
  182. ReplaceShow(targetObj, num);
  183. }
  184. public void ReplaceShow(Transform targetObj, int num)
  185. {
  186. VuforialHint.Instance.Close();
  187. Debug.Log("@@@@" + transform.name);
  188. isClose = false;
  189. this.targetObj = targetObj;
  190. this.num = num;
  191. state = true;
  192. closeT = 0;
  193. OnlySet = true;
  194. if (listPosZ == null)
  195. {
  196. listPosZ = new List<float>();
  197. listPosX = new List<float>();
  198. listPosX2 = new List<float>();
  199. listPosZ2 = new List<float>();
  200. }
  201. else
  202. {
  203. listPosX.Clear();
  204. listPosZ.Clear();
  205. listPosX2.Clear();
  206. listPosZ2.Clear();
  207. }
  208. //showObj.parent = transform;
  209. //showObj.localEulerAngles = new Vector3(0, -90, 0);
  210. //showObj.parent = listObjs[num].transform;
  211. //showObj.localPosition = listObjs[num].pos;
  212. //showObj.eulerAngles = new Vector3(0, listObjs[num].rotY, 0);
  213. gameObject.SetActive(true);
  214. }
  215. public void Close()
  216. {
  217. state = false;
  218. // isClose = true;
  219. // GameManager.Instance.SetIsEditor(true);
  220. // closeT = 0;
  221. //if(listRotY.Count>10)
  222. //transform.eulerAngles = new Vector3(transform.eulerAngles.x, listRotY.Average(), transform.eulerAngles.z);
  223. //listRotY.Clear();
  224. //listRotY = new List<float>();
  225. // showObj.parent = null;
  226. }
  227. /// <summary>
  228. /// 强制关闭
  229. /// </summary>
  230. public void DirectClose()
  231. {
  232. //showObj.parent = transform;
  233. //showObj.localEulerAngles = new Vector3(0, -90, 0);
  234. VuforialHint.Instance.Show();
  235. for (int i = 0; i < showObjs.Count; i++)
  236. {
  237. showObjs[i].gameObject.SetActive(false);
  238. }
  239. closeT = 0;
  240. state = false;
  241. isClose = true;
  242. VuforialControl.Instance.Close();
  243. // GameManager.Instance.uiMove.CloseEditor();
  244. // GameManager.Instance.SetIsEditor(true);
  245. // gameObject.SetActive(false);
  246. }
  247. private void SetShowObjePos()
  248. {
  249. if (listObjs.Count == 0)
  250. {
  251. Debug.Log(" 未设置锚点");
  252. return;
  253. }
  254. Vector3 pos = targetObj.position - listObjs[num].transform.position;
  255. #region 双卡尔曼滤波 物体晃动幅度小,移动平滑 (仅适合用于3Dof)
  256. // Debug.Log(num + "@@@");
  257. if (Mathf.Abs(pos.x) < 0.25f && Mathf.Abs(pos.z) < 0.2f)
  258. {
  259. lBNumber++;
  260. listPosX.Add(pos.x);
  261. listPosZ.Add(pos.z);
  262. if (listPosX.Count > 10)
  263. {
  264. listPosX.RemoveAt(0);
  265. listPosZ.RemoveAt(0);
  266. }
  267. if (lBNumber > 10)
  268. {
  269. List<float> x = new List<float>(kf.Filter(listPosX.ToArray()));
  270. pos.x = kf.Filter(pos.x);
  271. List<float> z = new List<float>(kf.Filter(listPosZ.ToArray()));
  272. pos.z = kf.Filter(pos.z);
  273. // transform.position += new Vector3(x.Average(), 0, z.Average());
  274. transform.position += new Vector3(pos.x, 0, pos.z);
  275. //VuforialControl.Instance.text1.text = transform.position.ToString();
  276. //VuforialControl.Instance.text3.text = "Kalman LB " + pos.x.ToString() + " " + pos.z.ToString();
  277. return;
  278. }
  279. }
  280. else
  281. {
  282. lBNumber = 0;
  283. listPosX2.Add(pos.x);
  284. listPosZ2.Add(pos.z);
  285. if (listPosX2.Count > 10)
  286. {
  287. listPosX2.RemoveAt(0);
  288. listPosZ2.RemoveAt(0);
  289. List<float> x = new List<float>(kf.Filter(listPosX2.ToArray()));
  290. pos.x = kf.Filter(pos.x);
  291. List<float> z = new List<float>(kf.Filter(listPosZ2.ToArray()));
  292. pos.z = kf.Filter(pos.z);
  293. // transform.position += new Vector3(pos.x, 0, pos.z);
  294. transform.position += new Vector3(pos.x, 0, pos.z);
  295. //VuforialControl.Instance.text3.text = "Kalman " + pos.x.ToString() + " " + pos.z.ToString();
  296. // VuforialControl.Instance.text1.text = transform.position.ToString();
  297. }
  298. }
  299. #endregion
  300. }
  301. /// <summary>
  302. /// 设置旋转属性
  303. /// </summary>
  304. private void SetShowObjRot()
  305. {
  306. // transform.eulerAngles = obj.eulerAngles + rotOffset;
  307. if (listObjs.Count == 0)
  308. {
  309. Debug.Log(" 未设置锚点");
  310. return;
  311. }
  312. if (targetObj.eulerAngles.x > 60 || targetObj.eulerAngles.x < 60)
  313. {
  314. float y = targetObj.eulerAngles.y - listObjs[num].transform.eulerAngles.y;
  315. //listObjs[num].transform.eulerAngles = new Vector3(listObjs[num].transform.eulerAngles.x, targetObj.eulerAngles.z, listObjs[num].transform.eulerAngles.z);
  316. // listObjs[num].transform.eulerAngles = targetObj.eulerAngles;
  317. transform.RotateAround(listObjs[num].transform.position, Vector3.down, -y);
  318. Vector3 pos = targetObj.position - listObjs[num].transform.position;
  319. transform.position += new Vector3(0, pos.y, 0);
  320. }
  321. else
  322. {
  323. float y = targetObj.eulerAngles.y - listObjs[num].transform.eulerAngles.y;
  324. //listObjs[num].transform.eulerAngles = new Vector3(listObjs[num].transform.eulerAngles.x, targetObj.eulerAngles.z, listObjs[num].transform.eulerAngles.z);
  325. // listObjs[num].transform.eulerAngles = targetObj.eulerAngles;
  326. transform.RotateAround(listObjs[num].transform.position, Vector3.up, y);
  327. Vector3 pos = targetObj.position - listObjs[num].transform.position;
  328. transform.position += new Vector3(0, pos.y, 0);
  329. }
  330. }
  331. }