package gg import ( "math" "github.com/hajimehoshi/ebiten/v2" ) // 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 Visibility Colority ShaderOptions ebiten.DrawTrianglesOptions } func (v Vertex) Ebiten() ebiten.Vertex { return ebiten.Vertex { 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) Draw(c *Context) { m := c.Camera.RealMatrix() // Draw solid color if no shader. if r.Shader == nil { 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() } } is := make([]uint16, len(r.Triangles) * 3) start := len(c.Engine.vindices) for i := 0 ; i < len(is) ; i++ { is[i] = uint16(start + i) } c.Engine.vertices = append(c.Engine.vertices, vs...) c.Engine.vindices = append(c.Engine.vindices, is...) return //c.DrawTriangles(vs, is, img, &r.DrawTrianglesOptions) return } // Use the Color as base image if no is provided. /*if r.Images[0] == nil { r.Images[0] = NewImage(1, 1) r.Images[0].Set(0, 0, r.Color) } w, h := r.Images[0].Size() // Drawing with shader. opts := &ebiten.DrawRectShaderOptions{ GeoM: m, Images: r.Images, Uniforms: r.Uniforms, } i.DrawRectShader(w, h, r.Shader, opts)*/ }