math.color.ts 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. import { DeepImmutable, FloatArray } from '../types';
  2. import { Scalar } from './math.scalar';
  3. import { ToLinearSpace, ToGammaSpace } from './math.constants';
  4. import { ArrayTools } from '../Misc/arrayTools';
  5. import { _TypeStore } from '../Misc/typeStore';
  6. /**
  7. * Class used to hold a RBG color
  8. */
  9. export class Color3 {
  10. /**
  11. * Creates a new Color3 object from red, green, blue values, all between 0 and 1
  12. * @param r defines the red component (between 0 and 1, default is 0)
  13. * @param g defines the green component (between 0 and 1, default is 0)
  14. * @param b defines the blue component (between 0 and 1, default is 0)
  15. */
  16. constructor(
  17. /**
  18. * Defines the red component (between 0 and 1, default is 0)
  19. */
  20. public r: number = 0,
  21. /**
  22. * Defines the green component (between 0 and 1, default is 0)
  23. */
  24. public g: number = 0,
  25. /**
  26. * Defines the blue component (between 0 and 1, default is 0)
  27. */
  28. public b: number = 0) {
  29. }
  30. /**
  31. * Creates a string with the Color3 current values
  32. * @returns the string representation of the Color3 object
  33. */
  34. public toString(): string {
  35. return "{R: " + this.r + " G:" + this.g + " B:" + this.b + "}";
  36. }
  37. /**
  38. * Returns the string "Color3"
  39. * @returns "Color3"
  40. */
  41. public getClassName(): string {
  42. return "Color3";
  43. }
  44. /**
  45. * Compute the Color3 hash code
  46. * @returns an unique number that can be used to hash Color3 objects
  47. */
  48. public getHashCode(): number {
  49. let hash = (this.r * 255) | 0;
  50. hash = (hash * 397) ^ ((this.g * 255) | 0);
  51. hash = (hash * 397) ^ ((this.b * 255) | 0);
  52. return hash;
  53. }
  54. // Operators
  55. /**
  56. * Stores in the given array from the given starting index the red, green, blue values as successive elements
  57. * @param array defines the array where to store the r,g,b components
  58. * @param index defines an optional index in the target array to define where to start storing values
  59. * @returns the current Color3 object
  60. */
  61. public toArray(array: FloatArray, index: number = 0): Color3 {
  62. array[index] = this.r;
  63. array[index + 1] = this.g;
  64. array[index + 2] = this.b;
  65. return this;
  66. }
  67. /**
  68. * Returns a new Color4 object from the current Color3 and the given alpha
  69. * @param alpha defines the alpha component on the new Color4 object (default is 1)
  70. * @returns a new Color4 object
  71. */
  72. public toColor4(alpha: number = 1): Color4 {
  73. return new Color4(this.r, this.g, this.b, alpha);
  74. }
  75. /**
  76. * Returns a new array populated with 3 numeric elements : red, green and blue values
  77. * @returns the new array
  78. */
  79. public asArray(): number[] {
  80. var result = new Array<number>();
  81. this.toArray(result, 0);
  82. return result;
  83. }
  84. /**
  85. * Returns the luminance value
  86. * @returns a float value
  87. */
  88. public toLuminance(): number {
  89. return this.r * 0.3 + this.g * 0.59 + this.b * 0.11;
  90. }
  91. /**
  92. * Multiply each Color3 rgb values by the given Color3 rgb values in a new Color3 object
  93. * @param otherColor defines the second operand
  94. * @returns the new Color3 object
  95. */
  96. public multiply(otherColor: DeepImmutable<Color3>): Color3 {
  97. return new Color3(this.r * otherColor.r, this.g * otherColor.g, this.b * otherColor.b);
  98. }
  99. /**
  100. * Multiply the rgb values of the Color3 and the given Color3 and stores the result in the object "result"
  101. * @param otherColor defines the second operand
  102. * @param result defines the Color3 object where to store the result
  103. * @returns the current Color3
  104. */
  105. public multiplyToRef(otherColor: DeepImmutable<Color3>, result: Color3): Color3 {
  106. result.r = this.r * otherColor.r;
  107. result.g = this.g * otherColor.g;
  108. result.b = this.b * otherColor.b;
  109. return this;
  110. }
  111. /**
  112. * Determines equality between Color3 objects
  113. * @param otherColor defines the second operand
  114. * @returns true if the rgb values are equal to the given ones
  115. */
  116. public equals(otherColor: DeepImmutable<Color3>): boolean {
  117. return otherColor && this.r === otherColor.r && this.g === otherColor.g && this.b === otherColor.b;
  118. }
  119. /**
  120. * Determines equality between the current Color3 object and a set of r,b,g values
  121. * @param r defines the red component to check
  122. * @param g defines the green component to check
  123. * @param b defines the blue component to check
  124. * @returns true if the rgb values are equal to the given ones
  125. */
  126. public equalsFloats(r: number, g: number, b: number): boolean {
  127. return this.r === r && this.g === g && this.b === b;
  128. }
  129. /**
  130. * Multiplies in place each rgb value by scale
  131. * @param scale defines the scaling factor
  132. * @returns the updated Color3
  133. */
  134. public scale(scale: number): Color3 {
  135. return new Color3(this.r * scale, this.g * scale, this.b * scale);
  136. }
  137. /**
  138. * Multiplies the rgb values by scale and stores the result into "result"
  139. * @param scale defines the scaling factor
  140. * @param result defines the Color3 object where to store the result
  141. * @returns the unmodified current Color3
  142. */
  143. public scaleToRef(scale: number, result: Color3): Color3 {
  144. result.r = this.r * scale;
  145. result.g = this.g * scale;
  146. result.b = this.b * scale;
  147. return this;
  148. }
  149. /**
  150. * Scale the current Color3 values by a factor and add the result to a given Color3
  151. * @param scale defines the scale factor
  152. * @param result defines color to store the result into
  153. * @returns the unmodified current Color3
  154. */
  155. public scaleAndAddToRef(scale: number, result: Color3): Color3 {
  156. result.r += this.r * scale;
  157. result.g += this.g * scale;
  158. result.b += this.b * scale;
  159. return this;
  160. }
  161. /**
  162. * Clamps the rgb values by the min and max values and stores the result into "result"
  163. * @param min defines minimum clamping value (default is 0)
  164. * @param max defines maximum clamping value (default is 1)
  165. * @param result defines color to store the result into
  166. * @returns the original Color3
  167. */
  168. public clampToRef(min: number = 0, max: number = 1, result: Color3): Color3 {
  169. result.r = Scalar.Clamp(this.r, min, max);
  170. result.g = Scalar.Clamp(this.g, min, max);
  171. result.b = Scalar.Clamp(this.b, min, max);
  172. return this;
  173. }
  174. /**
  175. * Creates a new Color3 set with the added values of the current Color3 and of the given one
  176. * @param otherColor defines the second operand
  177. * @returns the new Color3
  178. */
  179. public add(otherColor: DeepImmutable<Color3>): Color3 {
  180. return new Color3(this.r + otherColor.r, this.g + otherColor.g, this.b + otherColor.b);
  181. }
  182. /**
  183. * Stores the result of the addition of the current Color3 and given one rgb values into "result"
  184. * @param otherColor defines the second operand
  185. * @param result defines Color3 object to store the result into
  186. * @returns the unmodified current Color3
  187. */
  188. public addToRef(otherColor: DeepImmutable<Color3>, result: Color3): Color3 {
  189. result.r = this.r + otherColor.r;
  190. result.g = this.g + otherColor.g;
  191. result.b = this.b + otherColor.b;
  192. return this;
  193. }
  194. /**
  195. * Returns a new Color3 set with the subtracted values of the given one from the current Color3
  196. * @param otherColor defines the second operand
  197. * @returns the new Color3
  198. */
  199. public subtract(otherColor: DeepImmutable<Color3>): Color3 {
  200. return new Color3(this.r - otherColor.r, this.g - otherColor.g, this.b - otherColor.b);
  201. }
  202. /**
  203. * Stores the result of the subtraction of given one from the current Color3 rgb values into "result"
  204. * @param otherColor defines the second operand
  205. * @param result defines Color3 object to store the result into
  206. * @returns the unmodified current Color3
  207. */
  208. public subtractToRef(otherColor: DeepImmutable<Color3>, result: Color3): Color3 {
  209. result.r = this.r - otherColor.r;
  210. result.g = this.g - otherColor.g;
  211. result.b = this.b - otherColor.b;
  212. return this;
  213. }
  214. /**
  215. * Copy the current object
  216. * @returns a new Color3 copied the current one
  217. */
  218. public clone(): Color3 {
  219. return new Color3(this.r, this.g, this.b);
  220. }
  221. /**
  222. * Copies the rgb values from the source in the current Color3
  223. * @param source defines the source Color3 object
  224. * @returns the updated Color3 object
  225. */
  226. public copyFrom(source: DeepImmutable<Color3>): Color3 {
  227. this.r = source.r;
  228. this.g = source.g;
  229. this.b = source.b;
  230. return this;
  231. }
  232. /**
  233. * Updates the Color3 rgb values from the given floats
  234. * @param r defines the red component to read from
  235. * @param g defines the green component to read from
  236. * @param b defines the blue component to read from
  237. * @returns the current Color3 object
  238. */
  239. public copyFromFloats(r: number, g: number, b: number): Color3 {
  240. this.r = r;
  241. this.g = g;
  242. this.b = b;
  243. return this;
  244. }
  245. /**
  246. * Updates the Color3 rgb values from the given floats
  247. * @param r defines the red component to read from
  248. * @param g defines the green component to read from
  249. * @param b defines the blue component to read from
  250. * @returns the current Color3 object
  251. */
  252. public set(r: number, g: number, b: number): Color3 {
  253. return this.copyFromFloats(r, g, b);
  254. }
  255. /**
  256. * Compute the Color3 hexadecimal code as a string
  257. * @returns a string containing the hexadecimal representation of the Color3 object
  258. */
  259. public toHexString(): string {
  260. var intR = (this.r * 255) | 0;
  261. var intG = (this.g * 255) | 0;
  262. var intB = (this.b * 255) | 0;
  263. return "#" + Scalar.ToHex(intR) + Scalar.ToHex(intG) + Scalar.ToHex(intB);
  264. }
  265. /**
  266. * Computes a new Color3 converted from the current one to linear space
  267. * @returns a new Color3 object
  268. */
  269. public toLinearSpace(): Color3 {
  270. var convertedColor = new Color3();
  271. this.toLinearSpaceToRef(convertedColor);
  272. return convertedColor;
  273. }
  274. /**
  275. * Converts current color in rgb space to HSV values
  276. * @returns a new color3 representing the HSV values
  277. */
  278. public toHSV(): Color3 {
  279. let result = new Color3();
  280. this.toHSVToRef(result);
  281. return result;
  282. }
  283. /**
  284. * Converts current color in rgb space to HSV values
  285. * @param result defines the Color3 where to store the HSV values
  286. */
  287. public toHSVToRef(result: Color3) {
  288. var r = this.r;
  289. var g = this.g;
  290. var b = this.b;
  291. var max = Math.max(r, g, b);
  292. var min = Math.min(r, g, b);
  293. var h = 0;
  294. var s = 0;
  295. var v = max;
  296. var dm = max - min;
  297. if (max !== 0) {
  298. s = dm / max;
  299. }
  300. if (max != min) {
  301. if (max == r) {
  302. h = (g - b) / dm;
  303. if (g < b) {
  304. h += 6;
  305. }
  306. } else if (max == g) {
  307. h = (b - r) / dm + 2;
  308. } else if (max == b) {
  309. h = (r - g) / dm + 4;
  310. }
  311. h *= 60;
  312. }
  313. result.r = h;
  314. result.g = s;
  315. result.b = v;
  316. }
  317. /**
  318. * Converts the Color3 values to linear space and stores the result in "convertedColor"
  319. * @param convertedColor defines the Color3 object where to store the linear space version
  320. * @returns the unmodified Color3
  321. */
  322. public toLinearSpaceToRef(convertedColor: Color3): Color3 {
  323. convertedColor.r = Math.pow(this.r, ToLinearSpace);
  324. convertedColor.g = Math.pow(this.g, ToLinearSpace);
  325. convertedColor.b = Math.pow(this.b, ToLinearSpace);
  326. return this;
  327. }
  328. /**
  329. * Computes a new Color3 converted from the current one to gamma space
  330. * @returns a new Color3 object
  331. */
  332. public toGammaSpace(): Color3 {
  333. var convertedColor = new Color3();
  334. this.toGammaSpaceToRef(convertedColor);
  335. return convertedColor;
  336. }
  337. /**
  338. * Converts the Color3 values to gamma space and stores the result in "convertedColor"
  339. * @param convertedColor defines the Color3 object where to store the gamma space version
  340. * @returns the unmodified Color3
  341. */
  342. public toGammaSpaceToRef(convertedColor: Color3): Color3 {
  343. convertedColor.r = Math.pow(this.r, ToGammaSpace);
  344. convertedColor.g = Math.pow(this.g, ToGammaSpace);
  345. convertedColor.b = Math.pow(this.b, ToGammaSpace);
  346. return this;
  347. }
  348. // Statics
  349. private static _BlackReadOnly = Color3.Black() as DeepImmutable<Color3>;
  350. /**
  351. * Convert Hue, saturation and value to a Color3 (RGB)
  352. * @param hue defines the hue
  353. * @param saturation defines the saturation
  354. * @param value defines the value
  355. * @param result defines the Color3 where to store the RGB values
  356. */
  357. public static HSVtoRGBToRef(hue: number, saturation: number, value: number, result: Color3) {
  358. var chroma = value * saturation;
  359. var h = hue / 60;
  360. var x = chroma * (1 - Math.abs((h % 2) - 1));
  361. var r = 0;
  362. var g = 0;
  363. var b = 0;
  364. if (h >= 0 && h <= 1) {
  365. r = chroma;
  366. g = x;
  367. } else if (h >= 1 && h <= 2) {
  368. r = x;
  369. g = chroma;
  370. } else if (h >= 2 && h <= 3) {
  371. g = chroma;
  372. b = x;
  373. } else if (h >= 3 && h <= 4) {
  374. g = x;
  375. b = chroma;
  376. } else if (h >= 4 && h <= 5) {
  377. r = x;
  378. b = chroma;
  379. } else if (h >= 5 && h <= 6) {
  380. r = chroma;
  381. b = x;
  382. }
  383. var m = value - chroma;
  384. result.set((r + m), (g + m), (b + m));
  385. }
  386. /**
  387. * Creates a new Color3 from the string containing valid hexadecimal values
  388. * @param hex defines a string containing valid hexadecimal values
  389. * @returns a new Color3 object
  390. */
  391. public static FromHexString(hex: string): Color3 {
  392. if (hex.substring(0, 1) !== "#" || hex.length !== 7) {
  393. return new Color3(0, 0, 0);
  394. }
  395. var r = parseInt(hex.substring(1, 3), 16);
  396. var g = parseInt(hex.substring(3, 5), 16);
  397. var b = parseInt(hex.substring(5, 7), 16);
  398. return Color3.FromInts(r, g, b);
  399. }
  400. /**
  401. * Creates a new Color3 from the starting index of the given array
  402. * @param array defines the source array
  403. * @param offset defines an offset in the source array
  404. * @returns a new Color3 object
  405. */
  406. public static FromArray(array: DeepImmutable<ArrayLike<number>>, offset: number = 0): Color3 {
  407. return new Color3(array[offset], array[offset + 1], array[offset + 2]);
  408. }
  409. /**
  410. * Creates a new Color3 from integer values (< 256)
  411. * @param r defines the red component to read from (value between 0 and 255)
  412. * @param g defines the green component to read from (value between 0 and 255)
  413. * @param b defines the blue component to read from (value between 0 and 255)
  414. * @returns a new Color3 object
  415. */
  416. public static FromInts(r: number, g: number, b: number): Color3 {
  417. return new Color3(r / 255.0, g / 255.0, b / 255.0);
  418. }
  419. /**
  420. * Creates a new Color3 with values linearly interpolated of "amount" between the start Color3 and the end Color3
  421. * @param start defines the start Color3 value
  422. * @param end defines the end Color3 value
  423. * @param amount defines the gradient value between start and end
  424. * @returns a new Color3 object
  425. */
  426. public static Lerp(start: DeepImmutable<Color3>, end: DeepImmutable<Color3>, amount: number): Color3 {
  427. var result = new Color3(0.0, 0.0, 0.0);
  428. Color3.LerpToRef(start, end, amount, result);
  429. return result;
  430. }
  431. /**
  432. * Creates a new Color3 with values linearly interpolated of "amount" between the start Color3 and the end Color3
  433. * @param left defines the start value
  434. * @param right defines the end value
  435. * @param amount defines the gradient factor
  436. * @param result defines the Color3 object where to store the result
  437. */
  438. public static LerpToRef(left: DeepImmutable<Color3>, right: DeepImmutable<Color3>, amount: number, result: Color3): void {
  439. result.r = left.r + ((right.r - left.r) * amount);
  440. result.g = left.g + ((right.g - left.g) * amount);
  441. result.b = left.b + ((right.b - left.b) * amount);
  442. }
  443. /**
  444. * Returns a Color3 value containing a red color
  445. * @returns a new Color3 object
  446. */
  447. public static Red(): Color3 { return new Color3(1, 0, 0); }
  448. /**
  449. * Returns a Color3 value containing a green color
  450. * @returns a new Color3 object
  451. */
  452. public static Green(): Color3 { return new Color3(0, 1, 0); }
  453. /**
  454. * Returns a Color3 value containing a blue color
  455. * @returns a new Color3 object
  456. */
  457. public static Blue(): Color3 { return new Color3(0, 0, 1); }
  458. /**
  459. * Returns a Color3 value containing a black color
  460. * @returns a new Color3 object
  461. */
  462. public static Black(): Color3 { return new Color3(0, 0, 0); }
  463. /**
  464. * Gets a Color3 value containing a black color that must not be updated
  465. */
  466. public static get BlackReadOnly(): DeepImmutable<Color3> {
  467. return Color3._BlackReadOnly;
  468. }
  469. /**
  470. * Returns a Color3 value containing a white color
  471. * @returns a new Color3 object
  472. */
  473. public static White(): Color3 { return new Color3(1, 1, 1); }
  474. /**
  475. * Returns a Color3 value containing a purple color
  476. * @returns a new Color3 object
  477. */
  478. public static Purple(): Color3 { return new Color3(0.5, 0, 0.5); }
  479. /**
  480. * Returns a Color3 value containing a magenta color
  481. * @returns a new Color3 object
  482. */
  483. public static Magenta(): Color3 { return new Color3(1, 0, 1); }
  484. /**
  485. * Returns a Color3 value containing a yellow color
  486. * @returns a new Color3 object
  487. */
  488. public static Yellow(): Color3 { return new Color3(1, 1, 0); }
  489. /**
  490. * Returns a Color3 value containing a gray color
  491. * @returns a new Color3 object
  492. */
  493. public static Gray(): Color3 { return new Color3(0.5, 0.5, 0.5); }
  494. /**
  495. * Returns a Color3 value containing a teal color
  496. * @returns a new Color3 object
  497. */
  498. public static Teal(): Color3 { return new Color3(0, 1.0, 1.0); }
  499. /**
  500. * Returns a Color3 value containing a random color
  501. * @returns a new Color3 object
  502. */
  503. public static Random(): Color3 { return new Color3(Math.random(), Math.random(), Math.random()); }
  504. }
  505. /**
  506. * Class used to hold a RBGA color
  507. */
  508. export class Color4 {
  509. /**
  510. * Creates a new Color4 object from red, green, blue values, all between 0 and 1
  511. * @param r defines the red component (between 0 and 1, default is 0)
  512. * @param g defines the green component (between 0 and 1, default is 0)
  513. * @param b defines the blue component (between 0 and 1, default is 0)
  514. * @param a defines the alpha component (between 0 and 1, default is 1)
  515. */
  516. constructor(
  517. /**
  518. * Defines the red component (between 0 and 1, default is 0)
  519. */
  520. public r: number = 0,
  521. /**
  522. * Defines the green component (between 0 and 1, default is 0)
  523. */
  524. public g: number = 0,
  525. /**
  526. * Defines the blue component (between 0 and 1, default is 0)
  527. */
  528. public b: number = 0,
  529. /**
  530. * Defines the alpha component (between 0 and 1, default is 1)
  531. */
  532. public a: number = 1) {
  533. }
  534. // Operators
  535. /**
  536. * Adds in place the given Color4 values to the current Color4 object
  537. * @param right defines the second operand
  538. * @returns the current updated Color4 object
  539. */
  540. public addInPlace(right: DeepImmutable<Color4>): Color4 {
  541. this.r += right.r;
  542. this.g += right.g;
  543. this.b += right.b;
  544. this.a += right.a;
  545. return this;
  546. }
  547. /**
  548. * Creates a new array populated with 4 numeric elements : red, green, blue, alpha values
  549. * @returns the new array
  550. */
  551. public asArray(): number[] {
  552. var result = new Array<number>();
  553. this.toArray(result, 0);
  554. return result;
  555. }
  556. /**
  557. * Stores from the starting index in the given array the Color4 successive values
  558. * @param array defines the array where to store the r,g,b components
  559. * @param index defines an optional index in the target array to define where to start storing values
  560. * @returns the current Color4 object
  561. */
  562. public toArray(array: number[], index: number = 0): Color4 {
  563. array[index] = this.r;
  564. array[index + 1] = this.g;
  565. array[index + 2] = this.b;
  566. array[index + 3] = this.a;
  567. return this;
  568. }
  569. /**
  570. * Determines equality between Color4 objects
  571. * @param otherColor defines the second operand
  572. * @returns true if the rgba values are equal to the given ones
  573. */
  574. public equals(otherColor: DeepImmutable<Color4>): boolean {
  575. return otherColor && this.r === otherColor.r && this.g === otherColor.g && this.b === otherColor.b && this.a === otherColor.a;
  576. }
  577. /**
  578. * Creates a new Color4 set with the added values of the current Color4 and of the given one
  579. * @param right defines the second operand
  580. * @returns a new Color4 object
  581. */
  582. public add(right: DeepImmutable<Color4>): Color4 {
  583. return new Color4(this.r + right.r, this.g + right.g, this.b + right.b, this.a + right.a);
  584. }
  585. /**
  586. * Creates a new Color4 set with the subtracted values of the given one from the current Color4
  587. * @param right defines the second operand
  588. * @returns a new Color4 object
  589. */
  590. public subtract(right: DeepImmutable<Color4>): Color4 {
  591. return new Color4(this.r - right.r, this.g - right.g, this.b - right.b, this.a - right.a);
  592. }
  593. /**
  594. * Subtracts the given ones from the current Color4 values and stores the results in "result"
  595. * @param right defines the second operand
  596. * @param result defines the Color4 object where to store the result
  597. * @returns the current Color4 object
  598. */
  599. public subtractToRef(right: DeepImmutable<Color4>, result: Color4): Color4 {
  600. result.r = this.r - right.r;
  601. result.g = this.g - right.g;
  602. result.b = this.b - right.b;
  603. result.a = this.a - right.a;
  604. return this;
  605. }
  606. /**
  607. * Creates a new Color4 with the current Color4 values multiplied by scale
  608. * @param scale defines the scaling factor to apply
  609. * @returns a new Color4 object
  610. */
  611. public scale(scale: number): Color4 {
  612. return new Color4(this.r * scale, this.g * scale, this.b * scale, this.a * scale);
  613. }
  614. /**
  615. * Multiplies the current Color4 values by scale and stores the result in "result"
  616. * @param scale defines the scaling factor to apply
  617. * @param result defines the Color4 object where to store the result
  618. * @returns the current unmodified Color4
  619. */
  620. public scaleToRef(scale: number, result: Color4): Color4 {
  621. result.r = this.r * scale;
  622. result.g = this.g * scale;
  623. result.b = this.b * scale;
  624. result.a = this.a * scale;
  625. return this;
  626. }
  627. /**
  628. * Scale the current Color4 values by a factor and add the result to a given Color4
  629. * @param scale defines the scale factor
  630. * @param result defines the Color4 object where to store the result
  631. * @returns the unmodified current Color4
  632. */
  633. public scaleAndAddToRef(scale: number, result: Color4): Color4 {
  634. result.r += this.r * scale;
  635. result.g += this.g * scale;
  636. result.b += this.b * scale;
  637. result.a += this.a * scale;
  638. return this;
  639. }
  640. /**
  641. * Clamps the rgb values by the min and max values and stores the result into "result"
  642. * @param min defines minimum clamping value (default is 0)
  643. * @param max defines maximum clamping value (default is 1)
  644. * @param result defines color to store the result into.
  645. * @returns the cuurent Color4
  646. */
  647. public clampToRef(min: number = 0, max: number = 1, result: Color4): Color4 {
  648. result.r = Scalar.Clamp(this.r, min, max);
  649. result.g = Scalar.Clamp(this.g, min, max);
  650. result.b = Scalar.Clamp(this.b, min, max);
  651. result.a = Scalar.Clamp(this.a, min, max);
  652. return this;
  653. }
  654. /**
  655. * Multipy an Color4 value by another and return a new Color4 object
  656. * @param color defines the Color4 value to multiply by
  657. * @returns a new Color4 object
  658. */
  659. public multiply(color: Color4): Color4 {
  660. return new Color4(this.r * color.r, this.g * color.g, this.b * color.b, this.a * color.a);
  661. }
  662. /**
  663. * Multipy a Color4 value by another and push the result in a reference value
  664. * @param color defines the Color4 value to multiply by
  665. * @param result defines the Color4 to fill the result in
  666. * @returns the result Color4
  667. */
  668. public multiplyToRef(color: Color4, result: Color4): Color4 {
  669. result.r = this.r * color.r;
  670. result.g = this.g * color.g;
  671. result.b = this.b * color.b;
  672. result.a = this.a * color.a;
  673. return result;
  674. }
  675. /**
  676. * Creates a string with the Color4 current values
  677. * @returns the string representation of the Color4 object
  678. */
  679. public toString(): string {
  680. return "{R: " + this.r + " G:" + this.g + " B:" + this.b + " A:" + this.a + "}";
  681. }
  682. /**
  683. * Returns the string "Color4"
  684. * @returns "Color4"
  685. */
  686. public getClassName(): string {
  687. return "Color4";
  688. }
  689. /**
  690. * Compute the Color4 hash code
  691. * @returns an unique number that can be used to hash Color4 objects
  692. */
  693. public getHashCode(): number {
  694. let hash = (this.r * 255) | 0;
  695. hash = (hash * 397) ^ ((this.g * 255) | 0);
  696. hash = (hash * 397) ^ ((this.b * 255) | 0);
  697. hash = (hash * 397) ^ ((this.a * 255) | 0);
  698. return hash;
  699. }
  700. /**
  701. * Creates a new Color4 copied from the current one
  702. * @returns a new Color4 object
  703. */
  704. public clone(): Color4 {
  705. return new Color4(this.r, this.g, this.b, this.a);
  706. }
  707. /**
  708. * Copies the given Color4 values into the current one
  709. * @param source defines the source Color4 object
  710. * @returns the current updated Color4 object
  711. */
  712. public copyFrom(source: Color4): Color4 {
  713. this.r = source.r;
  714. this.g = source.g;
  715. this.b = source.b;
  716. this.a = source.a;
  717. return this;
  718. }
  719. /**
  720. * Copies the given float values into the current one
  721. * @param r defines the red component to read from
  722. * @param g defines the green component to read from
  723. * @param b defines the blue component to read from
  724. * @param a defines the alpha component to read from
  725. * @returns the current updated Color4 object
  726. */
  727. public copyFromFloats(r: number, g: number, b: number, a: number): Color4 {
  728. this.r = r;
  729. this.g = g;
  730. this.b = b;
  731. this.a = a;
  732. return this;
  733. }
  734. /**
  735. * Copies the given float values into the current one
  736. * @param r defines the red component to read from
  737. * @param g defines the green component to read from
  738. * @param b defines the blue component to read from
  739. * @param a defines the alpha component to read from
  740. * @returns the current updated Color4 object
  741. */
  742. public set(r: number, g: number, b: number, a: number): Color4 {
  743. return this.copyFromFloats(r, g, b, a);
  744. }
  745. /**
  746. * Compute the Color4 hexadecimal code as a string
  747. * @param returnAsColor3 defines if the string should only contains RGB values (off by default)
  748. * @returns a string containing the hexadecimal representation of the Color4 object
  749. */
  750. public toHexString(returnAsColor3 = false): string {
  751. var intR = (this.r * 255) | 0;
  752. var intG = (this.g * 255) | 0;
  753. var intB = (this.b * 255) | 0;
  754. if (returnAsColor3) {
  755. return "#" + Scalar.ToHex(intR) + Scalar.ToHex(intG) + Scalar.ToHex(intB);
  756. }
  757. var intA = (this.a * 255) | 0;
  758. return "#" + Scalar.ToHex(intR) + Scalar.ToHex(intG) + Scalar.ToHex(intB) + Scalar.ToHex(intA);
  759. }
  760. /**
  761. * Computes a new Color4 converted from the current one to linear space
  762. * @returns a new Color4 object
  763. */
  764. public toLinearSpace(): Color4 {
  765. var convertedColor = new Color4();
  766. this.toLinearSpaceToRef(convertedColor);
  767. return convertedColor;
  768. }
  769. /**
  770. * Converts the Color4 values to linear space and stores the result in "convertedColor"
  771. * @param convertedColor defines the Color4 object where to store the linear space version
  772. * @returns the unmodified Color4
  773. */
  774. public toLinearSpaceToRef(convertedColor: Color4): Color4 {
  775. convertedColor.r = Math.pow(this.r, ToLinearSpace);
  776. convertedColor.g = Math.pow(this.g, ToLinearSpace);
  777. convertedColor.b = Math.pow(this.b, ToLinearSpace);
  778. convertedColor.a = this.a;
  779. return this;
  780. }
  781. /**
  782. * Computes a new Color4 converted from the current one to gamma space
  783. * @returns a new Color4 object
  784. */
  785. public toGammaSpace(): Color4 {
  786. var convertedColor = new Color4();
  787. this.toGammaSpaceToRef(convertedColor);
  788. return convertedColor;
  789. }
  790. /**
  791. * Converts the Color4 values to gamma space and stores the result in "convertedColor"
  792. * @param convertedColor defines the Color4 object where to store the gamma space version
  793. * @returns the unmodified Color4
  794. */
  795. public toGammaSpaceToRef(convertedColor: Color4): Color4 {
  796. convertedColor.r = Math.pow(this.r, ToGammaSpace);
  797. convertedColor.g = Math.pow(this.g, ToGammaSpace);
  798. convertedColor.b = Math.pow(this.b, ToGammaSpace);
  799. convertedColor.a = this.a;
  800. return this;
  801. }
  802. // Statics
  803. /**
  804. * Creates a new Color4 from the string containing valid hexadecimal values
  805. * @param hex defines a string containing valid hexadecimal values
  806. * @returns a new Color4 object
  807. */
  808. public static FromHexString(hex: string): Color4 {
  809. if (hex.substring(0, 1) !== "#" || hex.length !== 9) {
  810. return new Color4(0.0, 0.0, 0.0, 0.0);
  811. }
  812. var r = parseInt(hex.substring(1, 3), 16);
  813. var g = parseInt(hex.substring(3, 5), 16);
  814. var b = parseInt(hex.substring(5, 7), 16);
  815. var a = parseInt(hex.substring(7, 9), 16);
  816. return Color4.FromInts(r, g, b, a);
  817. }
  818. /**
  819. * Creates a new Color4 object set with the linearly interpolated values of "amount" between the left Color4 object and the right Color4 object
  820. * @param left defines the start value
  821. * @param right defines the end value
  822. * @param amount defines the gradient factor
  823. * @returns a new Color4 object
  824. */
  825. public static Lerp(left: DeepImmutable<Color4>, right: DeepImmutable<Color4>, amount: number): Color4 {
  826. var result = new Color4(0.0, 0.0, 0.0, 0.0);
  827. Color4.LerpToRef(left, right, amount, result);
  828. return result;
  829. }
  830. /**
  831. * Set the given "result" with the linearly interpolated values of "amount" between the left Color4 object and the right Color4 object
  832. * @param left defines the start value
  833. * @param right defines the end value
  834. * @param amount defines the gradient factor
  835. * @param result defines the Color4 object where to store data
  836. */
  837. public static LerpToRef(left: DeepImmutable<Color4>, right: DeepImmutable<Color4>, amount: number, result: Color4): void {
  838. result.r = left.r + (right.r - left.r) * amount;
  839. result.g = left.g + (right.g - left.g) * amount;
  840. result.b = left.b + (right.b - left.b) * amount;
  841. result.a = left.a + (right.a - left.a) * amount;
  842. }
  843. /**
  844. * Creates a new Color4 from a Color3 and an alpha value
  845. * @param color3 defines the source Color3 to read from
  846. * @param alpha defines the alpha component (1.0 by default)
  847. * @returns a new Color4 object
  848. */
  849. public static FromColor3(color3: DeepImmutable<Color3>, alpha: number = 1.0): Color4 {
  850. return new Color4(color3.r, color3.g, color3.b, alpha);
  851. }
  852. /**
  853. * Creates a new Color4 from the starting index element of the given array
  854. * @param array defines the source array to read from
  855. * @param offset defines the offset in the source array
  856. * @returns a new Color4 object
  857. */
  858. public static FromArray(array: DeepImmutable<ArrayLike<number>>, offset: number = 0): Color4 {
  859. return new Color4(array[offset], array[offset + 1], array[offset + 2], array[offset + 3]);
  860. }
  861. /**
  862. * Creates a new Color3 from integer values (< 256)
  863. * @param r defines the red component to read from (value between 0 and 255)
  864. * @param g defines the green component to read from (value between 0 and 255)
  865. * @param b defines the blue component to read from (value between 0 and 255)
  866. * @param a defines the alpha component to read from (value between 0 and 255)
  867. * @returns a new Color3 object
  868. */
  869. public static FromInts(r: number, g: number, b: number, a: number): Color4 {
  870. return new Color4(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
  871. }
  872. /**
  873. * Check the content of a given array and convert it to an array containing RGBA data
  874. * If the original array was already containing count * 4 values then it is returned directly
  875. * @param colors defines the array to check
  876. * @param count defines the number of RGBA data to expect
  877. * @returns an array containing count * 4 values (RGBA)
  878. */
  879. public static CheckColors4(colors: number[], count: number): number[] {
  880. // Check if color3 was used
  881. if (colors.length === count * 3) {
  882. var colors4 = [];
  883. for (var index = 0; index < colors.length; index += 3) {
  884. var newIndex = (index / 3) * 4;
  885. colors4[newIndex] = colors[index];
  886. colors4[newIndex + 1] = colors[index + 1];
  887. colors4[newIndex + 2] = colors[index + 2];
  888. colors4[newIndex + 3] = 1.0;
  889. }
  890. return colors4;
  891. }
  892. return colors;
  893. }
  894. }
  895. /**
  896. * @hidden
  897. */
  898. export class TmpColors {
  899. public static Color3: Color3[] = ArrayTools.BuildArray(3, Color3.Black);
  900. public static Color4: Color4[] = ArrayTools.BuildArray(3, () => new Color4(0, 0, 0, 0));
  901. }
  902. _TypeStore.RegisteredTypes["BABYLON.Color3"] = Color3;
  903. _TypeStore.RegisteredTypes["BABYLON.Color4"] = Color4;