PolyViewer による3次元図形の表示

研究室のツールとして,3次元空間中に点列やその他の図形を作図したり,アニメーションを保存し簡単に動画にできる単純なプログラムを作成したので紹介します.

作成した動機

PythonRuby などのスクリプト言語から手軽に OpenGL を通したプログラムが書けたり,MATLABOctave, gnuplot などの優れたソフトウェアがあるなか,わざわざこのような似た機能をもつプログラムを作成したのには以下の理由があります.

  • 導入が容易.
    • PolyViewer はフリーです.それどころか,ソースコードをいじって好きに作り変えてもらって構いません.
    • PolyViewer はインストールする必要がありません.
    • PolyViewer はレジストリも設定ファイルも使用しないので,いらなくなったらすぐに捨てられます.
  • 理解しやすい.
    • PolyViewer が要求するファイルフォーマットは非常に単純です.
    • PolyViewer が要求するフォーマットで記述したファイルをウィンドウにドラッグ&ドロップするか,ファイルを PolyViewer に関連付けてダブルクリックするだけで表示できます.
  • ある程度高速である.
    • ネイティブコードで D3D を直接用いて描画しているため,Python などのスクリプト言語で描画するよりは高速です.

反面,次のデメリットがあります.

  • 低機能である.
    • PolyViewer には凡例や軸の目盛り,ラベルを表示する機能がありません.
    • PolyViewer にはカメラや図形の動きをユーザがプログラムする機能がありません.
  • Windows 2000 以降の OS でしか動作しない.
    • PolyViewer は Windows ME や 98 等の古い OS では動作しません.
  • 複雑な形状をした図形の描画には不向き.
    • PolyViewer でのなめらかな曲線や曲面の表示は現実的ではありません.
  • 次のプログラムのインストールが必要.
    • DirectX ランタイム(バージョン March 2008 以降).
    • Direct3D 9 に対応したディスプレイドライバ.

ファイルフォーマット

以下の描画コマンドをファイルに並べます.

  • sphere(x,y,z,cx,cy,cz,a,r,g,b,slices,stacks)
    • 座標 (x,y,z) に半径 (cx,cy,cz) の球を (a,r,g,b) 色で表示します.
    • 表示する球は,主軸を回転軸とした分割数を slices, 主軸に沿った分割数を stacks とします.
      • a はアルファ値で,不透明度を表します.
      • 0 \le a,\,r,\,g,\,b \le 1 です.0 \le a,\,r,\,g,\,b \le 255 ではないので注意してください.
      • 例えば,(a,\,r,\,g,\,b)=(0.5,\,1,\,0,\,0) は半透明の赤色を意味します.
      • 表示する球をなめらかにしたい場合には,slices と stacks を大きくしてください.
  • sphere(x,y,z,cx,cy,cz,a,r,g,b)
    • sphere(x,y,z,cx,cy,cz,a,r,g,b,32,32) と同じです.
  • sphere(x,y,z,cx,cy,cz)
    • sphere(x,y,z,cx,cy,cz,1,0,0,0) と同じです.
  • wire_sphere(x,y,z,cx,cy,cz,a,r,g,b,slices,stacks)
  • wire_sphere(x,y,z,cx,cy,cz,a,r,g,b)
  • wire_sphere(x,y,z,cx,cy,cz)
  • box(x,y,z,cx,cy,cz,a,r,g,b)
    • 座標 (x,y,z) にXYZ軸方向の辺長がそれぞれ (cx,cy,cz) の大きさの (a,r,g,b) 色のボックスを表示します.
  • box(x,y,z,cx,cy,cz)
    • box(x,y,z,cx,cy,cz,1,0,0,0) と同じです.
  • wire_box(x,y,z,cx,cy,cz,a,r,g,b)
  • wire_box(x,y,z,cx,cy,cz)
  • line(x1,y1,z1,x2,y2,z2,a,r,g,b,width,pattern)
    • (x1,y1,z1), (x2,y2,z2) を端点とする (a,r,g,b) 色の太さ width 幅の pattern パターンの線分を表示します.
    • width は浮動小数点で指定できます.width を大きくすればするほど太い線分を描画します.
    • pattern は線分の黒と白の部分をビットで指定します(ビットが立っている部分が黒になります).例えば,pattern に 0xFFFFFFFF を指定すれば直線に,0xFFFF0000 や 0xFF00FF00 や 0xF0F0F0F0 や 0xAAAAAAAA 等を指定すれば等間隔の点線に,0xFFFFFF00 などのようにすれば破線になります.
    • width に 1 以外の値を,あるいは pattern に 0xFFFFFFFF 以外の値を指定した場合,線分はスクリーン空間に描画されるため,他の図形との奥行き関係に関わらず常に最前面に描画されることに注意して下さい.
  • line(x1,y1,z1,x2,y2,z2,a,r,g,b,width)
    • line(x1,y1,z1,x2,y2,z2,a,r,g,b,width,0xFFFFFFFF) と同じです.
  • line(x1,y1,z1,x2,y2,z2,a,r,g,b)
    • line(x1,y1,z1,x2,y2,z2,a,r,g,b,1) と同じです.
  • line(x1,y1,z1,x2,y2,z2)
    • line(x1,y1,z1,x2,y2,z2,1,0,0,0) と同じです.
  • polygon(x1,y1,z1,x2,y2,z2,x3,y3,z3,a,r,g,b,tex,u1,v1,u2,v2,u3,v3)
    • (x1,y1,z1), (x2,y2,z2), (x3,y3,z3) を頂点とする (a,r,g,b) 色の三角形を表示します.また,三角形の内部を指定したテクスチャファイル tex とテクスチャ座標 (u1,v1), (u2,v2), (u3,v3) でテクスチャマッピングします.
    • テクスチャとして読み込める画像の形式は bmp, dds, dib, hdr, jpg, pfm, png, ppm, tga です.
    • テクスチャ座標は画像の左上を原点 (u,\,v)=(0,\,0) とし,右方向が u,下方向が v,右下が (u,\,v)=(1,\,1) になります.
  • polygon(x1,y1,z1,x2,y2,z2,x3,y3,z3,a,r,g,b)
    • (x1,y1,z1), (x2,y2,z2), (x3,y3,z3) を頂点とする (a,r,g,b) 色の三角形を表示します.
  • polygon(x1,y1,z1,x2,y2,z2,x3,y3,z3)
    • polygon(x1,y1,z1,x2,y2,z2,x3,y3,z3,1,0,0,0) と同じです.

