added polygon filling

This commit is contained in:
Thomas Friedel 2018-01-24 16:59:07 +01:00
parent c1de2f2b7d
commit 97615b7595
2 changed files with 136 additions and 7 deletions

View file

@ -155,13 +155,14 @@ func (cv *Canvas) Stroke() {
}
p1 := p.pos
v := p1.Sub(p0).Norm()
v = lm.Vec2{v[1], -v[0]}.MulF(cv.stroke.lineWidth * 0.5)
v1 := p1.Sub(p0).Norm()
v2 := lm.Vec2{v1[1], -v1[0]}.MulF(cv.stroke.lineWidth * 0.5)
v1 = v1.MulF(cv.stroke.lineWidth * 0.5)
x0f, y0f := cv.vecToGL(p0.Add(v))
x1f, y1f := cv.vecToGL(p1.Add(v))
x2f, y2f := cv.vecToGL(p1.Sub(v))
x3f, y3f := cv.vecToGL(p0.Sub(v))
x0f, y0f := cv.vecToGL(p0.Sub(v1).Add(v2))
x1f, y1f := cv.vecToGL(p1.Add(v1).Add(v2))
x2f, y2f := cv.vecToGL(p1.Add(v1).Sub(v2))
x3f, y3f := cv.vecToGL(p0.Sub(v1).Sub(v2))
tris = append(tris, x0f, y0f, x1f, y1f, x2f, y2f, x0f, y0f, x2f, y2f, x3f, y3f)
@ -170,7 +171,7 @@ func (cv *Canvas) Stroke() {
gli.BufferData(gl_ARRAY_BUFFER, len(tris)*4, unsafe.Pointer(&tris[0]), gl_STREAM_DRAW)
gli.VertexAttribPointer(sr.vertex, 2, gl_FLOAT, false, 0, nil)
gli.DrawArrays(gl_TRIANGLES, 6, int32(len(tris)/2))
gli.DrawArrays(gl_TRIANGLES, 6, int32(len(tris)/2-6))
gli.ColorMask(true, true, true, true)
gli.StencilFunc(gl_EQUAL, 1, 0xFF)
@ -182,3 +183,34 @@ func (cv *Canvas) Stroke() {
gli.Disable(gl_STENCIL_TEST)
}
func (cv *Canvas) Fill() {
if len(cv.path) < 3 {
return
}
cv.activate()
gli.UseProgram(sr.id)
gli.Uniform4f(sr.color, cv.fill.r, cv.fill.g, cv.fill.b, cv.fill.a)
gli.EnableVertexAttribArray(sr.vertex)
gli.BindBuffer(gl_ARRAY_BUFFER, buf)
var buf [1000]float32
tris := buf[:0]
tris = append(tris, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1)
tris = triangulatePath(cv.path, tris)
total := len(tris)
for i := 12; i < total; i += 2 {
x, y := tris[i], tris[i+1]
tris[i], tris[i+1] = cv.ptToGL(x, y)
}
gli.BufferData(gl_ARRAY_BUFFER, len(tris)*4, unsafe.Pointer(&tris[0]), gl_STREAM_DRAW)
gli.VertexAttribPointer(sr.vertex, 2, gl_FLOAT, false, 0, nil)
gli.DrawArrays(gl_TRIANGLES, 6, int32(len(tris)/2-6))
gli.DisableVertexAttribArray(sr.vertex)
}

97
triangulation.go Normal file
View file

@ -0,0 +1,97 @@
package canvas
import (
"github.com/void6/lm"
)
func pointIsRightOfLine(a, b, p lm.Vec2) bool {
if a[1] == b[1] {
return false
}
if a[1] > b[1] {
a, b = b, a
}
if p[1] < a[1] || p[1] > b[1] {
return false
}
v := b.Sub(a)
r := (p[1] - a[1]) / v[1]
x := a[0] + r*v[0]
return p[0] > x
}
func triangleContainsPoint(a, b, c, p lm.Vec2) bool {
// if point is outside triangle bounds, return false
if p[0] < a[0] && p[0] < b[0] && p[0] < c[0] {
return false
}
if p[0] > a[0] && p[0] > b[0] && p[0] > c[0] {
return false
}
if p[1] < a[1] && p[1] < b[1] && p[1] < c[1] {
return false
}
if p[1] > a[1] && p[1] > b[1] && p[1] > c[1] {
return false
}
// check whether the point is to the right of each triangle line.
// if the total is 1, it is inside the triangle
count := 0
if pointIsRightOfLine(a, b, p) {
count++
}
if pointIsRightOfLine(b, c, p) {
count++
}
if pointIsRightOfLine(c, a, p) {
count++
}
return count == 1
}
func polygonContainsPoint(polygon []lm.Vec2, p lm.Vec2) bool {
a := polygon[len(polygon)-1]
count := 0
for _, b := range polygon {
if pointIsRightOfLine(a, b, p) {
count++
}
a = b
}
return count%2 == 1
}
func triangulatePath(path []pathPoint, target []float32) []float32 {
var buf [500]lm.Vec2
polygon := buf[:0]
for _, p := range path {
polygon = append(polygon, p.pos)
}
for len(polygon) > 2 {
var i int
triangles:
for i = range polygon {
a := polygon[i]
b := polygon[(i+1)%len(polygon)]
c := polygon[(i+2)%len(polygon)]
for i2, p := range polygon {
if i2 >= i && i2 <= i+2 {
continue
}
if triangleContainsPoint(a, b, c, p) {
continue triangles
}
center := a.Add(b).Add(c).DivF(3)
if !polygonContainsPoint(polygon, center) {
continue triangles
}
}
target = append(target, a[0], a[1], b[0], b[1], c[0], c[1])
break
}
remove := (i + 1) % len(polygon)
polygon = append(polygon[:remove], polygon[remove+1:]...)
}
return target
}