raymath.d 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import raylib;
  2. import std.math;
  3. mixin template Linear()
  4. {
  5. import std.algorithm : canFind, map;
  6. import std.range : join;
  7. import std.traits : FieldNameTuple;
  8. private static alias T = typeof(this);
  9. static T zero()
  10. {
  11. enum fragment = [FieldNameTuple!T].map!(field => "0.").join(",");
  12. return mixin("T(" ~ fragment ~ ")");
  13. }
  14. static T one()
  15. {
  16. enum fragment = [FieldNameTuple!T].map!(field => "1.").join(",");
  17. return mixin("T(" ~ fragment ~ ")");
  18. }
  19. T opUnary(string op)() if (["+", "-"].canFind(op))
  20. {
  21. enum fragment = [FieldNameTuple!T].map!(field => op ~ field).join(",");
  22. return mixin("T(" ~ fragment ~ ")");
  23. }
  24. T opBinary(string op)(T rhs) if (["+", "-", "*", "/"].canFind(op))
  25. {
  26. enum fragment = [FieldNameTuple!T].map!(field => field ~ op ~ "rhs." ~ field).join(",");
  27. return mixin("T(" ~ fragment ~ ")");
  28. }
  29. T opBinary(string op)(float rhs) if (["+", "-", "*", "/"].canFind(op))
  30. {
  31. enum fragment = [FieldNameTuple!T].map!(field => field ~ op ~ "rhs").join(",");
  32. return mixin("T(" ~ fragment ~ ")");
  33. }
  34. T opBinaryRight(string op)(float lhs) if (["+", "-", "*", "/"].canFind(op))
  35. {
  36. enum fragment = [FieldNameTuple!T].map!(field => "lhs" ~ op ~ field).join(",");
  37. return mixin("T(" ~ fragment ~ ")");
  38. }
  39. }
  40. import std.traits : FieldNameTuple;
  41. import std.algorithm : map;
  42. import std.range : join;
  43. float length(T)(T v)
  44. {
  45. enum fragment = [FieldNameTuple!T].map!(field => "v." ~ field ~ "*" ~ "v." ~ field).join("+");
  46. return mixin("sqrt(" ~ fragment ~ ")");
  47. }
  48. T normalize(T)(T v)
  49. {
  50. return v / v.length;
  51. }
  52. float distance(T)(T lhs, T rhs)
  53. {
  54. return (lhs - rhs).length;
  55. }
  56. T dot(T)(T lhs, T rhs)
  57. {
  58. return lhs * rhs;
  59. }
  60. unittest
  61. {
  62. assert(-Vector2(1, 2) == Vector2(-1, -2));
  63. assert(Vector3(1, 2, 9) + Vector3(3, 4, 9) == Vector3(4, 6, 18));
  64. assert(4.0f - Vector2.zero == Vector2(4, 4));
  65. assert(Vector2.one - 3.0f == Vector2(-2, -2));
  66. assert(Vector2(3, 4).length == 5.0);
  67. }
  68. /// Mix `amount` of `lhs` with `1-amount` of `rhs`
  69. /// `amount` should be between 0 and 1, but can be anything
  70. /// lerp(lhs, rhs, 0) == lhs
  71. /// lerp(lhs, rhs, 1) == rhs
  72. T lerp(T)(T lhs, T rhs, float amount)
  73. {
  74. return lhs + amount * (rhs - lhs);
  75. }
  76. float angle(Vector2 v)
  77. {
  78. return atan2(v.y, v.x);
  79. }
  80. /// Rotate on imaginary plane
  81. Vector2 rotate(Vector2 lhs, Vector2 rhs)
  82. {
  83. return Vector2(lhs.x * rhs.x - lhs.y * rhs.y, lhs.x * rhs.y + lhs.y * rhs.x);
  84. }
  85. Vector2 rotate(Vector2 v, float angle)
  86. {
  87. return Vector2(v.x * cos(angle) - v.y * sin(angle), v.x * sin(angle) + v.y * cos(angle));
  88. }
  89. Vector2 slide(Vector2 v, Vector2 along)
  90. {
  91. return along.normalize * dot(v, along);
  92. }
  93. Bivector2 wedge(Vector2 lhs, Vector2 rhs)
  94. {
  95. return Bivector2(lhs.x * rhs.y - lhs.y * rhs.x);
  96. }
  97. // dfmt off
  98. Bivector3 wedge(Vector3 lhs, Vector3 rhs)
  99. {
  100. return Bivector3(
  101. lhs.y * rhs.z - lhs.z * rhs.y,
  102. lhs.z * rhs.x - lhs.x * rhs.z,
  103. lhs.x * rhs.y - lhs.y * rhs.x,
  104. );
  105. }
  106. Vector3 transform(Vector3 v, Matrix4 mat)
  107. {
  108. with (v) with (mat)
  109. return Vector3(
  110. m0 * x + m4 * y + m8 * z + m12,
  111. m1 * x + m5 * y + m9 * z + m13,
  112. m2 * x + m6 * y + m10 * z + m14
  113. );
  114. }
  115. // dfmt on
  116. Vector3 cross(Vector3 lhs, Vector3 rhs)
  117. {
  118. auto v = wedge(lhs, rhs);
  119. return Vector3(v.yz, v.zx, v.xy);
  120. }
  121. // TODO implement rotor3
  122. // Vector3 rotate(Vector3 v, Rotor3 r) {
  123. // return ;
  124. // }
  125. unittest
  126. {
  127. import std.format;
  128. const v = Vector2.one;
  129. assert(v.length == sqrt(2.0f), "%s %s".format(v,v.length));
  130. }