Skip to content

Commit

Permalink
replace Transform by much simpler Matrix
Browse files Browse the repository at this point in the history
  • Loading branch information
faiface committed Mar 6, 2017
1 parent 1083ca7 commit f0394ec
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 234 deletions.
35 changes: 22 additions & 13 deletions batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ package pixel
import (
"fmt"
"image/color"
"math"

"github.com/go-gl/mathgl/mgl32"
"github.com/go-gl/mathgl/mgl64"
)

// Batch is a Target that allows for efficient drawing of many objects with the same Picture (but
Expand All @@ -16,7 +15,7 @@ import (
type Batch struct {
cont Drawer

mat mgl32.Mat3
mat Matrix
col NRGBA
}

Expand Down Expand Up @@ -45,9 +44,9 @@ func (b *Batch) Draw(t Target) {
b.cont.Draw(t)
}

// SetTransform sets transforms used in the following draws onto the Batch.
func (b *Batch) SetTransform(t ...Transform) {
b.mat = transformToMat(t...)
// SetMatrix sets a Matrix that every point will be projected by.
func (b *Batch) SetMatrix(m Matrix) {
b.mat = m
}

// SetColorMask sets a mask color used in the following draws onto the Batch.
Expand All @@ -74,10 +73,12 @@ func (b *Batch) MakeTriangles(t Triangles) TargetTriangles {

// MakePicture returns a specialized copy of the provided Picture that draws onto this Batch.
func (b *Batch) MakePicture(p Picture) TargetPicture {
return &batchPicture{
bp := &batchPicture{
Picture: p,
b: b,
}
bp.original = bp
return bp
}

type batchTriangles struct {
Expand All @@ -89,15 +90,17 @@ type batchTriangles struct {

func (bt *batchTriangles) draw(bp *batchPicture) {
for i := range *bt.trans {
transPos := bt.b.mat.Mul3x1(mgl32.Vec3{
float32((*bt.orig)[i].Position.X()),
float32((*bt.orig)[i].Position.Y()),
transPos := mgl64.Mat3(bt.b.mat).Mul3x1(mgl64.Vec3{
(*bt.orig)[i].Position.X(),
(*bt.orig)[i].Position.Y(),
1,
})
(*bt.trans)[i].Position = V(float64(transPos.X()), float64(transPos.Y()))
(*bt.trans)[i].Color = (*bt.orig)[i].Color.Mul(bt.b.col)
(*bt.trans)[i].Picture = (*bt.orig)[i].Picture
(*bt.trans)[i].Intensity = (*bt.orig)[i].Intensity
if bp == nil {
(*bt.trans)[i].Picture = V(math.Inf(+1), math.Inf(+1))
(*bt.trans)[i].Intensity = 0
}
}

Expand All @@ -116,15 +119,21 @@ func (bt *batchTriangles) Draw() {
type batchPicture struct {
Picture

b *Batch
original *batchPicture
b *Batch
}

func (bp *batchPicture) Slice(r Rect) Picture {
return &batchPicture{
Picture: bp.Picture.Slice(r),
Picture: bp.Picture.Slice(r),
original: bp.original,
}
}

func (bp *batchPicture) Original() Picture {
return bp.original
}

func (bp *batchPicture) Draw(t TargetTriangles) {
bt := t.(*batchTriangles)
if bp.b != bt.b {
Expand Down
62 changes: 62 additions & 0 deletions geometry.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"math"
"math/cmplx"

"github.com/go-gl/mathgl/mgl64"
)

// Vec is a 2D vector type. It is unusually implemented as complex128 for convenience. Since
Expand Down Expand Up @@ -175,3 +177,63 @@ func (r Rect) Contains(u Vec) bool {
min, max := r.Pos, r.Pos+r.Size
return min.X() <= u.X() && u.X() <= max.X() && min.Y() <= u.Y() && u.Y() <= max.Y()
}

// Matrix is a 3x3 transformation matrix that can be used for all kinds of spacial transforms, such
// as movement, scaling and rotations.
//
// Matrix has a handful of useful methods, each of which adds a transformation to the matrix. For
// example:
//
// pixel.ZM.Move(pixel.V(100, 200)).Rotate(0, math.Pi/2)
//
// This code creates a Matrix that first moves everything by 100 units horizontaly and 200 units
// vertically and then rotates everything by 90 degrees around the origin.
type Matrix [9]float64

// ZM stands for Zero-Matrix which is the identity matrix. Does nothing, no transformation.
var ZM = Matrix(mgl64.Ident3())

// Move moves everything by the delta vector.
func (m Matrix) Move(delta Vec) Matrix {
m3 := mgl64.Mat3(m)
m3 = mgl64.Translate2D(delta.XY()).Mul3(m3)
return Matrix(m3)
}

// ScaleXY scales everything around a given point by the scale factor in each axis respectively.
func (m Matrix) ScaleXY(around Vec, scale Vec) Matrix {
m3 := mgl64.Mat3(m)
m3 = mgl64.Translate2D((-around).XY()).Mul3(m3)
m3 = mgl64.Scale2D(scale.XY()).Mul3(m3)
m3 = mgl64.Translate2D(around.XY()).Mul3(m3)
return Matrix(m3)
}

// Scale scales everything around a given point by the scale factor.
func (m Matrix) Scale(around Vec, scale float64) Matrix {
return m.ScaleXY(around, V(scale, scale))
}

// Rotate rotates everything around a given point by the given angle in radians.
func (m Matrix) Rotate(around Vec, angle float64) Matrix {
m3 := mgl64.Mat3(m)
m3 = mgl64.Translate2D((-around).XY()).Mul3(m3)
m3 = mgl64.Rotate3DZ(angle).Mul3(m3)
m3 = mgl64.Translate2D(around.XY()).Mul3(m3)
return Matrix(m3)
}

// Project applies all transformations added to the Matrix to a vector u and returns the result.
func (m Matrix) Project(u Vec) Vec {
m3 := mgl64.Mat3(m)
proj := m3.Mul3x1(mgl64.Vec3{u.X(), u.Y(), 1})
return V(proj.X(), proj.Y())
}

// Unproject does the inverse operation to Project.
func (m Matrix) Unproject(u Vec) Vec {
m3 := mgl64.Mat3(m)
inv := m3.Inv()
unproj := inv.Mul3x1(mgl64.Vec3{u.X(), u.Y(), 1})
return V(unproj.X(), unproj.Y())
}
7 changes: 3 additions & 4 deletions interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ type Target interface {
type BasicTarget interface {
Target

// SetTransform sets a Transform that transforms the TrianglesPosition property of all
// Triangles.
SetTransform(...Transform)
// SetMatrix sets a Matrix that every point will be projected by.
SetMatrix(Matrix)

// SetMColorMask sets a color that will be multiplied with the TrianglesColor property of all
// SetColorMask sets a color that will be multiplied with the TrianglesColor property of all
// Triangles.
SetColorMask(color.Color)
}
Expand Down
8 changes: 5 additions & 3 deletions pixelgl/canvas.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,11 @@ func (c *Canvas) MakePicture(p pixel.Picture) pixel.TargetPicture {
return cp
}

// SetTransform sets a set of Transforms that every position in triangles will be put through.
func (c *Canvas) SetTransform(t ...pixel.Transform) {
c.mat = transformToMat(t...)
// SetMatrix sets a Matrix that every point will be projected by.
func (c *Canvas) SetMatrix(m pixel.Matrix) {
for i := range m {
c.mat[i] = float32(m[i])
}
}

// SetColorMask sets a color that every color in triangles or a picture will be multiplied by.
Expand Down
9 changes: 0 additions & 9 deletions pixelgl/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,8 @@ import (
"math"

"github.com/faiface/pixel"
"github.com/go-gl/mathgl/mgl32"
)

func transformToMat(t ...pixel.Transform) mgl32.Mat3 {
mat := mgl32.Ident3()
for i := range t {
mat = mat.Mul3(t[i].Mat())
}
return mat
}

func discreteBounds(bounds pixel.Rect) (x, y, w, h int) {
x0 := int(math.Floor(bounds.Pos.X()))
y0 := int(math.Floor(bounds.Pos.Y()))
Expand Down
8 changes: 3 additions & 5 deletions pixelgl/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,11 +377,9 @@ func (w *Window) MakePicture(p pixel.Picture) pixel.TargetPicture {
return w.canvas.MakePicture(p)
}

// SetTransform sets a global transformation matrix for the Window.
//
// Transforms are applied right-to-left.
func (w *Window) SetTransform(t ...pixel.Transform) {
w.canvas.SetTransform(t...)
// SetMatrix sets a Matrix that every point will be projected by.
func (w *Window) SetMatrix(m pixel.Matrix) {
w.canvas.SetMatrix(m)
}

// SetColorMask sets a global color mask for the Window.
Expand Down
Loading

0 comments on commit f0394ec

Please sign in to comment.