LogicField.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using UnityEngine;
  2. public class LogicField
  3. {
  4. public Vector3 Position { get; private set;}
  5. public Vector3 Forward { get; private set;}
  6. public Vector3 Up { get; private set;}
  7. public Vector3 Right { get; private set;}
  8. public Vector3 Size {get; private set;}
  9. Vector3 mLocalMin;
  10. Vector3 mLocalMax;
  11. Matrix4x4 mLocalToWorld;
  12. Matrix4x4 mWorldToLocal;
  13. public LogicField(Vector3 pos, Vector3 size, Vector3 forward)
  14. {
  15. Position = pos;
  16. Size = size;
  17. Forward = forward.SetY (0).normalized;
  18. Up = Vector3.up;
  19. Right = Vector3.Cross (Up, Forward);
  20. mLocalMin = -0.5f * Size;
  21. mLocalMax = 0.5f * Size;
  22. mLocalToWorld.SetColumn (0, Right);
  23. mLocalToWorld.SetColumn (1, Up);
  24. mLocalToWorld.SetColumn (2, Forward);
  25. mLocalToWorld.SetColumn (3, new Vector4(Position.x, Position.y, Position.z, 1));
  26. mWorldToLocal = mLocalToWorld.inverse;
  27. }
  28. public bool IsInField(Vector3 pos)
  29. {
  30. Vector3 v = InverseTransformPoint(pos);
  31. return v.IsInRange (mLocalMin, mLocalMax);
  32. }
  33. public Vector3 FixMove(Vector3 from, Vector3 to)
  34. {
  35. Vector3 vfrom = InverseTransformPoint (from);
  36. if (!vfrom.IsInRange (mLocalMin, mLocalMax))
  37. return to;
  38. Vector3 vto = InverseTransformPoint(to);
  39. if (vto.IsInRange(mLocalMin, mLocalMax))
  40. return to;
  41. return TransformPoint(LocalCrossPosition(vfrom, vto));
  42. }
  43. public Vector3 ProjectGround(Vector3 pos)
  44. {
  45. return TransformPoint (InverseTransformPoint (pos).SetY (mLocalMin.y));
  46. }
  47. public Vector3 Closest(Vector3 pos)
  48. {
  49. Vector3 v = InverseTransformPoint(pos);
  50. v = Vector3.Min(v, mLocalMax);
  51. v = Vector3.Max(v, mLocalMin);
  52. return TransformPoint(v);
  53. }
  54. public float PositionHeight(Vector3 pos)
  55. {
  56. return InverseTransformPoint(pos).y - mLocalMin.y;
  57. }
  58. public Vector3 TransformPoint(Vector3 v)
  59. {
  60. return mLocalToWorld.MultiplyPoint(v);
  61. }
  62. public Vector3 InverseTransformPoint(Vector3 v)
  63. {
  64. return mWorldToLocal.MultiplyPoint(v);
  65. }
  66. public Vector3 TransformDirection(Vector3 d)
  67. {
  68. return mLocalToWorld.MultiplyVector(d);
  69. }
  70. public Vector3 InverseTransformDirection(Vector3 d)
  71. {
  72. return mWorldToLocal.MultiplyVector(d);
  73. }
  74. Vector3 LocalCrossPosition(Vector3 localInside, Vector3 localOutside)
  75. {
  76. float tx = 1f, ty = 1f, tz = 1f;
  77. const float diff = 1e-3f;
  78. if (localOutside.x < mLocalMin.x - diff)
  79. tx = (mLocalMin.x - localInside.x) / (localOutside.x - localInside.x);
  80. else if (localOutside.x > mLocalMax.x + diff)
  81. tx = (mLocalMax.x - localInside.x) / (localOutside.x - localInside.x);
  82. if (localOutside.y < mLocalMin.y - diff)
  83. ty = (mLocalMin.y - localInside.y) / (localOutside.y - localInside.y);
  84. else if (localOutside.y > mLocalMax.y + diff)
  85. ty = (mLocalMax.y - localInside.y) / (localOutside.y - localInside.y);
  86. if (localOutside.z < mLocalMin.z - diff)
  87. tz = (mLocalMin.z - localInside.z) / (localOutside.z - localInside.z);
  88. else if (localOutside.z > mLocalMax.z + diff)
  89. tz = (mLocalMax.z - localInside.z) / (localOutside.z - localInside.z);
  90. float t = Mathf.Min(tx, ty, tz);
  91. if (t >= 1 - 1e-3f)
  92. return localOutside.ClampPosition(mLocalMin, mLocalMax);
  93. else
  94. return Vector3.Lerp(localInside, localOutside, t);
  95. }
  96. }