Make the elements of matrices optional

This commit is contained in:
Hajime Hoshi 2014-12-26 11:22:36 +09:00
parent 3e5688e2e1
commit d764afcb8f
5 changed files with 128 additions and 24 deletions

View File

@ -43,7 +43,8 @@ func add(lhs, rhs, result affine) {
for i := 0; i < dim-1; i++ { for i := 0; i < dim-1; i++ {
for j := 0; j < dim; j++ { for j := 0; j < dim; j++ {
result.SetElement(i, j, lhs.Element(i, j)+rhs.Element(i, j)) v := lhs.Element(i, j) + rhs.Element(i, j)
result.SetElement(i, j, v)
} }
} }
} }

View File

@ -29,32 +29,45 @@ const ColorMatrixDim = 5
// the color is multiplied again. // the color is multiplied again.
type ColorMatrix struct { type ColorMatrix struct {
// es represents elements. // es represents elements.
es [ColorMatrixDim - 1][ColorMatrixDim]float64 es *[ColorMatrixDim - 1][ColorMatrixDim]float64
}
func colorMatrixEsI() *[ColorMatrixDim - 1][ColorMatrixDim]float64 {
return &[ColorMatrixDim - 1][ColorMatrixDim]float64{
{1, 0, 0, 0, 0},
{0, 1, 0, 0, 0},
{0, 0, 1, 0, 0},
{0, 0, 0, 1, 0},
}
} }
// NewColorMatrix returns an identity color matrix. // NewColorMatrix returns an identity color matrix.
func NewColorMatrix() ColorMatrix { func NewColorMatrix() ColorMatrix {
return ColorMatrix{ return ColorMatrix{
[ColorMatrixDim - 1][ColorMatrixDim]float64{ es: colorMatrixEsI(),
{1, 0, 0, 0, 0},
{0, 1, 0, 0, 0},
{0, 0, 1, 0, 0},
{0, 0, 0, 1, 0},
},
} }
} }
func (c *ColorMatrix) dim() int { func (c ColorMatrix) dim() int {
return ColorMatrixDim return ColorMatrixDim
} }
// Element returns a value of a matrix at (i, j). // Element returns a value of a matrix at (i, j).
func (c *ColorMatrix) Element(i, j int) float64 { func (c ColorMatrix) Element(i, j int) float64 {
if c.es == nil {
if i == j {
return 1
}
return 0
}
return c.es[i][j] return c.es[i][j]
} }
// Concat multiplies a color matrix with the other color matrix. // Concat multiplies a color matrix with the other color matrix.
func (c *ColorMatrix) Concat(other ColorMatrix) { func (c *ColorMatrix) Concat(other ColorMatrix) {
if c.es == nil {
c.es = colorMatrixEsI()
}
result := ColorMatrix{} result := ColorMatrix{}
mul(&other, c, &result) mul(&other, c, &result)
*c = result *c = result
@ -62,6 +75,9 @@ func (c *ColorMatrix) Concat(other ColorMatrix) {
// Add adds a color matrix with the other color matrix. // Add adds a color matrix with the other color matrix.
func (c *ColorMatrix) Add(other ColorMatrix) { func (c *ColorMatrix) Add(other ColorMatrix) {
if c.es == nil {
c.es = colorMatrixEsI()
}
result := ColorMatrix{} result := ColorMatrix{}
add(&other, c, &result) add(&other, c, &result)
*c = result *c = result
@ -69,6 +85,9 @@ func (c *ColorMatrix) Add(other ColorMatrix) {
// SetElement sets an element at (i, j). // SetElement sets an element at (i, j).
func (c *ColorMatrix) SetElement(i, j int, element float64) { func (c *ColorMatrix) SetElement(i, j int, element float64) {
if c.es == nil {
c.es = colorMatrixEsI()
}
c.es[i][j] = element c.es[i][j] = element
} }
@ -78,7 +97,7 @@ func Monochrome() ColorMatrix {
const g = 23434.0 / 32768.0 const g = 23434.0 / 32768.0
const b = 2366.0 / 32768.0 const b = 2366.0 / 32768.0
return ColorMatrix{ return ColorMatrix{
[ColorMatrixDim - 1][ColorMatrixDim]float64{ &[ColorMatrixDim - 1][ColorMatrixDim]float64{
{r, g, b, 0, 0}, {r, g, b, 0, 0},
{r, g, b, 0, 0}, {r, g, b, 0, 0},
{r, g, b, 0, 0}, {r, g, b, 0, 0},
@ -90,7 +109,7 @@ func Monochrome() ColorMatrix {
// ScaleColor returns a color matrix that scales a color matrix by the given color (r, g, b, a). // ScaleColor returns a color matrix that scales a color matrix by the given color (r, g, b, a).
func ScaleColor(r, g, b, a float64) ColorMatrix { func ScaleColor(r, g, b, a float64) ColorMatrix {
return ColorMatrix{ return ColorMatrix{
[ColorMatrixDim - 1][ColorMatrixDim]float64{ &[ColorMatrixDim - 1][ColorMatrixDim]float64{
{r, 0, 0, 0, 0}, {r, 0, 0, 0, 0},
{0, g, 0, 0, 0}, {0, g, 0, 0, 0},
{0, 0, b, 0, 0}, {0, 0, b, 0, 0},
@ -102,7 +121,7 @@ func ScaleColor(r, g, b, a float64) ColorMatrix {
// TranslateColor returns a color matrix that translates a color matrix by the given color (r, g, b, a). // TranslateColor returns a color matrix that translates a color matrix by the given color (r, g, b, a).
func TranslateColor(r, g, b, a float64) ColorMatrix { func TranslateColor(r, g, b, a float64) ColorMatrix {
return ColorMatrix{ return ColorMatrix{
[ColorMatrixDim - 1][ColorMatrixDim]float64{ &[ColorMatrixDim - 1][ColorMatrixDim]float64{
{1, 0, 0, 0, r}, {1, 0, 0, 0, r},
{0, 1, 0, 0, g}, {0, 1, 0, 0, g},
{0, 0, 1, 0, b}, {0, 0, 1, 0, b},
@ -118,7 +137,7 @@ func RotateHue(theta float64) ColorMatrix {
v2 := (1.0/3.0)*(1.0-cos) - math.Sqrt(1.0/3.0)*sin v2 := (1.0/3.0)*(1.0-cos) - math.Sqrt(1.0/3.0)*sin
v3 := (1.0/3.0)*(1.0-cos) + math.Sqrt(1.0/3.0)*sin v3 := (1.0/3.0)*(1.0-cos) + math.Sqrt(1.0/3.0)*sin
return ColorMatrix{ return ColorMatrix{
[ColorMatrixDim - 1][ColorMatrixDim]float64{ &[ColorMatrixDim - 1][ColorMatrixDim]float64{
{v1, v2, v3, 0, 0}, {v1, v2, v3, 0, 0},
{v3, v1, v2, 0, 0}, {v3, v1, v2, 0, 0},
{v2, v3, v1, 0, 0}, {v2, v3, v1, 0, 0},

View File

@ -13,3 +13,38 @@
// limitations under the License. // limitations under the License.
package ebiten_test package ebiten_test
import (
. "."
"testing"
)
func TestColorInit(t *testing.T) {
var m ColorMatrix
for i := 0; i < ColorMatrixDim-1; i++ {
for j := 0; j < ColorMatrixDim; j++ {
got := m.Element(i, j)
want := 0.0
if i == j {
want = 1
}
if want != got {
t.Errorf("m.Element(%d, %d) = %f, want %f", i, j, got, want)
}
}
}
m.Add(m)
for i := 0; i < ColorMatrixDim-1; i++ {
for j := 0; j < ColorMatrixDim; j++ {
got := m.Element(i, j)
want := 0.0
if i == j {
want = 2
}
if want != got {
t.Errorf("m.Element(%d, %d) = %f, want %f", i, j, got, want)
}
}
}
}

View File

@ -24,30 +24,43 @@ const GeometryMatrixDim = 3
// A GeometryMatrix represents a matrix to transform geometry when rendering an image. // A GeometryMatrix represents a matrix to transform geometry when rendering an image.
type GeometryMatrix struct { type GeometryMatrix struct {
// es represents elements. // es represents elements.
es [GeometryMatrixDim - 1][GeometryMatrixDim]float64 es *[GeometryMatrixDim - 1][GeometryMatrixDim]float64
}
func geometryMatrixEsI() *[GeometryMatrixDim - 1][GeometryMatrixDim]float64 {
return &[GeometryMatrixDim - 1][GeometryMatrixDim]float64{
{1, 0, 0},
{0, 1, 0},
}
} }
// NewGeometryMatrix returns an identity geometry matrix. // NewGeometryMatrix returns an identity geometry matrix.
func NewGeometryMatrix() GeometryMatrix { func NewGeometryMatrix() GeometryMatrix {
return GeometryMatrix{ return GeometryMatrix{
[GeometryMatrixDim - 1][GeometryMatrixDim]float64{ es: geometryMatrixEsI(),
{1, 0, 0},
{0, 1, 0},
},
} }
} }
func (g *GeometryMatrix) dim() int { func (g GeometryMatrix) dim() int {
return GeometryMatrixDim return GeometryMatrixDim
} }
// Element returns a value of a matrix at (i, j). // Element returns a value of a matrix at (i, j).
func (g *GeometryMatrix) Element(i, j int) float64 { func (g GeometryMatrix) Element(i, j int) float64 {
if g.es == nil {
if i == j {
return 1
}
return 0
}
return g.es[i][j] return g.es[i][j]
} }
// Concat multiplies a geometry matrix with the other geometry matrix. // Concat multiplies a geometry matrix with the other geometry matrix.
func (g *GeometryMatrix) Concat(other GeometryMatrix) { func (g *GeometryMatrix) Concat(other GeometryMatrix) {
if g.es == nil {
g.es = geometryMatrixEsI()
}
result := GeometryMatrix{} result := GeometryMatrix{}
mul(&other, g, &result) mul(&other, g, &result)
*g = result *g = result
@ -55,6 +68,9 @@ func (g *GeometryMatrix) Concat(other GeometryMatrix) {
// Add adds a geometry matrix with the other geometry matrix. // Add adds a geometry matrix with the other geometry matrix.
func (g *GeometryMatrix) Add(other GeometryMatrix) { func (g *GeometryMatrix) Add(other GeometryMatrix) {
if g.es == nil {
g.es = geometryMatrixEsI()
}
result := GeometryMatrix{} result := GeometryMatrix{}
add(&other, g, &result) add(&other, g, &result)
*g = result *g = result
@ -62,13 +78,16 @@ func (g *GeometryMatrix) Add(other GeometryMatrix) {
// SetElement sets an element at (i, j). // SetElement sets an element at (i, j).
func (g *GeometryMatrix) SetElement(i, j int, element float64) { func (g *GeometryMatrix) SetElement(i, j int, element float64) {
if g.es == nil {
g.es = geometryMatrixEsI()
}
g.es[i][j] = element g.es[i][j] = element
} }
// ScaleGeometry returns a matrix that scales a geometry matrix by (x, y). // ScaleGeometry returns a matrix that scales a geometry matrix by (x, y).
func ScaleGeometry(x, y float64) GeometryMatrix { func ScaleGeometry(x, y float64) GeometryMatrix {
return GeometryMatrix{ return GeometryMatrix{
[2][3]float64{ es: &[2][3]float64{
{x, 0, 0}, {x, 0, 0},
{0, y, 0}, {0, y, 0},
}, },
@ -78,7 +97,7 @@ func ScaleGeometry(x, y float64) GeometryMatrix {
// TranslateGeometry returns a matrix taht translates a geometry matrix by (tx, ty). // TranslateGeometry returns a matrix taht translates a geometry matrix by (tx, ty).
func TranslateGeometry(tx, ty float64) GeometryMatrix { func TranslateGeometry(tx, ty float64) GeometryMatrix {
return GeometryMatrix{ return GeometryMatrix{
[2][3]float64{ es: &[2][3]float64{
{1, 0, tx}, {1, 0, tx},
{0, 1, ty}, {0, 1, ty},
}, },
@ -89,7 +108,7 @@ func TranslateGeometry(tx, ty float64) GeometryMatrix {
func RotateGeometry(theta float64) GeometryMatrix { func RotateGeometry(theta float64) GeometryMatrix {
sin, cos := math.Sincos(theta) sin, cos := math.Sincos(theta)
return GeometryMatrix{ return GeometryMatrix{
[2][3]float64{ es: &[2][3]float64{
{cos, -sin, 0}, {cos, -sin, 0},
{sin, cos, 0}, {sin, cos, 0},
}, },

View File

@ -19,6 +19,36 @@ import (
"testing" "testing"
) )
func TestGeometryInit(t *testing.T) {
var m GeometryMatrix
for i := 0; i < GeometryMatrixDim-1; i++ {
for j := 0; j < GeometryMatrixDim; j++ {
got := m.Element(i, j)
want := 0.0
if i == j {
want = 1
}
if want != got {
t.Errorf("m.Element(%d, %d) = %f, want %f", i, j, got, want)
}
}
}
m.Add(m)
for i := 0; i < GeometryMatrixDim-1; i++ {
for j := 0; j < GeometryMatrixDim; j++ {
got := m.Element(i, j)
want := 0.0
if i == j {
want = 2
}
if want != got {
t.Errorf("m.Element(%d, %d) = %f, want %f", i, j, got, want)
}
}
}
}
func TestGeometryConcat(t *testing.T) { func TestGeometryConcat(t *testing.T) {
matrix1 := ScaleGeometry(2, 2) matrix1 := ScaleGeometry(2, 2)
matrix2 := TranslateGeometry(1, 1) matrix2 := TranslateGeometry(1, 1)