About this Blog

This Blog has English posts and Japanese posts. About Mac, iOS, Objective-C, and so on.

2013年4月25日木曜日

[ruby-opengl] 回転体 Advanced(回転角度によって半径を変えられる)

Z軸周りの回転体ならば、普通は、r=f(z)という関数を考えてそれをぐるっと回転させますが、
このメソッドでは、回転角度に応じて関数f(z)を変えて回転体を描くことができます。

例えば、theta=0のときはf(z)が定数で、theta=PIのときはf(z)は2次関数であるようにすれば、人のふくらはぎのような形も簡単に。



コードはこちら。
gl_cocoon.rb
require "opengl"

module GLUT
  def GLUT.Cocoon(height, slice, stack)
    return unless block_given?
    zStep = height/slice.to_f
    tStep = Math::PI/stack
    0.step(height-zStep+0.0001, zStep){|z|
       GL.Begin(GL::QUAD_STRIP)
      (-Math::PI).step(Math::PI+0.0001, tStep){|theta|
         r1 = yield(z, theta, tStep)
         r2 = yield(z+zStep, theta+tStep, tStep)
         phi = atan(zStep/(r2-r1).abs)
         GL.Normal(cos(theta)*sin(phi), sin(theta)*sin(phi), cos(phi))
         GL.Vertex(r1*cos(theta), r1*sin(theta), z)
         GL.Vertex(r2*cos(theta+tStep), r2*sin(theta+tStep), z+zStep)
      }
      GL.End
    }
  end


使い方
Z軸周りに回転します。
heightが高さ(Z軸方向の長さ)
sliceが高さ方向の刻み回数
stackが周方向の刻み回数
です。
渡すブロック内で、回転半径を返すようにしてください。

サンプル1
GLUT.Cocoon(6.0, 20, 20){|z,theta,tStep|
  # r = -a*z*(z-8) です。
  # 回転角が PI/3から PI*2/3の時はa=0.07、
  # それ以外の時は、a=0.1です。
  # 新宿のコクーンタワーのような形になります。
  case theta
  when Math::PI/3 .. 2*Math::PI/3
    -0.07*z*(z-8)
  else
    -0.1*z*(z-8)
  end
}



サンプル2 人の脛のような形も簡単に。
GLUT.Cocoon(6.0, 15, 15){|z,theta,tStep|
  # thetaは-PIからPIまで取るので、tは1〜0〜1と連続的に変化します。
  t = (theta/Math::PI).abs
  # tに1.0(定数)をかけ、1-tに-0.1*z^2 + 0.5*z + 1をかけることで、
  # f(z)は直線から2次曲線へと連続的に変化することになります。
  1.0*t + (1-t)*(-0.1*z*z + 0.5*z+1)
}


視点や光の設定などは省いています。このままでは表示されないので注意。

0 件のコメント:

コメントを投稿