From 37baaee464a700d1f04fa32d8b74530c1570d502 Mon Sep 17 00:00:00 2001
From: faiface <faiface@ksp.sk>
Date: Fri, 20 Jan 2017 18:40:48 +0100
Subject: [PATCH] add forgotten gltriangles.go

---
 gltriangles.go | 141 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)
 create mode 100644 gltriangles.go

diff --git a/gltriangles.go b/gltriangles.go
new file mode 100644
index 0000000..7d985fd
--- /dev/null
+++ b/gltriangles.go
@@ -0,0 +1,141 @@
+package pixel
+
+import (
+	"github.com/faiface/mainthread"
+	"github.com/faiface/pixel/pixelgl"
+)
+
+// NewGLTriangles returns OpenGL triangles implemented using pixelgl.VertexSlice. A few notes.
+//
+// Triangles returned from this function support TrianglesPosition, TrianglesColor and
+// TrianglesTexture. If you need to support more, you can "override" Update and Append method.
+//
+// Draw method simply draws the underlying pixelgl.VertexSlice. It needs to be called in the main
+// thread manually. Also, you need to take care of additional Target initialization or setting of
+// uniform attributes.
+func NewGLTriangles(shader *pixelgl.Shader, t Triangles) Triangles {
+	var gt *glTriangles
+	mainthread.Call(func() {
+		gt = &glTriangles{
+			vs:     pixelgl.MakeVertexSlice(shader, 0, t.Len()),
+			shader: shader,
+		}
+	})
+	gt.Update(t)
+	return gt
+}
+
+type glTriangles struct {
+	vs     *pixelgl.VertexSlice
+	data   []float32
+	shader *pixelgl.Shader
+}
+
+func (gt *glTriangles) Len() int {
+	return len(gt.data) / gt.vs.Stride()
+}
+
+func (gt *glTriangles) Draw() {
+	gt.vs.Begin()
+	gt.vs.Draw()
+	gt.vs.End()
+}
+
+func (gt *glTriangles) resize(len int) {
+	if len > gt.Len() {
+		needAppend := len - gt.Len()
+		for i := 0; i < needAppend; i++ {
+			gt.data = append(gt.data,
+				0, 0,
+				1, 1, 1, 1,
+				-1, -1,
+			)
+		}
+	}
+	if len < gt.Len() {
+		gt.data = gt.data[:len]
+	}
+}
+
+func (gt *glTriangles) updateData(offset int, t Triangles) {
+	if t, ok := t.(TrianglesPosition); ok {
+		for i := offset; i < offset+t.Len(); i++ {
+			px, py := t.Position(i).XY()
+			gt.data[i*gt.vs.Stride()+0] = float32(px)
+			gt.data[i*gt.vs.Stride()+1] = float32(py)
+		}
+	}
+	if t, ok := t.(TrianglesColor); ok {
+		for i := offset; i < offset+t.Len(); i++ {
+			col := t.Color(i)
+			gt.data[i*gt.vs.Stride()+2] = float32(col.R)
+			gt.data[i*gt.vs.Stride()+3] = float32(col.G)
+			gt.data[i*gt.vs.Stride()+4] = float32(col.B)
+			gt.data[i*gt.vs.Stride()+5] = float32(col.A)
+		}
+	}
+	if t, ok := t.(TrianglesTexture); ok {
+		for i := offset; i < offset+t.Len(); i++ {
+			tx, ty := t.Texture(i).XY()
+			gt.data[i*gt.vs.Stride()+6] = float32(tx)
+			gt.data[i*gt.vs.Stride()+7] = float32(ty)
+		}
+	}
+}
+
+func (gt *glTriangles) submitData() {
+	data := gt.data // avoid race condition
+	mainthread.CallNonBlock(func() {
+		gt.vs.Begin()
+		dataLen := len(data) / gt.vs.Stride()
+		if dataLen > gt.vs.Len() {
+			gt.vs.Append(make([]float32, (dataLen-gt.vs.Len())*gt.vs.Stride()))
+		}
+		if dataLen < gt.vs.Len() {
+			gt.vs = gt.vs.Slice(0, dataLen)
+		}
+		gt.vs.SetVertexData(gt.data)
+		gt.vs.End()
+	})
+}
+
+func (gt *glTriangles) Update(t Triangles) {
+	gt.resize(t.Len())
+	gt.updateData(0, t)
+	gt.submitData()
+}
+
+func (gt *glTriangles) Append(t Triangles) {
+	gt.resize(gt.Len() + t.Len())
+	gt.updateData(gt.Len()-t.Len(), t)
+	gt.submitData()
+}
+
+func (gt *glTriangles) Copy() Triangles {
+	return NewGLTriangles(gt.shader, gt)
+}
+
+func (gt *glTriangles) Position(i int) Vec {
+	px := gt.data[i*gt.vs.Stride()+0]
+	py := gt.data[i*gt.vs.Stride()+1]
+	return V(float64(px), float64(py))
+}
+
+func (gt *glTriangles) Color(i int) NRGBA {
+	r := gt.data[i*gt.vs.Stride()+2]
+	g := gt.data[i*gt.vs.Stride()+3]
+	b := gt.data[i*gt.vs.Stride()+4]
+	a := gt.data[i*gt.vs.Stride()+5]
+	return NRGBA{
+		R: float64(r),
+		G: float64(g),
+		B: float64(b),
+		A: float64(a),
+	}
+}
+
+func (gt *glTriangles) Texture(i int) Vec {
+	tx := gt.data[i*gt.vs.Stride()+6]
+	ty := gt.data[i*gt.vs.Stride()+7]
+	return V(float64(tx), float64(ty))
+}
-- 
GitLab