2016/02/13(土) [n年前の日記]
#1 [prog][dxruby] 曲線について調べていたり
ベジェ曲線とか、エルミート曲線とか、Catmull-Romスプライン曲線とか、そのあたりについて調べてたり。そのあたりを使って道路を自動生成できないものかなと。
_1.エルミート曲線軌道
_エルミート曲線 | ゲームを作りたい人のためのソースコード集
_デジタル・フロンティア-Digital Frontier | DF TALK | スプライン曲線の話
_Catmull-Rom 補間 - blog.seyself.com
_その34 スプライン曲線上をおおよそ等速で移動する(丸み不均一スプライン)
_【なめらかな曲線補間】-Nonuniform spline- | 株式会社ヘキサドライブ | HEXADRIVE | ゲーム制作を中心としたコンテンツクリエイト会社
丸み不均一スプラインなるものがレースゲームの軌道等には向いているという話も見かけたのだけど。とある書籍でしか解説されてないらしくて、手元で実験できなかった。
_1.エルミート曲線軌道
_エルミート曲線 | ゲームを作りたい人のためのソースコード集
_デジタル・フロンティア-Digital Frontier | DF TALK | スプライン曲線の話
_Catmull-Rom 補間 - blog.seyself.com
_その34 スプライン曲線上をおおよそ等速で移動する(丸み不均一スプライン)
_【なめらかな曲線補間】-Nonuniform spline- | 株式会社ヘキサドライブ | HEXADRIVE | ゲーム制作を中心としたコンテンツクリエイト会社
丸み不均一スプラインなるものがレースゲームの軌道等には向いているという話も見かけたのだけど。とある書籍でしか解説されてないらしくて、手元で実験できなかった。
◎ DXRubyでエルミート曲線を試してみたり。 :
こんな感じに。
起動後、ウインドウ内でマウスクリックすれば、始点、始点ベクトル、終点、終点ベクトル、の順で位置を指定できる。
ソースは、こんな感じに。
_hermite_curve.rb
ソースは、こんな感じに。
_hermite_curve.rb
# エルミート曲線をDXRubyで描画してみる # # 参考ページ # # 1.エルミート曲線軌道 # http://1st.geocities.jp/shift486909/program/hermite.html # # 2005-09-18 - ゲームプログラムめも日記 # http://d.hatena.ne.jp/kenmo/20050918#p1 # # エルミート曲線 | ゲームを作りたい人のためのソースコード集 # http://blog.higashisanmyaku.jp/?eid=123 require 'dxruby' Window.caption = "Hermite Curve" fnt = Font.new(12) # 始点、終点 p = [ [100, 200], [500, 300] ] # 始点ベクトル、終点ベクトル v = [ [50, -150], [20, -200] ] mode = 0 # 四角を描画 def draw_dot(x, y, size, color) x1, y1 = x - size, y - size x2, y2 = x + size, y + size Window.drawBoxFill(x1, y1, x2, y2, color) end # ベクトルを描画 def draw_vec(x, y, vx, vy, color) Window.drawLine(x, y, x + vx, y + vy, color) end Window.loop do break if Input.keyPush?(K_ESCAPE) if Input.mousePush?(M_LBUTTON) # マウスの左ボタンが押されたので各座標を指定する mx, my = Input.mousePosX.to_f, Input.mousePosY.to_f case mode when 0 p[0] = [mx, my] when 1 v[0] = [mx - p[0][0], my - p[0][1]] when 2 p[1] = [mx, my] when 3 v[1] = [mx - p[1][0], my - p[1][1]] end mode += 1 mode = 0 if mode >= 4 end p0x, p0y = p[0] p1x, p1y = p[1] v0x, v0y = v[0] v1x, v1y = v[1] # 始点、終点、始点ベクトル、終点ベクトルを描画 draw_dot(p0x, p0y, 2, [255, 0, 0]) draw_dot(p1x, p1y, 2, [255, 0, 0]) draw_vec(p0x, p0y, v0x, v0y, [0, 128, 255]) draw_vec(p1x, p1y, v1x, v1y, [0, 128, 255]) d = 48 # 分解度 d.times do |i| t1 = (0.0 + i) / (d - 1.0) t2= t1 * t1 t3= t1 * t1 * t1 mp0= t3 * 2.0 - t2 * 3.0 + 1.0 mv0= t3 - t2 * 2.0 + t1 mp1= -t3 * 2.0 + t2 * 3.0 mv1= t3 - t2 x= p0x * mp0 + v0x * mv0 + p1x * mp1 + v1x * mv1 y= p0y * mp0 + v0y * mv0 + p1y * mp1 + v1y * mv1 draw_dot(x, y, 1, C_WHITE) end Window.drawFont(4, 4, "Please click [#{mode}]", fnt) end
◎ DXRubyでCatmull-Romスプライン曲線を試してみたり。 :
こんな感じに。
起動後、ウインドウ内でマウスクリックすれば、各点の位置を順々に指定できる。
ソースはこんな感じに。
_catmul_rom_curve.rb.txt
ソースはこんな感じに。
_catmul_rom_curve.rb.txt
# DXRubyでCatmull-Romスプライン曲線を描画してみる # # Catmull-Rom 補間 - blog.seyself.com # http://blog.seyself.com/2008/06/post_2008061020.html # # デジタル・フロンティア-Digital Frontier | DF TALK | スプライン曲線の話 # http://www.dfx.co.jp/dftalk/?p=10576 require 'dxruby' Window.caption = "Catmul-Rom Spline Curve" # Catmul-Rom補間の値を取得 # # @param p0 [Number] 値0 # @param p1 [Number] 値1 # @param p2 [Number] 値2 # @param p3 [Number] 値3 # @param t [Number] t値 (0.0 - 1.0) # @return [Number] 結果 (p1 - p2 の間で値を返す) def get_catmul_rom(p0, p1, p2, p3, t) t = t.to_f v0 = (p2 - p0).to_f * 0.5 v1 = (p3 - p1).to_f * 0.5 t2 = t * t t3 = t2 * t return ((p1 - p2) * 2 + v0 + v1) * t3 + \ ((p2 - p1) * 3 - 2 * v0 - v1) * t2 + v0 * t + p1 end # 四角(塗り潰し)を描画 def draw_dot(x, y, sz, color) Window.drawBoxFill(x - sz, y - sz, x + sz, y +sz, color) end # 四角(線)を描画 def draw_box(x, y, sz, color) x1, y1 = x - sz, y - sz x2, y2 = x + sz, y + sz Window.drawLine(x1, y1, x2, y1, color) Window.drawLine(x2, y1, x2, y2, color) Window.drawLine(x1, y1, x1, y2, color) Window.drawLine(x1, y2, x2, y2, color) end fnt = Font.new(12) # 制御点を初期化 x = 16 y = 64 dx = 120 dy = 40 p = [] 8.times do |i| p.push([x, y]) x += dx y += dy end mode = 0 Window.resize(1024, 768) # メインループ Window.loop do break if Input.keyPush?(K_ESCAPE) if Input.mousePush?(M_LBUTTON) # マウスボタンが押されたので制御点の座標を変更 p[mode] = [Input.mousePosX.to_f, Input.mousePosY.to_f] mode += 1 mode = 0 if mode >= p.length end # 制御点を描画 p.each_with_index do |c, i| x, y = c draw_dot(x, y, 3, C_RED) draw_box(x, y, 6, C_CYAN) if i == mode end # Catmul-Rom Spline を描画 (p.length - 3).times do |i| n0, n1, n2, n3 = i, i+1, i+2, i+3 x0, x1, x2, x3 = p[n0][0], p[n1][0], p[n2][0], p[n3][0] y0, y1, y2, y3 = p[n0][1], p[n1][1], p[n2][1], p[n3][1] 0.step(1.0 - 0.05, 0.05) do |t| x = get_catmul_rom(x0, x1, x2, x3, t) y = get_catmul_rom(y0, y1, y2, y3, t) draw_dot(x, y, 1, C_WHITE) end end Window.drawFont(4, 4, "Please click [#{mode}]", fnt) end
[ ツッコむ ]
以上です。