# もしくは // で始まる行はコメントとみなします.

BNF(のようなもの)

<program> ::= <command list>
<command list> ::= <command>*
<command> ::= <sphere> | <wire_sphere> | <box> | <wire_box> | <line> | <polygon>
<sphere> ::= sphere(num,num,num,num,num,num,num,num,num,num) | sphere(num,num,num,num,num,num) | sphere(num,num,num,num,num,num,num,num,num,num,num,num)
<wire_sphere> ::= wire_sphere(num,num,num,num,num,num,num,num,num,num) | wire_sphere(num,num,num,num,num,num) | wire_sphere(num,num,num,num,num,num,num,num,num,num,num,num)
<box> ::= box(num,num,num,num,num,num,num,num,num,num) | box(num,num,num,num,num,num)
<wire_box> ::= wire_box(num,num,num,num,num,num,num,num,num,num) | wire_box(num,num,num,num,num,num)
<line> ::= line(num,num,num,num,num,num,num,num,num,num,num,num) | line(num,num,num,num,num,num,num,num,num,num,num) | line(num,num,num,num,num,num,num,num,num,num) | line(num,num,num,num,num,num)
<polygon> ::= polygon(num,num,num,num,num,num,num,num,num,num,num,num,num,str,num,num,num,num,num,num) | polygon(num,num,num,num,num,num,num,num,num,num,num,num,num) | polygon(num,num,num,num,num,num,num,num,num)
<num> ::= 数字
<str> ::= 文字列

実行例

(下記の内容のファイルを作成し,PolyViewer で開いて下さい)

sample1.plv
wire_sphere(0,0,0,2,2,2,1,0,0,0)
box(0,0,0,4,4,4,0.2,1,0,0)

line(-2,2,2,2,2,2)
line(-2,2,-2,2,2,-2)
line(-2,-2,2,2,-2,2)
line(-2,-2,-2,2,-2,-2)

line(-2,2,2,-2,-2,2)
line(2,2,2,2,-2,2)
line(-2,2,-2,-2,-2,-2)
line(2,2,-2,2,-2,-2)

line(2,2,-2,2,2,2)
line(-2,2,-2,-2,2,2)
line(2,-2,-2,2,-2,2)
line(-2,-2,-2,-2,-2,2)


sample2.plv
polygon(2,2,-2,2,2,2,2,-2,2,0.5,1,1,1,"tex.png",0,0,1,0,1,1)
polygon(2,2,-2,2,-2,2,2,-2,-2,0.5,1,1,1,"tex.png",0,0,1,1,0,1)

polygon(-2,2,2,-2,2,-2,-2,-2,-2,0.5,1,1,1,"tex.png",0,0,1,0,1,1)
polygon(-2,2,2,-2,-2,-2,-2,-2,2,0.5,1,1,1,"tex.png",0,0,1,1,0,1)

polygon(-2,2,2,2,2,2,2,2,-2,0.5,1,1,1,"tex.png",0,0,1,0,1,1)
polygon(-2,2,2,2,2,-2,-2,2,-2,0.5,1,1,1,"tex.png",0,0,1,1,0,1)

polygon(-2,-2,2,2,-2,2,2,-2,-2,0.5,1,1,1,"tex.png",0,0,1,0,1,1)
polygon(-2,-2,2,2,-2,-2,-2,-2,-2,0.5,1,1,1,"tex.png",0,0,1,1,0,1)

polygon(-2,2,2,2,2,2,2,-2,2,0.5,1,1,1,"tex.png",0,0,1,0,1,1)
polygon(-2,2,2,2,-2,2,-2,-2,2,0.5,1,1,1,"tex.png",0,0,1,1,0,1)

polygon(-2,2,-2,2,2,-2,2,-2,-2,0.5,1,1,1,"tex.png",0,0,1,0,1,1)
polygon(-2,2,-2,2,-2,-2,-2,-2,-2,0.5,1,1,1,"tex.png",0,0,1,1,0,1)


操作

  • 左クリック&ドラッグ
    • 図形を回転します.
  • 右クリック or ホイールクリック&ドラッグ
    • 図形を移動します.
  • W,S,A,D
    • カメラをZX平面上で移動します.
  • ↑,↓
    • カメラをY軸上で移動します.
  • ←,→
    • 図形の原点からの距離を95%に縮小,あるいは105%に拡大します.
  • C
    • カメラ(位置,姿勢,視野角)を初期化します.
  • N
    • 図形の原点からの距離の最大値が5になるように縮小,あるいは拡大します.
  • G
    • 図形の重心が原点にくるように移動します.
  • マウスホイール
    • 視野角を変更します.
  • ALT+Enter
    • 全画面モードとウィンドウモードを切り替えます.

表示

  • 赤色,緑色,青色で表示されている軸が順にX,Y,Z軸です.
  • 格子線を座標5毎に表示しています.
  • 軸や格子線はメニューにより表示,あるいは非表示にできます.