mirror of
https://github.com/SleepingInsomniac/pixelfaucet
synced 2025-01-31 19:57:53 +01:00
Add transform2d class
This commit is contained in:
parent
f4409b4496
commit
5f7880c171
3 changed files with 160 additions and 0 deletions
BIN
assets/bricks.png
Normal file
BIN
assets/bricks.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.5 KiB |
47
examples/affine.cr
Normal file
47
examples/affine.cr
Normal file
|
@ -0,0 +1,47 @@
|
|||
require "../src/game"
|
||||
require "../src/sprite"
|
||||
require "../src/transform2d"
|
||||
|
||||
module PF
|
||||
class Affine < Game
|
||||
@bricks : Sprite
|
||||
@transform : Transform2d = Transform2d.new
|
||||
@angle = 0.0
|
||||
|
||||
def initialize(*args, **kwargs)
|
||||
super
|
||||
@bricks = Sprite.new("./assets/bricks.png")
|
||||
end
|
||||
|
||||
def update(dt, event)
|
||||
@angle += 1.0 * dt
|
||||
end
|
||||
|
||||
def draw
|
||||
clear(50, 127, 200)
|
||||
|
||||
@transform
|
||||
.reset
|
||||
.translate(-(@bricks.size // 2))
|
||||
.rotate(@angle)
|
||||
.translate(viewport // 2)
|
||||
|
||||
b1, b2 = @transform.bounding_box(@bricks.size.x, @bricks.size.y).map(&.to_i)
|
||||
|
||||
@transform.invert
|
||||
|
||||
b1.y.upto(b2.y) do |y|
|
||||
b1.x.upto(b2.x) do |x|
|
||||
point = @transform.apply(x, y).to_i
|
||||
if point >= Vector[0, 0] && point < @bricks.size
|
||||
color = @bricks.sample(point.x, point.y)
|
||||
draw_point(x.to_i, y.to_i, color)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
game = PF::Affine.new(300, 200, 2)
|
||||
game.run!
|
113
src/transform2d.cr
Normal file
113
src/transform2d.cr
Normal file
|
@ -0,0 +1,113 @@
|
|||
require "./matrix"
|
||||
require "./vector"
|
||||
|
||||
module PF
|
||||
class Transform2d
|
||||
property matrix : Matrix(Float64, 3, 3) = Matrix[
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0,
|
||||
]
|
||||
|
||||
def initialize
|
||||
end
|
||||
|
||||
def initialize(@matrix)
|
||||
end
|
||||
|
||||
def reset
|
||||
@matrix = Matrix[
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0,
|
||||
]
|
||||
self
|
||||
end
|
||||
|
||||
def translate(x : Float | Int, y : Float | Int)
|
||||
@matrix = Matrix[
|
||||
1.0, 0.0, x.to_f64,
|
||||
0.0, 1.0, y.to_f64,
|
||||
0.0, 0.0, 1.0,
|
||||
] * @matrix
|
||||
self
|
||||
end
|
||||
|
||||
def translate(to : Vector)
|
||||
translate(to.x, to.y)
|
||||
end
|
||||
|
||||
def scale(x : Float | Int, y : Float | Int)
|
||||
@matrix = Matrix[
|
||||
x.to_f64, 0.0, 0.0,
|
||||
0.0, y.to_f64, 0.0,
|
||||
0.0, 0.0, 1.0,
|
||||
] * @matrix
|
||||
self
|
||||
end
|
||||
|
||||
def rotate(angle : Float | Int)
|
||||
cos = Math.cos(angle)
|
||||
sin = Math.sin(angle)
|
||||
@matrix = Matrix[
|
||||
cos, -sin, 0.0,
|
||||
sin, cos, 0.0,
|
||||
0.0, 0.0, 1.0,
|
||||
] * @matrix
|
||||
self
|
||||
end
|
||||
|
||||
def shear(x : Float | Int, y : Float | Int)
|
||||
@matrix = Matrix[
|
||||
1.0, x.to_f64, 0.0,
|
||||
y.to_f64, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0,
|
||||
] * @matrix
|
||||
self
|
||||
end
|
||||
|
||||
def bounding_box(x : Float | Int, y : Float | Int)
|
||||
top_left = apply(0.0, 0.0)
|
||||
top_right = apply(x.to_f, 0.0)
|
||||
bot_right = apply(x.to_f, y.to_f)
|
||||
bot_left = apply(0.0, y.to_f)
|
||||
|
||||
xs = Float64[top_left.x, top_right.x, bot_right.x, bot_left.x]
|
||||
ys = Float64[top_left.y, top_right.y, bot_right.y, bot_left.y]
|
||||
|
||||
{Vector[xs.min, ys.min], Vector[xs.max, ys.max]}
|
||||
end
|
||||
|
||||
def invert
|
||||
det = @matrix[0, 0] * (@matrix[1, 1] * @matrix[2, 2] - @matrix[1, 2] * @matrix[2, 1]) -
|
||||
@matrix[1, 0] * (@matrix[0, 1] * @matrix[2, 2] - @matrix[2, 1] * @matrix[0, 2]) +
|
||||
@matrix[2, 0] * (@matrix[0, 1] * @matrix[1, 2] - @matrix[1, 1] * @matrix[0, 2])
|
||||
|
||||
idet = 1.0 / det
|
||||
|
||||
@matrix = Matrix[
|
||||
(@matrix[1, 1] * @matrix[2, 2] - @matrix[1, 2] * @matrix[2, 1]) * idet,
|
||||
(@matrix[2, 0] * @matrix[1, 2] - @matrix[1, 0] * @matrix[2, 2]) * idet,
|
||||
(@matrix[1, 0] * @matrix[2, 1] - @matrix[2, 0] * @matrix[1, 1]) * idet,
|
||||
|
||||
(@matrix[2, 1] * @matrix[0, 2] - @matrix[0, 1] * @matrix[2, 2]) * idet,
|
||||
(@matrix[0, 0] * @matrix[2, 2] - @matrix[2, 0] * @matrix[0, 2]) * idet,
|
||||
(@matrix[0, 1] * @matrix[2, 0] - @matrix[0, 0] * @matrix[2, 1]) * idet,
|
||||
|
||||
(@matrix[0, 1] * @matrix[1, 2] - @matrix[0, 2] * @matrix[1, 1]) * idet,
|
||||
(@matrix[0, 2] * @matrix[1, 0] - @matrix[0, 0] * @matrix[1, 2]) * idet,
|
||||
(@matrix[0, 0] * @matrix[1, 1] - @matrix[0, 1] * @matrix[1, 0]) * idet,
|
||||
]
|
||||
self
|
||||
end
|
||||
|
||||
def apply(x : Float | Int, y : Float | Int)
|
||||
result = Vector[x, y, 1.0] * @matrix
|
||||
Vector[result.x, result.y]
|
||||
end
|
||||
|
||||
def apply(point : Vector)
|
||||
apply(point.x, point.y)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue