[CG実習 >  CG実習 課題(2025) >  [課題11] 恒星系のアニメーション ]

[課題11] 恒星系のアニメーション

課題

以下に示す仕様を満たすような単純にモデル化された恒星系を描いてアニメーションを行うプログラムを作成して,プログラムを提出してください.

仕様

プログラムは次の仕様を満たすようにしてください. その他の機能を追加することも自由です.

また次のように単純化したモデルを考えることにします. 余裕があれば,より複雑なモデルを考えてもよいでしょう.

なお今回作成する恒星系はあくまでも動きを見るもので,プログラムでは光源は恒星とは独立して定めてよいことにします.

課題の進め方

課題を行うにあたって,次のテンプレートファイルをダウンロードして利用してください.

このテンプレートでは視点はz軸上(z > 0)にあって,原点をとらえるようになっています.

またサンプルプログラムも参考にしてください.

恒星系を組み立てるには,モデル・ビュー変換行列のスタックをうまく利用して,階層的なモデリングを行います. GL.Translate,GL.RotateとGL.PushMatrix,GL.PopMatrixをうまく組み合わせてください. なお,後に記述した変換から先に適用されることに注意してください.

恒星系の構築の指針

衛星をもつ惑星系を含む恒星系を構築する際には, 恒星系の中に惑星系を配置することになります. 惑星系は恒星を中心に周回します. また惑星系内では,衛星が惑星を中心として公転することになります.

そこで恒星系を構築するには,まず恒星を基準にして,惑星系の配置を考えます. 次に惑星系においては,惑星を基準として,衛星の配置を考えます.

恒星系の各惑星系(衛星が存在しない惑星もありえます)には,それぞれ恒星を基準とした変換をかけます.惑星系同士は独立していて,それらの配置の間には関係はありません. そこで一つの惑星系を配置したら,その描画に用いた変換を外してから次の惑星系を配置します. このためにPushMatrix,PopMatrixを使います.

星の描き方

テンプレートファイルには星を描くメソッドstarが定義されています. starメソッドでは,マテリアルを指定して,球面として星を描きます.


  ## 恒星のデータ
  SUN_RADIUS=0.7  # 半径
  SUN_SLICES= 20  # 経線の本数
  SUN_STACKS= SUN_SLICES # 緯線の本数
  # マテリアル
  SUN_MATERIAL={ 
    :ambient=>[0.8,0.2,0.1],  # :ambient =>[Ra,Ga,Ba] 環境光反射率
    :diffuse=>[1.0,0.2,0.1],  # :diffuse =>[Rd,Gd,Bd] 拡散光反射率
    :specular=>[0.7,0.2,0.1], # :specular=>[Rs,Gs,Bs] 鏡面光反射率
    :shininess=>0.5 # 鏡面度/128→[0,1]
  }

  def star(size,slices,stacks,material)
   # 材質の設定
    GLMaterial.set(material)
    # 球面の描画
    GLUT.SolidSphere(size,slices,stacks)
  end

  display = Proc.new {

    # 恒星を描画
    star(SUN_RADIUS,SUN_SLICES,SUN_STACKS,SUN_MATERIAL)

  }

球面の描画方法

球面は多角形の集まりで近似的に表現されます. (原点中心の)球面を描くには次のようにします.


   GLUT.SolidSphere(radius,slices,stacks)

radiusは球の半径です.slices,stacksは近似の度合いを示します. これら二つの値を大きくすれば,より細かく近似することになります. 一方小さくした場合には粗い近似になります. 具体的にはslicesとstacksで与えられた数(整数)に基づいて,経線と緯線を等間隔に引いて,それらの線で区切られた一つ一つの区画を面として描くことになります. あまり細かくしすぎると描画にかかる時間が不必要に長くなりますので注意してください.

マテリアルの指定方法

今回のテンプレートでは,マテリアルは次のように定義して利用できるようになっています. 上の例も参照してください.

  # マテリアルの定義
  マテリアル名={
    :ambient=>[Ra,Ga,Ba], # 環境光反射率(赤,緑,青)
    :diffuse=>[Rd,Gd,Bd], # 拡散光反射率(赤,緑,青)
    :specular=>[Rs,Gs,Bs] # 鏡面光反射率(赤,緑,青)
    :shininess=>S # S==鏡面度/128 ∈ [0,1]
  }

  # マテリアルの設定
  GLMaterial.set(マテリアル名) 

公転軌道の描き方

公転軌道はシェーディングをOFFにして描きます. テンプレートには原点を中心として平面z=0上に白い円を描くメソッドorbitが定義されています. 円を描くのにMGLUtils.circleメソッドを使っています.


  def orbit(size)
    GL.Disable(GL::LIGHTING)    # Lighting/Shading OFF
    GL.Color(COLOR_ORBIT)       # 色の設定
    MGLUtils.circle([0,0],size) # 円を描く
    GL.Enable(GL::LIGHTING)     # Lighting/Shading ON
  end

  #### 描画コールバック ########
  display = Proc.new {

    # 公転軌道を描くテスト
    orbit(SUN_RADIUS*5) 

  }

なおMGLUtils.circleメソッドは標準のOpenGLでは定義されていません. MGLUtils.circleメソッドを使わないで円を描くには,GL::LINE_LOOPを使います.


  GL.Disable(GL::LIGHTING)
  GL.Begin(GL::LINE_LOOP)

    # 繰り返しを使って,公転軌道上の頂点を順に発生させる

  GL.End()
  GL.Enable(GL::LIGHTING)

球面の場合と同様に必要以上に多くの頂点をとると描画にかかる時間が不必要に長くなりますので注意してください.

[CG実習 >  CG実習 課題(2025) >  [課題11] 恒星系のアニメーション ]