Skip to content

Instantly share code, notes, and snippets.

@mirichi

mirichi/orevg.rb Secret

Created December 30, 2016 13:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mirichi/5dc3c9b4b0791cbc567da17c78dc2b96 to your computer and use it in GitHub Desktop.
Save mirichi/5dc3c9b4b0791cbc567da17c78dc2b96 to your computer and use it in GitHub Desktop.
構造をNanoVG的に変更
require 'dxruby'
# ラスタライズ結果を見やすく描画する
module Viewer
def self.draw(image, triangles)
s = 400.0 / image.width
Window.mag_filter = TEXF_POINT
Window.draw_ex(50, 50, image, scale_x:s, scale_y:s, center_x:0, center_y:0)
image.width.times do |c|
Window.draw_line(c * s + 50, 50, c * s + 50, image.width * s + 50, [100, 100, 100])
Window.draw_line(50, c * s + 50, image.width * s + 50, c * s + 50, [100, 100, 100])
end
triangles.each do |ary|
x1, y1, x2, y2, x3, y3 = *ary
Window.draw_line(x1 * s + 50, y1 * s + 50, x2 * s + 50, y2 * s + 50, C_RED)
Window.draw_line(x2 * s + 50, y2 * s + 50, x3 * s + 50, y3 * s + 50, C_RED)
Window.draw_line(x3 * s + 50, y3 * s + 50, x1 * s + 50, y1 * s + 50, C_RED)
end
end
end
class OreVG
attr_accessor :image, :triangles
class MoveTo < Struct.new(:x, :y);end
class LineTo < Struct.new(:x, :y);end
class Point < Struct.new(:x, :y);end
def initialize(l)
@image = Image.new(l, l, C_WHITE)
@triangles = []
@commands = []
@width = 1
@points = []
end
# EdgeFunction
# E(x, y) = (x - X) * dy - (y - Y) * dx
# E(x, y) <= 0で中と判定。3つのエッジの内側であれば塗る。
private def rasterize(x1, y1, x2, y2, x3, y3)
dx12 = x2 - x1
dy12 = y2 - y1
dx23 = x3 - x2
dy23 = y3 - y2
dx31 = x1 - x3
dy31 = y1 - y3
# 基点。ピクセルの中心で計算する。
e1 = (0.5 - x1) * dy12 - (0.5 - y1) * dx12
e2 = (0.5 - x2) * dy23 - (0.5 - y2) * dx23
e3 = (0.5 - x3) * dy31 - (0.5 - y3) * dx31
@image.height.times do |y|
et1 = e1
et2 = e2
et3 = e3
@image.width.times do |x|
yield x, y if et1 <= 0 and et2 <= 0 and et3 <= 0
et1 += dy12
et2 += dy23
et3 += dy31
end
e1 -= dx12
e2 -= dx23
e3 -= dx31
end
end
private def triangle(x1, y1, x2, y2, x3, y3)
rasterize(x1, y1, x2, y2, x3, y3) do |x, y|
@image[x,y] = [100, 100, 255]
end
@triangles << [x1, y1, x2, y2, x3, y3]
end
private def line(x1, y1, x2, y2)
dx = x2 - x1
dy = y2 - y1
len = Math.sqrt(dx * dx + dy * dy)
dmx = dx / len
dmy = dy / len
w = @width * 0.5
tx1 = x1 + dmy * w
ty1 = y1 - dmx * w
tx2 = x1 - dmy * w
ty2 = y1 + dmx * w
tx3 = x2 + dmy * w
ty3 = y2 - dmx * w
tx4 = x2 - dmy * w
ty4 = y2 + dmx * w
triangle(tx1, ty1, tx3, ty3, tx2, ty2)
triangle(tx2, ty2, tx3, ty3, tx4, ty4)
end
private def append_commands(cmd)
@commands << cmd
end
private def flatten_paths
@commands.each do |cmd|
case cmd
when MoveTo
@points << Point.new(cmd.x, cmd.y)
when LineTo
@points << Point.new(cmd.x, cmd.y)
end
end
end
def move_to(x, y)
append_commands(MoveTo.new(x, y))
end
def line_to(x, y)
append_commands(LineTo.new(x, y))
end
def width=(w)
@width = w
end
def stroke
flatten_paths
@points.each_cons(2) do |p1, p2|
line(p1.x, p1.y, p2.x, p2.y)
end
end
end
vg = OreVG.new(50)
vg.move_to(2, 5)
vg.line_to(42, 25)
vg.line_to(22, 40)
vg.width = 10
vg.stroke
Window.loop do
Viewer.draw(vg.image, vg.triangles)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment