ImageTracker.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.Events;
  5. #if IMAGINE_URP
  6. using UnityEngine.Rendering;
  7. using UnityEngine.Rendering.Universal;
  8. #endif
  9. using System.Runtime.InteropServices;
  10. namespace Imagine.WebAR
  11. {
  12. [System.Serializable]
  13. public class ImageTarget
  14. {
  15. public string id;
  16. public Transform transform;
  17. [HideInInspector] public Vector3 targetPos;
  18. [HideInInspector] public Quaternion targetRot;
  19. }
  20. public class ImageTracker : MonoBehaviour
  21. {
  22. [DllImport("__Internal")] private static extern void StartWebGLiTracker(string ids, string name);
  23. [DllImport("__Internal")] private static extern void StopWebGLiTracker();
  24. [DllImport("__Internal")] private static extern float SetWebGLiTrackerSettings(string settings);
  25. [DllImport("__Internal")] private static extern bool IsWebGLiTrackerReady();
  26. [DllImport("__Internal")] private static extern float DebugImageTarget(string id);
  27. [DllImport("__Internal")] private static extern bool IsWebGLImageTracked(string id);
  28. [SerializeField] private ARCamera trackerCam;
  29. [SerializeField] private List<ImageTarget> imageTargets;
  30. private Dictionary<string, ImageTarget> targets = new Dictionary<string, ImageTarget>();
  31. private enum TrackerOrigin { CAMERA_ORIGIN, FIRST_TARGET_ORIGIN }
  32. [SerializeField] private TrackerOrigin trackerOrigin;
  33. [SerializeField] private List<string> trackedIds = new List<string>();
  34. private string serializedIds = "";
  35. // [SerializeField] private bool overrideTrackerSettings = false;
  36. [SerializeField] private TrackerSettings trackerSettings;
  37. [SerializeField] private bool dontDeactivateOnLost = false;
  38. [SerializeField] private UnityEvent<string> OnImageFound, OnImageLost;
  39. [SerializeField] [Range(1f, 5f)] private float debugCamMoveSensitivity = 2f;
  40. [SerializeField] [Range(10f, 50f)] private float debugCamTiltSensitivity = 30f;
  41. private Vector3 firstTargetFinalPos, firstTargetCurrentPos;
  42. private Quaternion firstTargetFinalRot, firstTargetCurrentRot;
  43. private Transform dummyCamTransform;
  44. private int debugImageTargetIndex = 0;
  45. private bool isTrackerStopped = false;
  46. [Space][SerializeField] private bool startStopOnEnableDisable = false;
  47. [SerializeField] private bool stopOnDestroy = true;
  48. private Vector3 forward, up, right, pos;
  49. private Vector3 flippedScale = new Vector3(-1, 1, 1);
  50. private Quaternion rot;
  51. IEnumerator Start()
  52. {
  53. if(transform.parent != null) {
  54. Debug.LogError("ImageTracker should be a root transform to receive Javascript messages");
  55. }
  56. if(trackerCam == null)
  57. {
  58. trackerCam = GameObject.FindObjectOfType<ARCamera>();
  59. }
  60. foreach (var i in imageTargets)
  61. {
  62. targets.Add(i.id, i);
  63. i.transform.GetComponent<Renderer>().enabled = false;
  64. i.transform.gameObject.SetActive(false);
  65. serializedIds += i.id;
  66. if (i != imageTargets[imageTargets.Count - 1])
  67. {
  68. serializedIds += ",";
  69. }
  70. }
  71. Debug.Log(serializedIds);
  72. Application.targetFrameRate = (int)this.trackerSettings.targetFrameRate;
  73. #if !UNITY_EDITOR && UNITY_WEBGL
  74. // while (!IsWebGLiTrackerReady())
  75. // {
  76. // Debug.Log("waiting for tracker ready");
  77. // yield return new WaitForSeconds(0.1f);
  78. // }
  79. StartWebGLiTracker(serializedIds, name);
  80. Debug.Log(trackerSettings.Serialize());
  81. SetWebGLiTrackerSettings(trackerSettings.Serialize());
  82. #endif
  83. if( trackerOrigin == TrackerOrigin.FIRST_TARGET_ORIGIN && trackerSettings.maxSimultaneousTargets > 1){
  84. dummyCamTransform = (new GameObject("Dummy Cam Transform")).transform;
  85. }
  86. Debug.Log("tracker started!");
  87. yield break;
  88. }
  89. private void OnEnable(){
  90. if(startStopOnEnableDisable)
  91. StartTracker();
  92. }
  93. private void OnDisable(){
  94. if(startStopOnEnableDisable)
  95. StopTracker();
  96. }
  97. private void OnDestroy()
  98. {
  99. if(stopOnDestroy)
  100. StopTracker();
  101. //SetWebGLiTrackerSettings(trackerSettings.Serialize());
  102. }
  103. public void StartTracker()
  104. {
  105. if(!isTrackerStopped)
  106. return;
  107. Debug.Log("Starting Tracker...");
  108. #if !UNITY_EDITOR && UNITY_WEBGL
  109. if (IsWebGLiTrackerReady())
  110. {
  111. StartWebGLiTracker(serializedIds, name);
  112. }
  113. #endif
  114. isTrackerStopped = false;
  115. }
  116. public void StopTracker()
  117. {
  118. if(isTrackerStopped)
  119. return;
  120. Debug.Log("Stopping Tracker...");
  121. #if !UNITY_EDITOR && UNITY_WEBGL
  122. if (IsWebGLiTrackerReady())
  123. {
  124. StopWebGLiTracker();
  125. }
  126. #endif
  127. isTrackerStopped = true;
  128. }
  129. public bool IsImageTracked(string id)
  130. {
  131. return IsWebGLImageTracked(id);
  132. }
  133. void OnTrackingFound(string id)
  134. {
  135. if (!targets.ContainsKey(id))
  136. return;
  137. targets[id].transform.gameObject.SetActive(true);
  138. if(!trackedIds.Contains(id))
  139. trackedIds.Add(id);
  140. else
  141. Debug.LogError("Found an already tracked id - " + id);
  142. OnImageFound?.Invoke(id);
  143. }
  144. void OnTrackingLost(string id)
  145. {
  146. if (!targets.ContainsKey(id))
  147. return;
  148. targets[id].transform.gameObject.SetActive(false || dontDeactivateOnLost);
  149. var index = trackedIds.FindIndex(t => t == id);
  150. if (index > -1)
  151. {
  152. trackedIds.RemoveAt(index);
  153. }
  154. else{
  155. Debug.LogError("Lost an untracked id - " + id);
  156. }
  157. OnImageLost?.Invoke(id);
  158. }
  159. void OnTrack(string data)
  160. {
  161. ParseData(data);
  162. }
  163. void ParseData(string data)
  164. {
  165. string[] values = data.Split(new char[] { ',' });
  166. string id = values[0];
  167. if (!targets.ContainsKey(id))
  168. return;
  169. forward.x = float.Parse(values[4], System.Globalization.CultureInfo.InvariantCulture);
  170. forward.y = float.Parse(values[5], System.Globalization.CultureInfo.InvariantCulture);
  171. forward.z = float.Parse(values[6], System.Globalization.CultureInfo.InvariantCulture);
  172. up.x = float.Parse(values[7], System.Globalization.CultureInfo.InvariantCulture);
  173. up.y = float.Parse(values[8], System.Globalization.CultureInfo.InvariantCulture);
  174. up.z = float.Parse(values[9], System.Globalization.CultureInfo.InvariantCulture);
  175. right.x = float.Parse(values[10], System.Globalization.CultureInfo.InvariantCulture);
  176. right.y = float.Parse(values[11], System.Globalization.CultureInfo.InvariantCulture);
  177. right.z = float.Parse(values[12], System.Globalization.CultureInfo.InvariantCulture);
  178. rot = Quaternion.LookRotation(forward, up);
  179. pos.x = float.Parse(values[1], System.Globalization.CultureInfo.InvariantCulture);
  180. pos.y = float.Parse(values[2], System.Globalization.CultureInfo.InvariantCulture);
  181. pos.z = float.Parse(values[3], System.Globalization.CultureInfo.InvariantCulture);
  182. var target = targets[id].transform;
  183. if(trackerCam.isFlipped){
  184. rot.eulerAngles = new Vector3(rot.eulerAngles.x, rot.eulerAngles.y * -1, rot.eulerAngles.z * -1);
  185. pos.x *= -1;
  186. target.localScale = flippedScale;
  187. }
  188. else{
  189. target.localScale = Vector3.one;
  190. }
  191. if (trackerOrigin == TrackerOrigin.CAMERA_ORIGIN)
  192. {
  193. if(!trackerSettings.useExtraSmoothing){
  194. target.position = trackerCam.transform.TransformPoint(pos);
  195. target.rotation = trackerCam.transform.rotation * rot;
  196. }
  197. else{
  198. targets[id].targetPos = trackerCam.transform.TransformPoint(pos);
  199. targets[id].targetRot = trackerCam.transform.rotation * rot;
  200. }
  201. }
  202. else if (trackerOrigin == TrackerOrigin.FIRST_TARGET_ORIGIN)
  203. {
  204. if (trackedIds[0] == id)
  205. {
  206. //first target in origin
  207. target.position = Vector3.zero;
  208. target.rotation = Quaternion.identity;
  209. if(!trackerSettings.useExtraSmoothing){
  210. trackerCam.transform.position = Quaternion.Inverse(rot) * -pos;
  211. trackerCam.transform.rotation = Quaternion.Inverse(rot);
  212. }
  213. else{
  214. firstTargetFinalPos = pos;
  215. firstTargetFinalRot = rot;
  216. dummyCamTransform.position = Quaternion.Inverse(rot) * -pos;
  217. dummyCamTransform.rotation = Quaternion.Inverse(rot);
  218. }
  219. }
  220. else
  221. {
  222. //succeeding targets relative to camera
  223. if(!trackerSettings.useExtraSmoothing){
  224. target.position = trackerCam.transform.TransformPoint(pos);
  225. target.rotation = trackerCam.transform.rotation * rot;
  226. }
  227. else{
  228. targets[id].targetPos = dummyCamTransform.TransformPoint(pos);
  229. targets[id].targetRot = dummyCamTransform.transform.rotation * rot;
  230. }
  231. }
  232. }
  233. }
  234. private void Update()
  235. {
  236. if(trackerSettings.useExtraSmoothing){
  237. foreach(var target in imageTargets){
  238. if(target.transform.gameObject.activeSelf){
  239. target.transform.position = Vector3.Lerp(target.transform.position, target.targetPos, Time.deltaTime * trackerSettings.smoothenFactor);
  240. target.transform.rotation = Quaternion.Slerp(target.transform.rotation, target.targetRot, Time.deltaTime * trackerSettings.smoothenFactor);
  241. }
  242. }
  243. if(trackerOrigin == TrackerOrigin.FIRST_TARGET_ORIGIN){
  244. firstTargetCurrentPos = Vector3.Lerp(firstTargetCurrentPos, firstTargetFinalPos, Time.deltaTime * trackerSettings.smoothenFactor);
  245. firstTargetCurrentRot = Quaternion.Slerp(firstTargetCurrentRot, firstTargetFinalRot, Time.deltaTime * trackerSettings.smoothenFactor);
  246. trackerCam.transform.position = Quaternion.Inverse(firstTargetCurrentRot) * -firstTargetCurrentPos;
  247. trackerCam.transform.rotation = Quaternion.Inverse(firstTargetCurrentRot);
  248. }
  249. }
  250. if (trackerSettings.debugMode)
  251. {
  252. if (Input.GetKeyDown(KeyCode.I))
  253. {
  254. if(debugImageTargetIndex >= imageTargets.Count)
  255. {
  256. debugImageTargetIndex = 0;
  257. DebugImageTarget("");
  258. }
  259. else
  260. {
  261. DebugImageTarget(imageTargets[debugImageTargetIndex].id);
  262. debugImageTargetIndex++;
  263. }
  264. }
  265. }
  266. #if UNITY_EDITOR
  267. Update_Debug();
  268. #endif
  269. }
  270. private void Update_Debug()
  271. {
  272. var x_left = Input.GetKey(KeyCode.A);
  273. var x_right = Input.GetKey(KeyCode.D);
  274. var z_forward = Input.GetKey(KeyCode.W); ;
  275. var z_back = Input.GetKey(KeyCode.S); ;
  276. var y_up = Input.GetKey(KeyCode.R);
  277. var y_down = Input.GetKey(KeyCode.F);
  278. float speed = debugCamMoveSensitivity * Time.deltaTime;
  279. float dx = (x_right ? speed : 0) + (x_left ? -speed : 0);
  280. float dy = (y_up ? speed : 0) + (y_down ? -speed : 0);
  281. //float dsca = 1 + (z_forward ? speed : 0) + (z_back ? -speed : 0);
  282. float dz = (z_forward ? speed : 0) + (z_back ? -speed : 0);
  283. var y_rot_left = Input.GetKey(KeyCode.LeftArrow);
  284. var y_rot_right = Input.GetKey(KeyCode.RightArrow);
  285. var x_rot_up = Input.GetKey(KeyCode.UpArrow);
  286. var x_rot_down = Input.GetKey(KeyCode.DownArrow);
  287. var z_rot_cw = Input.GetKey(KeyCode.Comma);
  288. var z_rot_ccw = Input.GetKey(KeyCode.Period);
  289. var angularSpeed = debugCamTiltSensitivity * Time.deltaTime; //degrees per frame
  290. var d_rotx = (x_rot_up ? angularSpeed : 0) + (x_rot_down ? -angularSpeed : 0);
  291. var d_roty = (y_rot_right ? angularSpeed : 0) + (y_rot_left ? -angularSpeed : 0);
  292. var d_rotz = (z_rot_ccw ? angularSpeed : 0) + (z_rot_cw ? -angularSpeed : 0);
  293. var w = trackerCam.transform.rotation.w;
  294. var i = trackerCam.transform.rotation.x;
  295. var j = trackerCam.transform.rotation.y;
  296. var k = trackerCam.transform.rotation.z;
  297. var rot = new Quaternion(i, j, k, w);
  298. var dq = Quaternion.Euler(d_rotx, d_roty, d_rotz);
  299. rot *= dq;
  300. var dp = Vector3.right * dx + Vector3.up * dy + Vector3.forward * dz;
  301. trackerCam.transform.Translate(dp);
  302. trackerCam.transform.rotation = rot;
  303. }
  304. }
  305. }