package gg import ( "math" "github.com/hajimehoshi/ebiten/v2" ) type EVertex = ebiten.Vertex // Ebitens vector in better abstractions like Vectors. type Vertex struct { Dst Vector Src Vector Colority } type Triangle [3]Vector type Triangles []Triangle type DrawableTriangles struct { Triangles Colority } func (v Vertex) Ebiten() EVertex { return EVertex { DstX: float32(v.Dst.X), DstY: float32(v.Dst.Y), SrcX: float32(v.Src.X), SrcY: float32(v.Src.Y), ColorR: float32(v.Color.R)/(float32(MaxColorV)), ColorG: float32(v.Color.G)/(float32(MaxColorV)), ColorB: float32(v.Color.B)/(float32(MaxColorV)), ColorA: float32(v.Color.A)/(float32(MaxColorV)), } } // Returns the area of the triangle. func (t Triangle) Area() Float { x1 := t[0].X y1 := t[0].Y x2 := t[1].X y2 := t[1].Y x3 := t[2].X y3 := t[2].Y return math.Abs( (x1*(y2-y3) + x2*(y3-y1) + x3*(y1-y2))/2) } func sqr(v Float) Float { return v * v } // Return squares of lengths of sides of the triangle. func (t Triangle) SideLengthSquares() ([3]Float) { l1 := LineSegment{t[0], t[1]}.LenSqr() l2 := LineSegment{t[1], t[2]}.LenSqr() l3 := LineSegment{t[2], t[0]}.LenSqr() return [3]Float{l1, l2, l3} } // Check whether the point is in the triangle. func (t Triangle) ContainsPoint(p Point) bool { d1 := Triangle{p, t[0], t[1]}.Sgn() d2 := Triangle{p, t[1], t[2]}.Sgn() d3 := Triangle{p, t[2], t[0]}.Sgn() neg := (d1 < 0) || (d2 < 0) || (d3 < 0) pos := (d1 > 0) || (d2 > 0) || (d3 > 0) return !(neg && pos) } func (t Triangle) Sgn() Float { return (t[0].X - t[2].X) * (t[1].Y - t[2].Y) - (t[1].X - t[2].X) * (t[0].Y - t[2].Y) } func (ts Triangles) ContainsPoint(p Point) bool { for _, t := range ts { if t.ContainsPoint(p) { return true } } return false } func (r *DrawableTriangles) MakeEVertices(c *Context) []EVertex { m := c.Camera.RealMatrix() vs := make([]ebiten.Vertex, len(r.Triangles) * 3) var buf Vertex buf.Color = r.Color for i := range r.Triangles { for j := range r.Triangles[i] { buf.Dst = r.Triangles[i][j].Apply(m) vs[i*3 + j] = buf.Ebiten() } } return vs }