oxygengine_composite_renderer/
math.rs

1use core::{Ignite, Scalar};
2use serde::{Deserialize, Serialize};
3use std::ops::{Add, Div, Mul, Neg, Not, Sub};
4
5#[inline]
6pub fn lerp(a: Scalar, b: Scalar, f: Scalar) -> Scalar {
7    (b - a) * f + a
8}
9
10#[inline]
11pub fn lerp_clamped(a: Scalar, b: Scalar, f: Scalar) -> Scalar {
12    lerp(a, b, f.max(0.0).min(1.0))
13}
14
15#[inline]
16pub fn unlerp(a: Scalar, b: Scalar, v: Scalar) -> Scalar {
17    (v - a) / (b - a)
18}
19
20#[derive(Ignite, Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
21pub struct Mat2d(pub [Scalar; 6]);
22
23impl Default for Mat2d {
24    fn default() -> Self {
25        Self([1.0, 0.0, 0.0, 1.0, 0.0, 0.0])
26    }
27}
28
29impl Mat2d {
30    pub fn new(cells: [Scalar; 6]) -> Self {
31        Self(cells)
32    }
33
34    pub fn new_complex(translation: Vec2, rotation: Scalar, scale: Vec2) -> Self {
35        let t = Self::translation(translation);
36        let r = Self::rotation(rotation);
37        let s = Self::scale(scale);
38        t * r * s
39    }
40
41    pub fn translation(value: Vec2) -> Self {
42        Self([1.0, 0.0, 0.0, 1.0, value.x, value.y])
43    }
44
45    pub fn rotation(value: Scalar) -> Self {
46        let (sin, cos) = value.sin_cos();
47        Self([cos, sin, -sin, cos, 0.0, 0.0])
48    }
49
50    pub fn scale(value: Vec2) -> Self {
51        Self([value.x, 0.0, 0.0, value.y, 0.0, 0.0])
52    }
53
54    pub fn skew(value: Vec2) -> Self {
55        Self([1.0, value.y.tan(), value.x.tan(), 1.0, 0.0, 0.0])
56    }
57
58    pub fn inverse(self) -> Option<Self> {
59        !self
60    }
61}
62
63impl Mul for Mat2d {
64    type Output = Self;
65
66    fn mul(self, other: Self) -> Self {
67        Self([
68            self.0[0] * other.0[0] + self.0[2] * other.0[1],
69            self.0[1] * other.0[0] + self.0[3] * other.0[1],
70            self.0[0] * other.0[2] + self.0[2] * other.0[3],
71            self.0[1] * other.0[2] + self.0[3] * other.0[3],
72            self.0[0] * other.0[4] + self.0[2] * other.0[5] + self.0[4],
73            self.0[1] * other.0[4] + self.0[3] * other.0[5] + self.0[5],
74        ])
75    }
76}
77
78impl Mul<Vec2> for Mat2d {
79    type Output = Vec2;
80
81    fn mul(self, other: Vec2) -> Vec2 {
82        other * self
83    }
84}
85
86impl Not for Mat2d {
87    type Output = Option<Self>;
88
89    fn not(self) -> Option<Self> {
90        let det = self.0[0] * self.0[3] - self.0[1] * self.0[2];
91        if det == 0.0 {
92            return None;
93        }
94        let det = 1.0 / det;
95        Some(Self([
96            self.0[3] * det,
97            -self.0[1] * det,
98            -self.0[2] * det,
99            self.0[0] * det,
100            (self.0[2] * self.0[5] - self.0[3] * self.0[4]) * det,
101            (self.0[1] * self.0[4] - self.0[0] * self.0[5]) * det,
102        ]))
103    }
104}
105
106impl From<[Scalar; 6]> for Mat2d {
107    fn from(v: [Scalar; 6]) -> Self {
108        Self(v)
109    }
110}
111
112impl From<Mat2d> for [Scalar; 6] {
113    fn from(v: Mat2d) -> Self {
114        v.0
115    }
116}
117
118impl From<(Scalar, Scalar, Scalar, Scalar, Scalar, Scalar)> for Mat2d {
119    fn from(v: (Scalar, Scalar, Scalar, Scalar, Scalar, Scalar)) -> Self {
120        Self([v.0, v.1, v.2, v.3, v.4, v.5])
121    }
122}
123
124impl From<Mat2d> for (Scalar, Scalar, Scalar, Scalar, Scalar, Scalar) {
125    fn from(v: Mat2d) -> Self {
126        (v.0[0], v.0[1], v.0[2], v.0[3], v.0[4], v.0[5])
127    }
128}
129
130#[derive(Ignite, Debug, Default, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
131pub struct Color {
132    pub r: u8,
133    pub g: u8,
134    pub b: u8,
135    pub a: u8,
136}
137
138impl Color {
139    pub fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
140        Self { r, g, b, a }
141    }
142
143    pub fn rgb(r: u8, g: u8, b: u8) -> Self {
144        Self { r, g, b, a: 255 }
145    }
146
147    pub fn transparent() -> Self {
148        Self {
149            r: 0,
150            g: 0,
151            b: 0,
152            a: 0,
153        }
154    }
155
156    pub fn white() -> Self {
157        Self {
158            r: 255,
159            g: 255,
160            b: 255,
161            a: 255,
162        }
163    }
164
165    pub fn black() -> Self {
166        Self {
167            r: 0,
168            g: 0,
169            b: 0,
170            a: 255,
171        }
172    }
173
174    pub fn red() -> Self {
175        Self {
176            r: 255,
177            g: 0,
178            b: 0,
179            a: 255,
180        }
181    }
182
183    pub fn green() -> Self {
184        Self {
185            r: 0,
186            g: 255,
187            b: 0,
188            a: 255,
189        }
190    }
191
192    pub fn blue() -> Self {
193        Self {
194            r: 0,
195            g: 0,
196            b: 255,
197            a: 255,
198        }
199    }
200
201    pub fn yellow() -> Self {
202        Self {
203            r: 255,
204            g: 255,
205            b: 0,
206            a: 255,
207        }
208    }
209
210    pub fn cyan() -> Self {
211        Self {
212            r: 0,
213            g: 255,
214            b: 255,
215            a: 255,
216        }
217    }
218
219    pub fn magenta() -> Self {
220        Self {
221            r: 255,
222            g: 0,
223            b: 255,
224            a: 255,
225        }
226    }
227
228    pub fn r(mut self, value: u8) -> Self {
229        self.r = value;
230        self
231    }
232
233    pub fn g(mut self, value: u8) -> Self {
234        self.g = value;
235        self
236    }
237
238    pub fn b(mut self, value: u8) -> Self {
239        self.b = value;
240        self
241    }
242
243    pub fn a(mut self, value: u8) -> Self {
244        self.a = value;
245        self
246    }
247}
248
249impl From<(u8, u8, u8, u8)> for Color {
250    fn from(value: (u8, u8, u8, u8)) -> Self {
251        Self {
252            r: value.0,
253            g: value.1,
254            b: value.2,
255            a: value.3,
256        }
257    }
258}
259
260impl From<[u8; 4]> for Color {
261    fn from(value: [u8; 4]) -> Self {
262        Self {
263            r: value[0],
264            g: value[1],
265            b: value[2],
266            a: value[3],
267        }
268    }
269}
270
271impl ToString for Color {
272    fn to_string(&self) -> String {
273        format!(
274            "rgba({}, {}, {}, {})",
275            self.r,
276            self.g,
277            self.b,
278            Scalar::from(self.a) / 255.0
279        )
280    }
281}
282
283#[derive(Ignite, Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize)]
284pub struct Vec2 {
285    pub x: Scalar,
286    pub y: Scalar,
287}
288
289impl Vec2 {
290    #[inline]
291    pub fn new(x: Scalar, y: Scalar) -> Self {
292        Self { x, y }
293    }
294
295    #[inline]
296    pub fn zero() -> Self {
297        Self { x: 0.0, y: 0.0 }
298    }
299
300    #[inline]
301    pub fn one() -> Self {
302        Self { x: 1.0, y: 1.0 }
303    }
304
305    #[inline]
306    pub fn sqr_magnitude(self) -> Scalar {
307        self.x * self.x + self.y * self.y
308    }
309
310    #[inline]
311    pub fn magnitude(self) -> Scalar {
312        self.sqr_magnitude().sqrt()
313    }
314
315    #[inline]
316    pub fn normalized(self) -> Self {
317        self / self.magnitude()
318    }
319
320    #[inline]
321    pub fn dot(self, other: Self) -> Scalar {
322        self.x * other.x + self.y * other.y
323    }
324
325    #[inline]
326    pub fn right(self) -> Vec2 {
327        Self {
328            x: self.y,
329            y: -self.x,
330        }
331    }
332
333    #[inline]
334    pub fn is_clockwise(a: Self, b: Self) -> bool {
335        a.x * b.y - a.y * b.x > 0.0
336    }
337
338    #[inline]
339    pub fn lerp(self, other: Vec2, factor: Scalar) -> Self {
340        Self {
341            x: lerp(self.x, other.x, factor),
342            y: lerp(self.y, other.y, factor),
343        }
344    }
345
346    #[inline]
347    pub fn lerp_clamped(self, other: Vec2, factor: Scalar) -> Self {
348        Self {
349            x: lerp_clamped(self.x, other.x, factor),
350            y: lerp_clamped(self.y, other.y, factor),
351        }
352    }
353
354    #[inline]
355    pub fn project_distance(self, from: Vec2, to: Vec2) -> Scalar {
356        let u = self - from;
357        let v = to - from;
358        u.dot(v) / v.sqr_magnitude()
359    }
360
361    #[inline]
362    pub fn project(self, from: Vec2, to: Vec2) -> Vec2 {
363        (to - from) * self.project_distance(from, to)
364    }
365}
366
367impl Add for Vec2 {
368    type Output = Self;
369
370    fn add(self, other: Self) -> Self {
371        Self {
372            x: self.x + other.x,
373            y: self.y + other.y,
374        }
375    }
376}
377
378impl Add<Scalar> for Vec2 {
379    type Output = Self;
380
381    fn add(self, other: Scalar) -> Self {
382        Self {
383            x: self.x + other,
384            y: self.y + other,
385        }
386    }
387}
388
389impl Sub for Vec2 {
390    type Output = Self;
391
392    fn sub(self, other: Self) -> Self {
393        Self {
394            x: self.x - other.x,
395            y: self.y - other.y,
396        }
397    }
398}
399
400impl Sub<Scalar> for Vec2 {
401    type Output = Self;
402
403    fn sub(self, other: Scalar) -> Self {
404        Self {
405            x: self.x - other,
406            y: self.y - other,
407        }
408    }
409}
410
411impl Mul for Vec2 {
412    type Output = Self;
413
414    fn mul(self, other: Self) -> Self {
415        Self {
416            x: self.x * other.x,
417            y: self.y * other.y,
418        }
419    }
420}
421
422impl Mul<Scalar> for Vec2 {
423    type Output = Self;
424
425    fn mul(self, other: Scalar) -> Self {
426        Self {
427            x: self.x * other,
428            y: self.y * other,
429        }
430    }
431}
432
433impl Mul<Mat2d> for Vec2 {
434    type Output = Self;
435
436    fn mul(self, other: Mat2d) -> Self {
437        Self {
438            x: other.0[0] * self.x + other.0[2] * self.y + other.0[4],
439            y: other.0[1] * self.x + other.0[3] * self.y + other.0[5],
440        }
441    }
442}
443
444impl Div for Vec2 {
445    type Output = Self;
446
447    fn div(self, other: Self) -> Self {
448        Self {
449            x: self.x / other.x,
450            y: self.y / other.y,
451        }
452    }
453}
454
455impl Div<Scalar> for Vec2 {
456    type Output = Self;
457
458    fn div(self, other: Scalar) -> Self {
459        Self {
460            x: self.x / other,
461            y: self.y / other,
462        }
463    }
464}
465
466impl Neg for Vec2 {
467    type Output = Self;
468
469    fn neg(self) -> Self {
470        Self {
471            x: -self.x,
472            y: -self.y,
473        }
474    }
475}
476
477impl From<Scalar> for Vec2 {
478    fn from(value: Scalar) -> Self {
479        Self { x: value, y: value }
480    }
481}
482
483impl From<(Scalar, Scalar)> for Vec2 {
484    fn from(value: (Scalar, Scalar)) -> Self {
485        Self {
486            x: value.0,
487            y: value.1,
488        }
489    }
490}
491
492impl From<[Scalar; 2]> for Vec2 {
493    fn from(value: [Scalar; 2]) -> Self {
494        Self {
495            x: value[0],
496            y: value[1],
497        }
498    }
499}
500
501#[derive(Ignite, Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize)]
502pub struct Rect {
503    pub x: Scalar,
504    pub y: Scalar,
505    pub w: Scalar,
506    pub h: Scalar,
507}
508
509impl Rect {
510    pub fn raw(x: Scalar, y: Scalar, w: Scalar, h: Scalar) -> Self {
511        Self { x, y, w, h }
512    }
513
514    pub fn new(position: Vec2, size: Vec2) -> Self {
515        Self {
516            x: position.x,
517            y: position.y,
518            w: size.x,
519            h: size.y,
520        }
521    }
522
523    pub fn with_size(size: Vec2) -> Self {
524        Self {
525            x: 0.0,
526            y: 0.0,
527            w: size.x,
528            h: size.y,
529        }
530    }
531
532    pub fn bounding(points: &[Vec2]) -> Option<Self> {
533        points.iter().fold(None, |a, v| {
534            if let Some(a) = a {
535                Some(a.include(*v))
536            } else {
537                Some(Rect::new(*v, Vec2::zero()))
538            }
539        })
540    }
541
542    pub fn align(&self, factor: Vec2) -> Self {
543        Self {
544            x: self.x - self.w * factor.x,
545            y: self.y - self.h * factor.y,
546            w: self.w,
547            h: self.h,
548        }
549    }
550
551    pub fn expand(&self, thickness: Scalar) -> Self {
552        let tt = thickness * 2.0;
553        let mut result = Self {
554            x: self.x - thickness,
555            y: self.y - thickness,
556            w: self.w + tt,
557            h: self.h + tt,
558        };
559        result.validate();
560        result
561    }
562
563    pub fn include(&self, point: Vec2) -> Self {
564        let (x, w) = if point.x < self.x {
565            (point.x, self.w + self.x - point.x)
566        } else if point.x > self.x + self.w {
567            (self.x, point.x - self.x)
568        } else {
569            (self.x, self.w)
570        };
571        let (y, h) = if point.y < self.y {
572            (point.y, self.h + self.y - point.y)
573        } else if point.y > self.y + self.h {
574            (self.y, point.y - self.y)
575        } else {
576            (self.y, self.h)
577        };
578        Self { x, y, w, h }
579    }
580
581    pub fn validate(&mut self) {
582        if self.w < 0.0 {
583            self.x += self.w;
584            self.w = -self.w;
585        }
586        if self.h < 0.0 {
587            self.y += self.h;
588            self.h = -self.h;
589        }
590    }
591
592    pub fn center(&self) -> Vec2 {
593        Vec2::new(self.x + self.w * 0.5, self.y + self.h * 0.5)
594    }
595
596    pub fn size(&self) -> Vec2 {
597        Vec2::new(self.w, self.h)
598    }
599
600    pub fn contains_point(&self, point: Vec2) -> bool {
601        point.x > self.x
602            && point.x < self.x + self.w
603            && point.y > self.y
604            && point.y < self.y + self.h
605    }
606}
607
608impl From<(Scalar, Scalar)> for Rect {
609    fn from(value: (Scalar, Scalar)) -> Self {
610        Self {
611            x: 0.0,
612            y: 0.0,
613            w: value.0,
614            h: value.1,
615        }
616    }
617}
618
619impl From<[Scalar; 2]> for Rect {
620    fn from(value: [Scalar; 2]) -> Self {
621        Self {
622            x: 0.0,
623            y: 0.0,
624            w: value[0],
625            h: value[1],
626        }
627    }
628}
629
630impl From<(Scalar, Scalar, Scalar, Scalar)> for Rect {
631    fn from(value: (Scalar, Scalar, Scalar, Scalar)) -> Self {
632        Self {
633            x: value.0,
634            y: value.1,
635            w: value.2,
636            h: value.3,
637        }
638    }
639}
640
641impl From<[Scalar; 4]> for Rect {
642    fn from(value: [Scalar; 4]) -> Self {
643        Self {
644            x: value[0],
645            y: value[1],
646            w: value[2],
647            h: value[3],
648        }
649    }
650}