Vector.hx 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. package h3d;
  2. using hxd.Math;
  3. /**
  4. A 3 floats vector. Everytime a Vector is returned, it means a copy is created.
  5. **/
  6. class VectorImpl #if apicheck implements h2d.impl.PointApi<Vector,Matrix> #end {
  7. public var x : Float;
  8. public var y : Float;
  9. public var z : Float;
  10. // -- gen api
  11. public inline function new( x = 0., y = 0., z = 0. ) {
  12. this.x = x;
  13. this.y = y;
  14. this.z = z;
  15. }
  16. public inline function distance( v : Vector ) {
  17. return Math.sqrt(distanceSq(v));
  18. }
  19. public inline function distanceSq( v : Vector ) {
  20. var dx = v.x - x;
  21. var dy = v.y - y;
  22. var dz = v.z - z;
  23. return dx * dx + dy * dy + dz * dz;
  24. }
  25. public inline function sub( v : Vector ) {
  26. return new Vector(x - v.x, y - v.y, z - v.z);
  27. }
  28. public inline function add( v : Vector ) {
  29. return new Vector(x + v.x, y + v.y, z + v.z);
  30. }
  31. public inline function scaled( v : Float ) {
  32. return new Vector(x * v, y * v, z * v);
  33. }
  34. public inline function equals( v : Vector ) {
  35. return x == v.x && y == v.y && z == v.z;
  36. }
  37. public inline function cross( v : Vector ) {
  38. // note : cross product is left-handed
  39. return new Vector(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
  40. }
  41. public inline function dot( v : Vector ) {
  42. return x * v.x + y * v.y + z * v.z;
  43. }
  44. public inline function lengthSq() {
  45. return x * x + y * y + z * z;
  46. }
  47. public inline function length() {
  48. return lengthSq().sqrt();
  49. }
  50. public inline function normalize() {
  51. var k = lengthSq();
  52. if( k < hxd.Math.EPSILON2 ) k = 0 else k = k.invSqrt();
  53. x *= k;
  54. y *= k;
  55. z *= k;
  56. }
  57. public inline function normalized() {
  58. var k = lengthSq();
  59. if( k < hxd.Math.EPSILON2 ) k = 0 else k = k.invSqrt();
  60. return new Vector(x * k, y * k, z * k);
  61. }
  62. public inline function packNormal() {
  63. x = x * 0.5 + 0.5;
  64. y = y * 0.5 + 0.5;
  65. z = z * 0.5 + 0.5;
  66. }
  67. public inline function unpackNormal() {
  68. x = x * 2.0 - 1.0;
  69. y = y * 2.0 - 1.0;
  70. z = z * 2.0 - 1.0;
  71. }
  72. public inline function normalStrength(strength : Float) {
  73. var k = 1.0 / strength;
  74. x *= k;
  75. y *= k;
  76. normalize();
  77. }
  78. public inline function set(x=0.,y=0.,z=0.) {
  79. this.x = x;
  80. this.y = y;
  81. this.z = z;
  82. }
  83. public inline function load(v : Vector) {
  84. this.x = v.x;
  85. this.y = v.y;
  86. this.z = v.z;
  87. }
  88. public inline function scale( f : Float ) {
  89. x *= f;
  90. y *= f;
  91. z *= f;
  92. }
  93. public inline function lerp( v1 : Vector, v2 : Vector, k : Float ) {
  94. this.x = Math.lerp(v1.x, v2.x, k);
  95. this.y = Math.lerp(v1.y, v2.y, k);
  96. this.z = Math.lerp(v1.z, v2.z, k);
  97. }
  98. public inline function transform( m : Matrix ) {
  99. var px = x * m._11 + y * m._21 + z * m._31 + m._41;
  100. var py = x * m._12 + y * m._22 + z * m._32 + m._42;
  101. var pz = x * m._13 + y * m._23 + z * m._33 + m._43;
  102. x = px;
  103. y = py;
  104. z = pz;
  105. }
  106. public inline function transformed( m : Matrix ) {
  107. var px = x * m._11 + y * m._21 + z * m._31 + m._41;
  108. var py = x * m._12 + y * m._22 + z * m._32 + m._42;
  109. var pz = x * m._13 + y * m._23 + z * m._33 + m._43;
  110. return new Vector(px,py,pz);
  111. }
  112. public inline function transform3x3( m : Matrix ) {
  113. var px = x * m._11 + y * m._21 + z * m._31;
  114. var py = x * m._12 + y * m._22 + z * m._32;
  115. var pz = x * m._13 + y * m._23 + z * m._33;
  116. x = px;
  117. y = py;
  118. z = pz;
  119. }
  120. public inline function transformed3x3( m : Matrix ) {
  121. var px = x * m._11 + y * m._21 + z * m._31;
  122. var py = x * m._12 + y * m._22 + z * m._32;
  123. var pz = x * m._13 + y * m._23 + z * m._33;
  124. return new Vector(px,py,pz);
  125. }
  126. public inline function clone() {
  127. return new Vector(x,y,z);
  128. }
  129. public inline function toVector4() {
  130. return new h3d.Vector4(x,y,z);
  131. }
  132. public inline function to2D() {
  133. return new h2d.col.Point(x,y);
  134. }
  135. public function toString() {
  136. return '{${x.fmt()},${y.fmt()},${z.fmt()}}';
  137. }
  138. // --- end
  139. public inline function reflect( n : Vector ) {
  140. var k = 2 * this.dot(n);
  141. return new Vector(x - k * n.x, y - k * n.y, z - k * n.z);
  142. }
  143. public inline function project( m : Matrix ) {
  144. var px = x * m._11 + y * m._21 + z * m._31 + m._41;
  145. var py = x * m._12 + y * m._22 + z * m._32 + m._42;
  146. var pz = x * m._13 + y * m._23 + z * m._33 + m._43;
  147. var iw = 1 / (x * m._14 + y * m._24 + z * m._34 + m._44);
  148. x = px * iw;
  149. y = py * iw;
  150. z = pz * iw;
  151. }
  152. /// ----- COLOR FUNCTIONS
  153. public var r(get, set) : Float;
  154. public var g(get, set) : Float;
  155. public var b(get, set) : Float;
  156. inline function get_r() return x;
  157. inline function get_g() return y;
  158. inline function get_b() return z;
  159. inline function set_r(v) return x = v;
  160. inline function set_g(v) return y = v;
  161. inline function set_b(v) return z = v;
  162. public inline function setColor( c : Int ) {
  163. r = ((c >> 16) & 0xFF) / 255;
  164. g = ((c >> 8) & 0xFF) / 255;
  165. b = (c & 0xFF) / 255;
  166. }
  167. public function makeColor( hue : Float, saturation : Float = 1., brightness : Float = 0.5 ) {
  168. hue = Math.ufmod(hue, Math.PI * 2);
  169. var c = (1 - Math.abs(2 * brightness - 1)) * saturation;
  170. var x = c * (1 - Math.abs((hue * 3 / Math.PI) % 2. - 1));
  171. var m = brightness - c / 2;
  172. if( hue < Math.PI / 3 ) {
  173. r = c;
  174. g = x;
  175. b = 0;
  176. } else if( hue < Math.PI * 2 / 3 ) {
  177. r = x;
  178. g = c;
  179. b = 0;
  180. } else if( hue < Math.PI ) {
  181. r = 0;
  182. g = c;
  183. b = x;
  184. } else if( hue < Math.PI * 4 / 3 ) {
  185. r = 0;
  186. g = x;
  187. b = c;
  188. } else if( hue < Math.PI * 5 / 3 ) {
  189. r = x;
  190. g = 0;
  191. b = c;
  192. } else {
  193. r = c;
  194. g = 0;
  195. b = x;
  196. }
  197. r += m;
  198. g += m;
  199. b += m;
  200. }
  201. public inline function toColor() {
  202. return 0xFF000000 | (Std.int(r.clamp() * 255 + 0.499) << 16) | (Std.int(g.clamp() * 255 + 0.499) << 8) | Std.int(b.clamp() * 255 + 0.499);
  203. }
  204. public function toColorHSL() {
  205. var max = hxd.Math.max(hxd.Math.max(r, g), b);
  206. var min = hxd.Math.min(hxd.Math.min(r, g), b);
  207. var h, s, l = (max + min) / 2.0;
  208. if(max == min)
  209. h = s = 0.0; // achromatic
  210. else {
  211. var d = max - min;
  212. s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  213. if(max == r)
  214. h = (g - b) / d + (g < b ? 6.0 : 0.0);
  215. else if(max == g)
  216. h = (b - r) / d + 2.0;
  217. else
  218. h = (r - g) / d + 4.0;
  219. h *= Math.PI / 3.0;
  220. }
  221. return new h3d.Vector(h, s, l);
  222. }
  223. public function toColorHSV() {
  224. var max = hxd.Math.max(hxd.Math.max(r, g), b);
  225. var min = hxd.Math.min(hxd.Math.min(r, g), b);
  226. var h, s, v = max;
  227. if(max == min)
  228. h = s = 0.0; // achromatic
  229. else {
  230. var d = max - min;
  231. s = (max + min) > 1.0 ? d / (2 - max - min) : d / (max + min);
  232. if(max == r)
  233. h = (g - b) / d + (g < b ? 6.0 : 0.0);
  234. else if(max == g)
  235. h = (b - r) / d + 2.0;
  236. else
  237. h = (r - g) / d + 4.0;
  238. h *= Math.PI / 3.0;
  239. }
  240. return new h3d.Vector(h, s, v);
  241. }
  242. }
  243. /**
  244. A 3 floats vector. Everytime a Vector is returned, it means a copy is created.
  245. **/
  246. @:forward abstract Vector(VectorImpl) from VectorImpl to VectorImpl {
  247. public inline function new( x = 0., y = 0., z = 0. ) {
  248. this = new VectorImpl(x,y,z);
  249. }
  250. @:op(a - b) public inline function sub(v:Vector) return this.sub(v);
  251. @:op(a + b) public inline function add(v:Vector) return this.add(v);
  252. @:op(a *= b) public inline function transform(m:Matrix) this.transform(m);
  253. @:op(a * b) public inline function transformed(m:Matrix) return this.transformed(m);
  254. // to deprecate at final refactoring
  255. public inline function toPoint() return this.clone();
  256. public inline function toVector() return this.clone();
  257. @:op(a *= b) public inline function scale(v:Float) this.scale(v);
  258. @:op(a * b) public inline function scaled(v:Float) return this.scaled(v);
  259. @:op(a * b) static inline function scaledInv( f : Float, v : Vector ) return v.scaled(f);
  260. public static inline function fromColor( c : Int, scale : Float = 1.0 ) {
  261. var s = scale / 255;
  262. return new Vector(((c>>16)&0xFF)*s,((c>>8)&0xFF)*s,(c&0xFF)*s);
  263. }
  264. public static inline function fromArray(a : Array<Float>) {
  265. var r = new Vector();
  266. if(a.length > 0) r.x = a[0];
  267. if(a.length > 1) r.y = a[1];
  268. if(a.length > 2) r.z = a[2];
  269. return r;
  270. }
  271. }