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
[ ツッコむ ]
以上です。

