mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
graphics: Optimize GeoM
This commit is contained in:
parent
06d3eb66c7
commit
6db994f0e8
@ -36,7 +36,7 @@ type ColorM struct {
|
|||||||
// Concat multiplies a color matrix with the other color matrix.
|
// Concat multiplies a color matrix with the other color matrix.
|
||||||
// This is same as muptiplying the matrix other and the matrix c in this order.
|
// This is same as muptiplying the matrix other and the matrix c in this order.
|
||||||
func (c *ColorM) Concat(other ColorM) {
|
func (c *ColorM) Concat(other ColorM) {
|
||||||
c.impl.Concat(other.impl)
|
c.impl.Concat(&other.impl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add is deprecated as of 1.5.0-alpha.
|
// Add is deprecated as of 1.5.0-alpha.
|
||||||
|
20
geom.go
20
geom.go
@ -30,13 +30,29 @@ type GeoM struct {
|
|||||||
|
|
||||||
// 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 {
|
||||||
return g.impl.UnsafeElements()[i*affine.GeoMDim+j]
|
a, b, c, d, tx, ty := g.impl.Elements()
|
||||||
|
switch {
|
||||||
|
case i == 0 && j == 0:
|
||||||
|
return a
|
||||||
|
case i == 0 && j == 1:
|
||||||
|
return b
|
||||||
|
case i == 0 && j == 2:
|
||||||
|
return tx
|
||||||
|
case i == 1 && j == 0:
|
||||||
|
return c
|
||||||
|
case i == 1 && j == 1:
|
||||||
|
return d
|
||||||
|
case i == 1 && j == 2:
|
||||||
|
return ty
|
||||||
|
default:
|
||||||
|
panic("ebiten: i or j is out of index")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concat multiplies a geometry matrix with the other geometry matrix.
|
// Concat multiplies a geometry matrix with the other geometry matrix.
|
||||||
// This is same as muptiplying the matrix other and the matrix g in this order.
|
// This is same as muptiplying the matrix other and the matrix g in this order.
|
||||||
func (g *GeoM) Concat(other GeoM) {
|
func (g *GeoM) Concat(other GeoM) {
|
||||||
g.impl.Concat(other.impl)
|
g.impl.Concat(&other.impl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add is deprecated as of 1.5.0-alpha.
|
// Add is deprecated as of 1.5.0-alpha.
|
||||||
|
@ -82,7 +82,7 @@ func (c *ColorM) Equals(other *ColorM) bool {
|
|||||||
|
|
||||||
// Concat multiplies a color matrix with the other color matrix.
|
// Concat multiplies a color matrix with the other color matrix.
|
||||||
// This is same as muptiplying the matrix other and the matrix c in this order.
|
// This is same as muptiplying the matrix other and the matrix c in this order.
|
||||||
func (c *ColorM) Concat(other ColorM) {
|
func (c *ColorM) Concat(other *ColorM) {
|
||||||
if c.elements == nil {
|
if c.elements == nil {
|
||||||
c.elements = colorMIdentityElements
|
c.elements = colorMIdentityElements
|
||||||
}
|
}
|
||||||
@ -182,8 +182,8 @@ var (
|
|||||||
// This conversion uses RGB to/from YCrCb conversion.
|
// This conversion uses RGB to/from YCrCb conversion.
|
||||||
func (c *ColorM) ChangeHSV(hueTheta float64, saturationScale float64, valueScale float64) {
|
func (c *ColorM) ChangeHSV(hueTheta float64, saturationScale float64, valueScale float64) {
|
||||||
sin, cos := math.Sincos(hueTheta)
|
sin, cos := math.Sincos(hueTheta)
|
||||||
c.Concat(rgbToYCbCr)
|
c.Concat(&rgbToYCbCr)
|
||||||
c.Concat(ColorM{
|
c.Concat(&ColorM{
|
||||||
elements: []float64{
|
elements: []float64{
|
||||||
1, 0, 0, 0, 0,
|
1, 0, 0, 0, 0,
|
||||||
0, cos, -sin, 0, 0,
|
0, cos, -sin, 0, 0,
|
||||||
@ -194,7 +194,7 @@ func (c *ColorM) ChangeHSV(hueTheta float64, saturationScale float64, valueScale
|
|||||||
s := saturationScale
|
s := saturationScale
|
||||||
v := valueScale
|
v := valueScale
|
||||||
c.Scale(v, s*v, s*v, 1)
|
c.Scale(v, s*v, s*v, 1)
|
||||||
c.Concat(yCbCrToRgb)
|
c.Concat(&yCbCrToRgb)
|
||||||
}
|
}
|
||||||
|
|
||||||
var monochrome ColorM
|
var monochrome ColorM
|
||||||
|
@ -21,105 +21,138 @@ import (
|
|||||||
// GeoMDim is a dimension of a GeoM.
|
// GeoMDim is a dimension of a GeoM.
|
||||||
const GeoMDim = 3
|
const GeoMDim = 3
|
||||||
|
|
||||||
var (
|
|
||||||
geoMIdentityElements = []float64{
|
|
||||||
1, 0, 0,
|
|
||||||
0, 1, 0,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// A GeoM represents a matrix to transform geometry when rendering an image.
|
// A GeoM represents a matrix to transform geometry when rendering an image.
|
||||||
//
|
//
|
||||||
// The initial value is identity.
|
// The initial value is identity.
|
||||||
type GeoM struct {
|
type GeoM struct {
|
||||||
// When elements is empty, this matrix is identity.
|
a float64
|
||||||
// elements is immutable and a new array must be created when updating.
|
b float64
|
||||||
elements []float64
|
c float64
|
||||||
|
d float64
|
||||||
|
tx float64
|
||||||
|
ty float64
|
||||||
|
inited bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GeoM) UnsafeElements() []float64 {
|
func (g *GeoM) Elements() (a, b, c, d, tx, ty float64) {
|
||||||
if g.elements == nil {
|
if !g.inited {
|
||||||
g.elements = geoMIdentityElements
|
return 1, 0, 0, 1, 0, 0
|
||||||
}
|
}
|
||||||
return g.elements
|
return g.a, g.b, g.c, g.d, g.tx, g.ty
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GeoM) init() {
|
||||||
|
g.a = 1
|
||||||
|
g.b = 0
|
||||||
|
g.c = 0
|
||||||
|
g.d = 1
|
||||||
|
g.tx = 0
|
||||||
|
g.ty = 0
|
||||||
|
g.inited = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetElement sets an element at (i, j).
|
// SetElement sets an element at (i, j).
|
||||||
func (g *GeoM) SetElement(i, j int, element float64) {
|
func (g *GeoM) SetElement(i, j int, element float64) {
|
||||||
if g.elements == nil {
|
if !g.inited {
|
||||||
g.elements = geoMIdentityElements
|
g.init()
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case i == 0 && j == 0:
|
||||||
|
g.a = element
|
||||||
|
case i == 0 && j == 1:
|
||||||
|
g.b = element
|
||||||
|
case i == 0 && j == 2:
|
||||||
|
g.tx = element
|
||||||
|
case i == 1 && j == 0:
|
||||||
|
g.c = element
|
||||||
|
case i == 1 && j == 1:
|
||||||
|
g.d = element
|
||||||
|
case i == 1 && j == 2:
|
||||||
|
g.ty = element
|
||||||
|
default:
|
||||||
|
panic("affine: i or j is out of index")
|
||||||
}
|
}
|
||||||
es := make([]float64, len(g.elements))
|
|
||||||
copy(es, g.elements)
|
|
||||||
es[i*GeoMDim+j] = element
|
|
||||||
g.elements = es
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concat multiplies a geometry matrix with the other geometry matrix.
|
// Concat multiplies a geometry matrix with the other geometry matrix.
|
||||||
// This is same as muptiplying the matrix other and the matrix g in this order.
|
// This is same as muptiplying the matrix other and the matrix g in this order.
|
||||||
func (g *GeoM) Concat(other GeoM) {
|
func (g *GeoM) Concat(other *GeoM) {
|
||||||
if g.elements == nil {
|
if !g.inited {
|
||||||
g.elements = geoMIdentityElements
|
g.init()
|
||||||
}
|
}
|
||||||
if other.elements == nil {
|
if !other.inited {
|
||||||
other.elements = geoMIdentityElements
|
other.init()
|
||||||
}
|
}
|
||||||
g.elements = mul(other.elements, g.elements, GeoMDim)
|
a, b, c, d, tx, ty := g.a, g.b, g.c, g.d, g.tx, g.ty
|
||||||
|
g.a = other.a*a + other.b*c
|
||||||
|
g.b = other.a*b + other.b*d
|
||||||
|
g.tx = other.a*tx + other.b*ty + other.tx
|
||||||
|
g.c = other.c*a + other.d*c
|
||||||
|
g.d = other.c*b + other.d*d
|
||||||
|
g.ty = other.c*tx + other.d*ty + other.ty
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add is deprecated.
|
// Add is deprecated.
|
||||||
func (g *GeoM) Add(other GeoM) {
|
func (g *GeoM) Add(other GeoM) {
|
||||||
if g.elements == nil {
|
if !g.inited {
|
||||||
g.elements = geoMIdentityElements
|
g.init()
|
||||||
}
|
}
|
||||||
if other.elements == nil {
|
if !other.inited {
|
||||||
other.elements = geoMIdentityElements
|
other.init()
|
||||||
}
|
}
|
||||||
g.elements = add(other.elements, g.elements, GeoMDim)
|
g.a += other.a
|
||||||
|
g.b += other.b
|
||||||
|
g.c += other.c
|
||||||
|
g.d += other.d
|
||||||
|
g.tx += other.tx
|
||||||
|
g.ty += other.ty
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale scales the matrix by (x, y).
|
// Scale scales the matrix by (x, y).
|
||||||
func (g *GeoM) Scale(x, y float64) {
|
func (g *GeoM) Scale(x, y float64) {
|
||||||
if g.elements == nil {
|
if !g.inited {
|
||||||
g.elements = []float64{
|
g.a = x
|
||||||
x, 0, 0,
|
g.b = 0
|
||||||
0, y, 0,
|
g.c = 0
|
||||||
}
|
g.d = y
|
||||||
|
g.tx = 0
|
||||||
|
g.ty = 0
|
||||||
|
g.inited = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
es := make([]float64, len(g.elements))
|
g.a *= x
|
||||||
copy(es, g.elements)
|
g.b *= x
|
||||||
for i := 0; i < GeoMDim; i++ {
|
g.tx *= x
|
||||||
es[i] *= x
|
g.c *= y
|
||||||
es[i+GeoMDim] *= y
|
g.d *= y
|
||||||
}
|
g.ty *= y
|
||||||
g.elements = es
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate translates the matrix by (x, y).
|
// Translate translates the matrix by (x, y).
|
||||||
func (g *GeoM) Translate(tx, ty float64) {
|
func (g *GeoM) Translate(tx, ty float64) {
|
||||||
if g.elements == nil {
|
if !g.inited {
|
||||||
g.elements = []float64{
|
g.a = 1
|
||||||
1, 0, tx,
|
g.b = 0
|
||||||
0, 1, ty,
|
g.c = 0
|
||||||
}
|
g.d = 1
|
||||||
|
g.tx = tx
|
||||||
|
g.ty = ty
|
||||||
|
g.inited = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
es := make([]float64, len(g.elements))
|
g.tx += tx
|
||||||
copy(es, g.elements)
|
g.ty += ty
|
||||||
es[2] += tx
|
|
||||||
es[2+GeoMDim] += ty
|
|
||||||
g.elements = es
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate rotates the matrix by theta.
|
// Rotate rotates the matrix by theta.
|
||||||
func (g *GeoM) Rotate(theta float64) {
|
func (g *GeoM) Rotate(theta float64) {
|
||||||
sin, cos := math.Sincos(theta)
|
sin, cos := math.Sincos(theta)
|
||||||
g.Concat(GeoM{
|
g.Concat(&GeoM{
|
||||||
elements: []float64{
|
a: cos,
|
||||||
cos, -sin, 0,
|
b: -sin,
|
||||||
sin, cos, 0,
|
c: sin,
|
||||||
},
|
d: cos,
|
||||||
|
inited: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
vertices.go
14
vertices.go
@ -31,13 +31,13 @@ func vertices(parts ImageParts, width, height int, geo *affine.GeoM) []float32 {
|
|||||||
// TODO: This function should be in graphics package?
|
// TODO: This function should be in graphics package?
|
||||||
l := parts.Len()
|
l := parts.Len()
|
||||||
vs := make([]float32, l*quadFloat32Num)
|
vs := make([]float32, l*quadFloat32Num)
|
||||||
g := geo.UnsafeElements()
|
a, b, c, d, tx, ty := geo.Elements()
|
||||||
g0 := float32(g[0])
|
g0 := float32(a)
|
||||||
g1 := float32(g[1])
|
g1 := float32(b)
|
||||||
g2 := float32(g[3])
|
g2 := float32(c)
|
||||||
g3 := float32(g[4])
|
g3 := float32(d)
|
||||||
g4 := float32(g[2])
|
g4 := float32(tx)
|
||||||
g5 := float32(g[5])
|
g5 := float32(ty)
|
||||||
w := 1
|
w := 1
|
||||||
h := 1
|
h := 1
|
||||||
for w < width {
|
for w < width {
|
||||||
|
Loading…
Reference in New Issue
Block a user