PointerUIMesh.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. namespace ZenFulcrum.EmbeddedBrowser {
  6. /// <summary>
  7. /// A BrowserUI that tracks pointer interaction through a camera to a mesh of some sort.
  8. /// </summary>
  9. [RequireComponent(typeof(MeshCollider))]
  10. public class PointerUIMesh : PointerUIBase {
  11. protected MeshCollider meshCollider;
  12. protected Dictionary<int, RaycastHit> rayHits = new Dictionary<int, RaycastHit>();
  13. [Tooltip("Which layers should UI rays collide with (and be able to hit)?")]
  14. public LayerMask layerMask = -1;
  15. public override void Awake() {
  16. base.Awake();
  17. meshCollider = GetComponent<MeshCollider>();
  18. }
  19. protected override Vector2 MapPointerToBrowser(Vector2 screenPosition, int pointerId) {
  20. var camera = viewCamera ? viewCamera : Camera.main;
  21. return MapRayToBrowser(camera.ScreenPointToRay(screenPosition), pointerId);
  22. }
  23. protected override Vector2 MapRayToBrowser(Ray worldRay, int pointerId) {
  24. RaycastHit hit;
  25. var rayHit = Physics.Raycast(worldRay, out hit, maxDistance, layerMask);
  26. //store hit data for GetCurrentHitLocation
  27. rayHits[pointerId] = hit;
  28. if (!rayHit || hit.collider.transform != meshCollider.transform) {
  29. //not aimed at it
  30. return new Vector3(float.NaN, float.NaN);
  31. } else {
  32. return hit.textureCoord;
  33. }
  34. }
  35. public override void GetCurrentHitLocation(out Vector3 pos, out Quaternion rot) {
  36. if (currentPointerId == 0) {
  37. //no pointer
  38. pos = new Vector3(float.NaN, float.NaN, float.NaN);
  39. rot = Quaternion.identity;
  40. return;
  41. }
  42. var hitInfo = rayHits[currentPointerId];
  43. //We need to know which way is up, so the cursor has the correct "up".
  44. //There's a couple ways to do this:
  45. //1. Use the barycentric coordinates and some math to figure out what direction the collider's
  46. // v (from the uv) is getting bigger/smaller, then do some math to find out what direction
  47. // that is in world space.
  48. //2. Just use the collider's local orientation's up. This isn't accurate on highly
  49. // distorted meshes, but is much simpler to calculate.
  50. //For now, we use method 2.
  51. var up = hitInfo.collider.transform.up;
  52. pos = hitInfo.point;
  53. rot = Quaternion.LookRotation(-hitInfo.normal, up);
  54. }
  55. }
  56. }