graphicsutil: Extract matrix applying for performance

This commit is contained in:
Hajime Hoshi 2018-06-17 19:45:09 +09:00
parent 9f34b79297
commit ac24a8382f
7 changed files with 32 additions and 30 deletions

View File

@ -61,6 +61,10 @@ func (g *GeoM) apply32(x, y float32) (x2, y2 float32) {
return (g.a_1+1)*x + g.b*y + g.tx, g.c*x + (g.d_1+1)*y + g.ty return (g.a_1+1)*x + g.b*y + g.tx, g.c*x + (g.d_1+1)*y + g.ty
} }
func (g *GeoM) elements() (a, b, c, d, tx, ty float32) {
return g.a_1 + 1, g.b, g.c, g.d_1 + 1, g.tx, g.ty
}
// Element returns a value of a matrix at (i, j). // Element returns a value of a matrix at (i, j).
func (g *GeoM) Element(i, j int) float64 { func (g *GeoM) Element(i, j int) float64 {
switch { switch {
@ -136,6 +140,10 @@ func (g *GeoM) Translate(tx, ty float64) {
// Rotate rotates the matrix by theta. // Rotate rotates the matrix by theta.
// The unit is radian. // The unit is radian.
func (g *GeoM) Rotate(theta float64) { func (g *GeoM) Rotate(theta float64) {
if theta == 0 {
return
}
sin64, cos64 := math.Sincos(theta) sin64, cos64 := math.Sincos(theta)
sin, cos := float32(sin64), float32(cos64) sin, cos := float32(sin64), float32(cos64)

View File

@ -130,8 +130,8 @@ type geoM32 struct {
inner *GeoM inner *GeoM
} }
func (g geoM32) Apply(x, y float32) (x2, y2 float32) { func (g geoM32) Elements() (a, b, c, d, tx, ty float32) {
return g.inner.apply32(x, y) return g.inner.elements()
} }
// DrawImage draws the given image on the image i. // DrawImage draws the given image on the image i.

View File

@ -44,7 +44,7 @@ func (v *verticesBackend) sliceForOneQuad() []float32 {
} }
type GeoM interface { type GeoM interface {
Apply(x, y float32) (x2, y2 float32) Elements() (a, b, c, d, tx, ty float32)
} }
func QuadVertices(width, height int, sx0, sy0, sx1, sy1 int, geom GeoM) []float32 { func QuadVertices(width, height int, sx0, sy0, sx1, sy1 int, geom GeoM) []float32 {
@ -55,9 +55,6 @@ func QuadVertices(width, height int, sx0, sy0, sx1, sy1 int, geom GeoM) []float3
return nil return nil
} }
x0, y0 := float32(0.0), float32(0.0)
x1, y1 := float32(sx1-sx0), float32(sy1-sy0)
// it really feels like we should be able to cache this computation // it really feels like we should be able to cache this computation
// but it may not matter. // but it may not matter.
w := 1 w := 1
@ -71,16 +68,16 @@ func QuadVertices(width, height int, sx0, sy0, sx1, sy1 int, geom GeoM) []float3
wf := float32(w) wf := float32(w)
hf := float32(h) hf := float32(h)
u0, v0, u1, v1 := float32(sx0)/wf, float32(sy0)/hf, float32(sx1)/wf, float32(sy1)/hf u0, v0, u1, v1 := float32(sx0)/wf, float32(sy0)/hf, float32(sx1)/wf, float32(sy1)/hf
return quadVerticesImpl(u0, v0, u1, v1, x0, y0, x1, y1, geom) return quadVerticesImpl(float32(sx1-sx0), float32(sy1-sy0), u0, v0, u1, v1, geom)
} }
func quadVerticesImpl(u0, v0, u1, v1, x0, y0, x1, y1 float32, geom GeoM) []float32 { func quadVerticesImpl(x, y, u0, v0, u1, v1 float32, geom GeoM) []float32 {
vs := theVerticesBackend.sliceForOneQuad() vs := theVerticesBackend.sliceForOneQuad()
x, y := geom.Apply(x0, y0) a, b, c, d, tx, ty := geom.Elements()
// Vertex coordinates // Vertex coordinates
vs[0] = x vs[0] = tx
vs[1] = y vs[1] = ty
// Texture coordinates: first 2 values indicates the actual coodinate, and // Texture coordinates: first 2 values indicates the actual coodinate, and
// the second indicates diagonally opposite coodinates. // the second indicates diagonally opposite coodinates.
@ -91,25 +88,22 @@ func quadVerticesImpl(u0, v0, u1, v1, x0, y0, x1, y1 float32, geom GeoM) []float
vs[5] = v1 vs[5] = v1
// and the same for the other three coordinates // and the same for the other three coordinates
x, y = geom.Apply(x1, y0) vs[6] = a*x + tx
vs[6] = x vs[7] = c*x + ty
vs[7] = y
vs[8] = u1 vs[8] = u1
vs[9] = v0 vs[9] = v0
vs[10] = u0 vs[10] = u0
vs[11] = v1 vs[11] = v1
x, y = geom.Apply(x0, y1) vs[12] = b*y + tx
vs[12] = x vs[13] = d*y + ty
vs[13] = y
vs[14] = u0 vs[14] = u0
vs[15] = v1 vs[15] = v1
vs[16] = u1 vs[16] = u1
vs[17] = v0 vs[17] = v0
x, y = geom.Apply(x1, y1) vs[18] = a*x + b*y + tx
vs[18] = x vs[19] = c*x + d*y + ty
vs[19] = y
vs[20] = u1 vs[20] = u1
vs[21] = v1 vs[21] = v1
vs[22] = u0 vs[22] = u0

View File

@ -129,8 +129,8 @@ type geoM struct {
ty float32 ty float32
} }
func (g *geoM) Apply(x, y float32) (float32, float32) { func (g *geoM) Elements() (a, b, c, d, tx, ty float32) {
return x*g.scaleX + g.tx, y*g.scaleY + g.ty return g.scaleX, 0, 0, g.scaleY, g.tx, g.ty
} }
// ReplacePixels replaces the image pixels with the given pixels slice. // ReplacePixels replaces the image pixels with the given pixels slice.

View File

@ -107,8 +107,8 @@ var (
type idGeoM struct{} type idGeoM struct{}
func (idGeoM) Apply(x, y float32) (x2, y2 float32) { func (idGeoM) Elements() (a, b, c, d, tx, ty float32) {
return x, y return 1, 0, 0, 1, 0, 0
} }
func TestRestoreChain(t *testing.T) { func TestRestoreChain(t *testing.T) {
@ -267,8 +267,8 @@ type geoM struct {
ty float32 ty float32
} }
func (g *geoM) Apply(x, y float32) (x2, y2 float32) { func (g *geoM) Elements() (a, b, c, d, tx, ty float32) {
return x + g.tx, y + g.ty return 1, 0, 0, 1, g.tx, g.ty
} }
func TestRestoreComplexGraph(t *testing.T) { func TestRestoreComplexGraph(t *testing.T) {

View File

@ -100,8 +100,8 @@ type Image struct {
type idGeoM struct{} type idGeoM struct{}
func (idGeoM) Apply(x, y float32) (x2, y2 float32) { func (idGeoM) Elements() (a, b, c, d, tx, ty float32) {
return x, y return 1, 0, 0, 1, 0, 0
} }
func (i *Image) ensureNotShared() { func (i *Image) ensureNotShared() {

View File

@ -50,8 +50,8 @@ type geoM struct {
ty float32 ty float32
} }
func (g *geoM) Apply(x, y float32) (x2, y2 float32) { func (g *geoM) Elements() (a, b, c, d, tx, ty float32) {
return x + g.tx, y + g.ty return 1, 0, 0, 1, g.tx, g.ty
} }
func TestEnsureNotShared(t *testing.T) { func TestEnsureNotShared(t *testing.T) {