mieki256's diary



2016/02/13() [n年前の日記]

#1 [prog][dxruby] 曲線について調べていたり

ベジェ曲線とか、エルミート曲線とか、Catmull-Romスプライン曲線とか、そのあたりについて調べてたり。そのあたりを使って道路を自動生成できないものかなと。

_1.エルミート曲線軌道
_エルミート曲線 | ゲームを作りたい人のためのソースコード集
_デジタル・フロンティア-Digital Frontier | DF TALK | スプライン曲線の話
_Catmull-Rom 補間 - blog.seyself.com
_その34 スプライン曲線上をおおよそ等速で移動する(丸み不均一スプライン)
_【なめらかな曲線補間】-Nonuniform spline- | 株式会社ヘキサドライブ | HEXADRIVE | ゲーム制作を中心としたコンテンツクリエイト会社

丸み不均一スプラインなるものがレースゲームの軌道等には向いているという話も見かけたのだけど。とある書籍でしか解説されてないらしくて、手元で実験できなかった。

DXRubyでエルミート曲線を試してみたり。 :

こんな感じに。
hermite_curve_ss.png
起動後、ウインドウ内でマウスクリックすれば、始点、始点ベクトル、終点、終点ベクトル、の順で位置を指定できる。

ソースは、こんな感じに。

_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_ss.png
起動後、ウインドウ内でマウスクリックすれば、各点の位置を順々に指定できる。

ソースはこんな感じに。

_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

#2 [nitijyou] 体調がよろしくない

鼻水は治まってきたけど、相変わらず咳が出る。

以上、1 日分です。

過去ログ表示

Prev - 2016/02 - Next
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project