AVPRG Home / Members / Akira Kageyama / VFIVE / manual

VFIVEユーザーズマニュアル

更新履歴


VFIVEとは

VFIVE (Vector Field Interactive Visualization Environment) は、 CAVE型VRシステムを用いて3次元データを可視化し、 解析するための汎用プログラムである。 ユーザーは自分でプログラミングする手間なしに (コマンド一つ打つだけで)、 自分のシミュレーションデータをすぐに仮想現実化して観察することが出来る。 このプログラムの主要な目的は、 複雑な3次元ベクトル場を3次元のまま解析することである。 このために、 仮想現実(VR)技術の持つ立体感や対話性、 没入感などの特徴を利用した様々な可視化モジュールを開発した。 VFIVEには簡単なメニュー機能があり、 様々な可視化機能やその対象となる場を容易に選択することが可能である。 VFIVEにはまた、曲線や曲面の座標データをオプションとして渡すことによって、 それらの物体をVR空間内に自動的に構成し、 表示させる機能も持つ。 この機能は、 各ユーザーがそれぞれ独自の可視化手法とデータを使ってあらかじめ計算 (定義)済みのオブジェクトを表示させたい場合等に便利である。

VFIVEは本来、 シミュレーションの解析に利用することを想定して開発が始められたが、 入力データ形式やその可視化機能には汎用性があるため、 様々な分野の実験や観測データの解析等にも応用できる。

データ

VFIVEの公開バージョン(Ver.3.72)で解析可能なデータの定義領域は直方体である。 座標はカーテシアン(x,y,z)で与える。 x,y,zの各方向のグリッドは不等間隔でもよい。 一般の曲線座標系上でのデータをVFIVEで可視化する時には、 あらかじめデータをカーテシアン座標上にマップしたものを用意して頂きたい。

ユーザがVFIVEに与える入力データファイルは現在以下のものがある。 それぞれのデータフォーマットについては後述する。

     
  1. [必須] 座標データファイル (各グリッドのx,y,z座標値)
  2.  
  3. [必須] ベクトル場データファイル (複数の場の解析が可能)
  4.  
  5. [必須] スカラー場データファイル (複数の場の解析が可能)
  6.  
  7. [オプション] 曲線データファイル (あらかじめ計算した曲線を表示する)
  8.  
  9. [オプション] 曲面データファイル (あらかじめ計算した曲面を表示する)

与えられる場の数には以下の制限がある。

フォーマット

グリッドの座標と場のデータは次のテキストファイルに記述する。 以下に2つのベクトル場(磁場と速度場)と 2つのスカラー場(圧力場と密度場)の可視化のための サンプルファイル "test.v5"を示す。 (ファイルの拡張子は何でも良い。)


+------------------------------------------------------------------+
|                    入力ファイルの例    始まり                    

% cat test.v5

# test.v5    ('#' で始まる行はコメント)
#
# 左にキーワード(1カラム目から)   スペースが任意個続いて  パラメータ値
# 
n1          60
n2          70
n3          80
nvec        2
nscal       2
scale       1.0
shift_x     0.0
shift_y     0.0
shift_z     0.0
xfile       /home/guest/test/test-coord.x
yfile       /home/guest/test/test-coord.y
zfile       /home/guest/test/test-coord.z
vect0_label MAGNETIC\nField
vect0x      /home/guest/test/test-magnetic.x
vect0y      /home/guest/test/test-magnetic.y
vect0z      /home/guest/test/test-magnetic.z
vect1_label VELOCITY\nField
vect1x      /home/guest/test/test-velocity.x
vect1y      /home/guest/test/test-velocity.y
vect1z      /home/guest/test/test-velocity.z
scal0_label PRESSURE
scal0       /home/guest/test/test-pressure
scal1_label DENSITY
scal1       /home/guest/test/test-density

|                    入力ファイルの例    終わり                    
+------------------------------------------------------------------+

それぞれのパラメータの意味をコメントの形で説明する。


+------------------------------------------------------------------+
|           コメント付き  入力ファイルの例    始まり               

# test.v5    ('#' で始まる行はコメント)
#
# ... x方向のグリッド数
n1         60
# ... y方向のグリッド数
n2         70
# ... z方向のグリッド数
n3         80
# ... ベクトル場の数 2 (磁場と速度場)
nvec       2
# ... スカラー場の数 2 (圧力と密度)
nscal      2
# ... スケール変換パラメータ (シミュレーション座標系での値に
# ... この値を乗じたものがメートルのスケールで CAVE の部屋に表示される。
scale     1.0
# ... 座標平行移動パラメータ (プログラム開始時にこの距離だけ原点を
#     x方向に移動してからCAVEに表示する。単位はシミュレーション座標系で。)
shift_x   0.0
# ... 同様にyとz方向の移動量
shift_y   0.0
shift_z   0.0
# ... x座標値ファイル(倍精度実数。書き方は後述)
xfile      /home/guest/test/test-coord.x
# ... y座標値ファイル(倍精度実数。書き方は後述)
yfile      /home/guest/test/test-coord.y
# ... z座標値ファイル(倍精度実数。書き方は後述)
zfile      /home/guest/test/test-coord.z
# ... 最初のベクトル場のラベル(メニューに書かれる)。  '\n'は改行
vect0_label MAGNETIC\nField
# ... 最初のベクトル場のx成分(倍精度実数。書き方は後述)
vect0x     /home/guest/test/test-magnetic.x
# ... 最初のベクトル場のy成分(倍精度実数。書き方は後述)
vect0y     /home/guest/test/test-magnetic.y
# ... 最初のベクトル場のz成分(倍精度実数。書き方は後述)
vect0z     /home/guest/test/test-magnetic.z
# ... 2番目ベクトル場のラベル(メニューに書かれる)。  '\n'は改行
vect1_label VELOCITY\nField
# ... 2番目のベクトル場のx成分(倍精度実数。書き方は後述)
vect1x     /home/guest/test/test-velocity.x
# ... 2番目のベクトル場のy成分(倍精度実数。書き方は後述)
vect1y     /home/guest/test/test-velocity.y
# ... 2番目のベクトル場のz成分(倍精度実数。書き方は後述)
vect1z     /home/guest/test/test-velocity.z
# ... 最初のスカラー場のラベル(メニューに書かれる)
scal0_label PRESSURE
# ... 最初のスカラー場(倍精度実数。書き方は後述)
scal0      /home/guest/test/test-pressure
# ... 2番目のスカラー場のラベル(メニューに書かれる)
scal1_label DENSITY
# ... 2番目のスカラー場(倍精度実数。書き方は後述)
scal1      /home/guest/test/test-density
# -- 以上。

|           コメント付き  入力ファイルの例    終わり               
+------------------------------------------------------------------+

座標データ

座標データファイル (上の例 "test.v5" では /home/guest/test/test-coord.x 他二つ。) は、

  1. Fortranの書式なし出力(バイナリデータ。VFIVEは、データの先頭4バイトを読み飛ばす)
  2. 倍精度実数(C/C++言語のdouble型)

で用意する。下に(倍精度実数の)サンプルプログラムを示す。

+------------------------------------------------------+     
| 座標データファイル生成プログラムの例 (Fortran) 始まり

      implicit none
      integer nx, ny, nz
      parameter(nx=60,ny=70,nz=80)
      integer i, j, k
      real*8 xpos(nx), ypos(ny), zpos(nz)
      character*50 xfile, yfile, zfile
c
      xfile = "/home/guest/test/test-coord.x"
      yfile = "/home/guest/test/test-coord.y"
      zfile = "/home/guest/test/test-coord.z"
c
      do i = 1 , nx
        xpos(i) = x座標の定義。不等間隔グリッドも可。
      end do
c
      do j = 1 , ny
        ypos(j) = y座標の定義。不等間隔グリッドも可。
      end do
c
      do k = 1 , nz
        zpos(k) = z座標の定義。不等間隔グリッドも可。
      end do
c
      open(11,file=xfile,form='unformatted')
      open(12,file=yfile,form='unformatted')
      open(13,file=zfile,form='unformatted')
        write(11) xpos
        write(12) ypos
        write(13) zpos
      close(13)
      close(12)
      close(11)
c
      stop
      end

| 座標データファイル生成プログラムの例(Fortran) 終わり
+------------------------------------------------------+
+----------------------------------------------------+
| 座標データファイル生成プログラムの例 (C言語) 始まり 

#include <stdio.h>
#include <stdlib.h>

const int nx = 60;
const int ny = 70;
const int nz = 80;

int
main(int argc, char **argv)
{
      int i, j, k;
      double xpos[nx], ypos[ny], zpos[nz];
      char dummy[4];
      FILE *fp;

      char xfile[] = "/home/guest/test/test-coord.x";
      char yfile[] = "/home/guest/test/test-coord.y";
      char zfile[] = "/home/guest/test/test-coord.z";

      for(i = 0; i < nx ; i++){
        xpos[i] = x座標の定義。不等間隔グリッドも可。;
      }

      for(j = 0; j < ny; j++){
        ypos[j] = y座標の定義。不等間隔グリッドも可。;
      }

      for(k = 0; k < nz; k++){
        zpos[k] = z座標の定義。不等間隔グリッドも可。;
      }

      if((fp=fopen(xfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(xpos, sizeof(double), nx, fp);
      fclose(fp);

      if((fp=fopen(yfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(ypos, sizeof(double), ny, fp);
      fclose(fp);

      if((fp=fopen(zfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(zpos, sizeof(double), nz, fp);
      fclose(fp);

   return 0;

}

| 座標データファイル生成プログラムの例(C言語) 終わり 
+----------------------------------------------------+

場のデータ

ベクトル場及びスカラー場のデータファイル (上の例 "test.v5" では /home/guest/test/test-magnetic.x 等)も 上述の座標データと同様に

  1. Fortranの書式なし出力(バイナリデータ。VFIVEは、データの先頭4バイトを読み飛ばす)
  2. 倍精度実数(C/C++言語のdouble型)

で用意する。下にサンプルプログラムを示す。

+-----------------------------------------------------------+     
| 場のデータファイル生成プログラムの例(Fortran) 始まり    

      implicit none
      integer nx, ny, nz
      parameter(nx=60,ny=70,nz=80)
      integer i,j,k
      real*8 xmag(nx,ny,nz), ymag(nx,ny,nz), zmag(nx,ny,nz)
      real*8 xvel(nx,ny,nz), yvel(nx,ny,nz), zvel(nx,ny,nz)
      real*8 pres(nx,ny,nz), dens(nx,ny,nz)

      character*50 xmfile, ymfile, zmfile
      character*50 xvfile, yvfile, zvfile
      character*50 psfile, dnfile
c
      xmfile = "/home/guest/test/test-magnetic.x"
      ymfile = "/home/guest/test/test-magnetic.y"
      zmfile = "/home/guest/test/test-magnetic.z"
      xvfile = "/home/guest/test/test-velocity.x"
      yvfile = "/home/guest/test/test-velocity.y"
      zvfile = "/home/guest/test/test-velocity.z"
      psfile = "/home/guest/test/test-pressure.z"
      dnfile = "/home/guest/test/test-density.z"
c
      do k = 1 , nz
        do j = 1 , ny
          do i = 1 , nx
            xmag(i,j,k) = 磁場のx成分の定義。
            ymag(i,j,k) = 磁場のy成分の定義。
            zmag(i,j,k) = 磁場のz成分の定義。
            xvel(i,j,k) = 速度場のx成分の定義。
            yvel(i,j,k) = 速度場のy成分の定義。
            zvel(i,j,k) = 速度場のz成分の定義。
            pres(i,j,k) = 圧力場の定義。
            dens(i,j,k) = 密度場の定義。
          end do
        end do
      end do
c
      open(11,file=xmfile,form='unformatted')
      open(12,file=ymfile,form='unformatted')
      open(13,file=zmfile,form='unformatted')
      open(21,file=xvfile,form='unformatted')
      open(22,file=yvfile,form='unformatted')
      open(23,file=zvfile,form='unformatted')
      open(31,file=psfile,form='unformatted')
      open(32,file=dnfile,form='unformatted')
        write(11) xmag
        write(12) ymag
        write(13) zmag
        write(21) xvel
        write(22) yvel
        write(23) zvel
        write(31) pres
        write(32) dens
      close(32)
      close(31)
      close(23)
      close(22)
      close(21)
      close(13)
      close(12)
      close(11)
c
      stop
      end

| 場のデータファイル生成プログラムの例 (Fortran) 終わり
+-----------------------------------------------------------+
+-----------------------------------------------------------+     
| 場のデータファイル生成プログラムの例(C言語) 始まり    

#include <stdio.h>
#include <stdlib.h>

const int nx = 60;
const int ny = 70;
const int nz = 80;

int
main(int argc, char **argv)
{
      int i,j,k;
      double xmag[nz][ny][nx], ymag[nz][ny][nx], zmag[nz][ny][nx];
      double xvel[nz][ny][nx], yvel[nz][ny][nx], zvel[nz][ny][nx];
      double pres[nz][ny][nx], dens[nz][ny][nx];

      char dummy[4];
      FILE *fp;

      char xmfile[] = "/home/guest/test/test-magnetic.x";
      char ymfile[] = "/home/guest/test/test-magnetic.y";
      char zmfile[] = "/home/guest/test/test-magnetic.z";
      char xvfile[] = "/home/guest/test/test-velocity.x";
      char yvfile[] = "/home/guest/test/test-velocity.y";
      char zvfile[] = "/home/guest/test/test-velocity.z";
      char psfile[] = "/home/guest/test/test-pressure.z";
      char dnfile[] = "/home/guest/test/test-density.z";

      for(k = 0; k < nz; k++){
        for(j = 0; j< ny; j++){
          for(i = 0; i < nx; i++){
            xmag[k][j][i] = 磁場のx成分の定義。;
            ymag[k][j][i] = 磁場のy成分の定義。;
            zmag[k][j][i] = 磁場のz成分の定義。;
            xvel[k][j][i] = 速度場のx成分の定義。;
            yvel[k][j][i] = 速度場のy成分の定義。;
            zvel[k][j][i] = 速度場のz成分の定義。;
            pres[k][j][i] = 圧力場の定義。;
            dens[k][j][i] = 密度場の定義。;
          }
        }
      }

      if((fp=fopen(xmfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(xmag, sizeof(double), nx * ny * nz, fp);
      fclose(fp);

	.........(略).........

  return 0;
}

| 場のデータファイル生成プログラムの例(C言語) 終わり
+-----------------------------------------------------------+

単精度データ

マルチスレッド版は、単精度(C/C++のfloat型)のデータも可視化できる。vfive.hの(56,57行目のあたり)

//======
//      float or double.
//      Added on 2008.05.27. by A.K.
// typedef float ffloat_;     
typedef double ffloat_;  
//======
//======
//      float or double.
//      Added on 2008.05.27. by A.K.
typedef float ffloat_;     
// typedef double ffloat_;  
//======
として、再コンパイルする。座標データと場のデータいずれも単精度にする必要がある。

時間発展データ(アニメーション機能)

マルチスレッド版ver.3.72aは、時間発展データを扱うことができる。 時間発展データを扱う場合の入力ファイルは、下記のとおりである。
+----------------------------
n1        256
n2        128
n3        128
ntime       5
nvec        1
nscal       2
scale        1.000
shift_x     -6.500
shift_y     -3.000
shift_z     -3.000
xfile   /home/guest/data/coord_x.dat
yfile   /home/guest/data/coord_y.dat
zfile   /home/guest/data/coord_z.dat

vect0_label  vel
vect0xt0  /home/guest/data/velx200.dat
vect0yt0  /home/guest/data/vely200.dat
vect0zt0  /home/guest/data/velz200.dat

vect0xt1  /home/guest/data/velx205.dat
vect0yt1  /home/guest/data/vely205.dat
vect0zt1  /home/guest/data/velz205.dat

vect0xt2  /home/guest/data/velx210.dat
vect0yt2  /home/guest/data/vely210.dat
vect0zt2  /home/guest/data/velz210.dat

vect0xt3  /home/guest/data/velx215.dat
vect0yt3  /home/guest/data/vely215.dat
vect0zt3  /home/guest/data/velz215.dat

vect0xt4  /home/guest/data/velx220.dat
vect0yt4  /home/guest/data/vely220.dat
vect0zt4  /home/guest/data/velz220.dat



vectmax0  0.06
vectmin0  0.0


scal0_label pressure
scal0t0   /home/guest/data/pre200.dat
scal0t1   /home/guest/data/pre205.dat
scal0t2   /home/guest/data/pre210.dat
scal0t3   /home/guest/data/pre215.dat
scal0t4   /home/guest/data/pre220.dat



scalmax0 -11.0
scalmin0 -20.0


scal1_label density
scal1t0   /home/guest/data/den200.dat
scal1t1   /home/guest/data/den205.dat
scal1t2   /home/guest/data/den210.dat
scal1t3   /home/guest/data/den215.dat
scal1t4   /home/guest/data/den220.dat



scalmax1 -5.0
scalmin1 -16.0

+----------------------------
コメント付きで、意味の説明をする
+----------------------------
n1        256
n2        128
n3        128
ntime       5
# タイムステップ数
nvec        1
nscal       2
scale        1.000
shift_x     -6.500
shift_y     -3.000
shift_z     -3.000
xfile   /home/guest/data/coord_x.dat
yfile   /home/guest/data/coord_y.dat
zfile   /home/guest/data/coord_z.dat

vect0_label  vel

vect0xt0  /home/guest/data/velx200.dat
#0番目のベクトルデータの時刻0のx成分のデータ
vect0yt0  /home/guest/data/vely200.dat
#0番目のベクトルデータの時刻0のy成分のデータ
vect0zt0  /home/guest/data/velz200.dat
#0番目のベクトルデータの時刻0のz成分のデータ

vect0xt1  /home/guest/data/velx205.dat
#0番目のベクトルデータの時刻1のx成分のデータ
vect0yt1  /home/guest/data/vely205.dat
#0番目のベクトルデータの時刻1のy成分のデータ
vect0zt1  /home/guest/data/velz205.dat
#0番目のベクトルデータの時刻1のz成分のデータ

vect0xt2  /home/guest/data/velx210.dat
#0番目のベクトルデータの時刻2のx成分のデータ
vect0yt2  /home/guest/data/vely210.dat
#0番目のベクトルデータの時刻2のy成分のデータ
vect0zt2  /home/guest/data/velz210.dat
#0番目のベクトルデータの時刻2のz成分のデータ

vect0xt3  /home/guest/data/velx215.dat
#0番目のベクトルデータの時刻3のx成分のデータ
vect0yt3  /home/guest/data/vely215.dat
#0番目のベクトルデータの時刻3のy成分のデータ
vect0zt3  /home/guest/data/velz215.dat
#0番目のベクトルデータの時刻3のz成分のデータ

vect0xt4  /home/guest/data/velx220.dat
#0番目のベクトルデータの時刻4のx成分のデータ
vect0yt4  /home/guest/data/vely220.dat
#0番目のベクトルデータの時刻4のy成分のデータ
vect0zt4  /home/guest/data/velz220.dat
#0番目のベクトルデータの時刻4のz成分のデータ



vectmax0  0.06
#0番目のベクトルデータの大きさの最大値
vectmin0  0.0
#0番目のベクトルデータの大きさの最小値


scal0_label pressure

scal0t0   /home/guest/data/pre200.dat
#0番目のスカラーデータの時刻0のデータ
scal0t1   /home/guest/data/pre205.dat
#0番目のスカラーデータの時刻1のデータ
scal0t2   /home/guest/data/pre210.dat
#0番目のスカラーデータの時刻2のデータ
scal0t3   /home/guest/data/pre215.dat
#0番目のスカラーデータの時刻3のデータ
scal0t4   /home/guest/data/pre220.dat
#0番目のスカラーデータの時刻4のデータ



scalmax0 -11.0
#0番目のスカラーデータの最大値
scalmin0 -20.0
#0番目のスカラーデータの最小値


scal1_label density

scal1t0   /home/guest/data/den200.dat
#1番目のスカラーデータの時刻0のデータ
scal1t1   /home/guest/data/den205.dat
#1番目のスカラーデータの時刻1のデータ
scal1t2   /home/guest/data/den210.dat
#1番目のスカラーデータの時刻2のデータ
scal1t3   /home/guest/data/den215.dat
#1番目のスカラーデータの時刻3のデータ
scal1t4   /home/guest/data/den220.dat
#1番目のスカラーデータの時刻4のデータ



scalmax1 -5.0
#1番目のスカラーデータの最大値
scalmin1 -16.0
#1番目のスカラーデータの最小値

+----------------------------

プログラムの実行

実行コマンドは "vfive" である。 CAVEの計算機にログインして、

% vfive test.v5

と打てば良い。(Windowsの場合は、コマンドプロンプトで入力する)

オプション

オプションは二つある。

  1. あらかじめ計算した曲線データのファイル名の指定 (-l ファイル名)
  2. あらかじめ計算した曲面データのファイル名の指定 (-s ファイル名)

例1 曲線の表示:

% vfive test.v5 -l test-lines.v5

例2 曲面の表示:

% vfive test.v5 -s test-surfaces.v5

例3 曲線と曲面の表示:

% vfive test.v5 -l test-lines.v5 -s test-surfaces.v5

曲面と曲線データのフォーマットについては後述する。

コマンドを打ち込んだら

CAVEに入りステレオ眼鏡をかけてしばらく待と 境界線を示す直方体が出現する。

データの境界を示す立方体の辺には赤、緑、青の3種類の色がついているが、 これはそれぞれx-軸方向、y-軸方向、z-軸方向を表す。 プログラム開始時には、 正面のスクリーンに向かう方向がy軸、 右がx軸、上がz軸になっている。

操作方法

VFIVEにはデータを可視化するための機能が複数用意されており、 その基本的な使い方は次のように統一されている。

  1. ワンドの左ボタンを押す(押しっぱなしにする) とメニューパネルが表示される。
  2. 仮想レーザーポインターで任意のパネルを選択する。
  3. そのパネルにサブメニューがあれば、 右側に表示される
  4. 左ボタンを離すと選択が確定する。
  5. 選択した可視化機能はワンドの真ん中ボタンを押すことで実行される。 例えば、力線表示(Field Lines)を選択した場合、 真ん中ボタンを押すと力線の追跡開始点が現れる。
  6. 右ボタンを押すと、 その時に選択されている可視化機能によって表示された物体 (磁力線など)が消去される。

ジョイスティックの操作方法

ジョイスティック (ワンドに付属の黒くて大きなボタン)は仮想空間の ナビゲーション(移動と回転)に使われる。
  1. 前に倒すとワンドの指している(3次元的な) 方向に自分が仮想空間を移動して行く。
  2. 後ろに倒すと逆に後退する。
  3. 左右に倒すと仮想空間内部で自分が回転する。

メインメニュー

Vector Select vector_select 可視化対象となるベクトル場の選択。
Scalar Select scalar_select 可視化対象となるスカラー場の選択。
Object Select object_select 曲線(-l オプション)や曲面(-s オプション)オブジェクトの表示。
Animation animation Play(アニメーション実行)、1step前進、後進。 アニメーション実行時、真ん中ボタンで速さを変えることができる。右ボタンでストップ。ver.3.72a以上。
Scale Changer scalechanger 表示サイズの変更(glScalef使用)
Snapshot snapshot 正面スクリーンに投影された画像をファイルにセーブする (PPM形式)。 このパネルを選択した後、 ワンドの真ん中ボタンを押すたびに snapshot000.ppm, snapshot001.ppm,...というファイルが次々に生成される。 GIMPやIrfanVIewで、閲覧可能。
Quit quit VFIVEの終了。

ベクトル場可視化モジュール

Field Lines field_lines 力線追跡。真ん中ボタンを押すと手の先に短いビームが現れる。 ボタンを離した瞬間、ビームの先端から出発した力線が計算・表示される。 力線の追跡はベクトルの正、負両方向に同時に行われる。 追跡計算におけるベクトル場の補間は3次精度で、 積分は6次のルンゲ=クッタ法で実行される。
Particle Tracer particle_tracer 粒子軌道。 Field Linesと同様に真ん中ボタンを押すと手の先に短いビームが現れる。 ボタンを離した瞬間、ビームの先端から粒子を放出する。 粒子は現在選択されているベクトル場を流れ場とした流線を描く。 積分精度はField Linesと同じ。
Local Arrows local_arrows 3次元矢印。 真ん中ボタンを押すと手の先に短いビームが現れる。 ビームの先端から半径約1フィートの球内部でのベクトル場を 3次元的な矢印の向きと長さで可視化する。 矢印の表示される球領域は、手の動きについて移動する。 真ん中ボタンを離すと矢印は固定される。
Snow in Spotlight spotlighted_snow 真ん中ボタンを押すと手の先からスポットライトが放射され、 そのライトに照らされる円錐領域内部のベクトル場が、 合計5千個の白い点の流れで可視化される。 スポットライトの位置と向きは手の動きについて移動する。 ボタンを離すとスポットライトの円錐領域は固定されるが白点は流れ続ける。 高速化のため白点の流れの積分は1次精度である。
Hotaru hotaru 局所的な解析よりもベクトル場の全体構造を把握するのに便利な機能。 合計1万個の黄色い点がデータの定義域の全領域中を動く。 高速化のため流れの積分は1次精度。
Probe probe 真ん中ボタンを押すと手の先に短いビームが現れる。 ビームの先端のベクトル場の各成分の大きさを文字で表示する。(マルチスレッド版のみ)

スカラー場可視化モジュール

Isosurface isosurface 等値面。 真ん中ボタンを押すと、 等値面のレベル調節用の仮想物体が目の前に出現する。 横向きに8個並んだ黄色の円錐が表示する等値面のレベルを示している。 ワンドを持った手を上に上げれば(下げれば)、 このレベルが上がって(下がって)いく。 中心にある縦方向の円錐物体の太さが、 その高さでのスカラー値の絶対値の(相対的な)大きさを表す。 つまり、円錐の頂点はスカラー値がちょうどゼロのレベルである。 中心の円錐には、 それを取り囲むようにして水平にリング状の線が描かれている。 黒色のリングはそのスカラー場の平均値のレベルを示し、 ピンク色のリングは、 1標準偏差を単位とした平均値との差を表している。
Local Slicer local_slicer 局所的スライス。 真ん中ボタンを押すと、 手の先からビームが現れ、 このビームの先端を中心にして約1メートル四方の正方形が描かれる。 この面は、ビームの先端位置における0番のベクトルに対して常に垂直である。 この正方形面内での0番目のスカラー場の分布が色で示されている。 赤が最大値を、青が最小値を表す。
Ortho Slicer ortho_slicer 軸垂直面スライス。 「x-y plane」、「y-z plane」、「z-x plane」の3つのサブメニューがある。 それぞれ、z軸、x軸、y軸に垂直な面でのスカラー場の分布を色で表す。 真ん中ボタンを押すと、 目の前にデータ領域を示す小さな箱が現れ、 現在のスライス面の位置を示すメッシュが点滅している。 ワンドを持った手を上下(x-y plane の場合)、 左右(y-z planeの場合)、 前後(z-x planeの場合)に動かすことによりスライス面を変更出来る。
Volume Rendering volumerendering テクスチャマッピング機能を用いたボリュームレンダリング。 真ん中ボタンで、伝達関数の変更が可能。(マルチスレッド版のみ)
Probe probe 真ん中ボタンを押すと手の先に短いビームが現れる。 ビームの先端のスカラー場の大きさを文字で表示する。(マルチスレッド版のみ)

曲面データのフォーマット

障害物回りの流れデータをVFIVEで解析する時など、 その障害物を3次元物体としてVR空間に表示できることが望ましい。 VFIVEではオプション引数として「-s 曲面データファイル名」を渡すことにより、 そのデータが記述する複数の曲面を表示することが出来る。 曲面データファイルは次の形のテキストファイルである。

% cat test-surf.v5

+------------------------------------------------+
|               曲面データファイル例    始まり

# vfive sample surface data
surfaceObj:nmen      2
surfaceObj:ni_max    30
surfaceObj:nj_max    50
surfaceObj:xfile     /home/guest/test/test.surf.x
surfaceObj:yfile     /home/guest/test/test.surf.y
surfaceObj:zfile     /home/guest/test/test.surf.z

|               曲面データファイル例    終わり
+------------------------------------------------+

上の曲面データファイルには、

 
      表示する面の総数                        nmen 
      一つの面を構成するグリッド数            ni_max * nj_max
      各面を構成するグリッドのx座標ファイル   xfile
      各面を構成するグリッドのy座標ファイル   yfile
      各面を構成するグリッドのz座標ファイル   zfile

を指定する。 グリッドの座標ファイルは、

  1. Fortranの書式なし出力(バイナリファイル。VFIVEは、先頭の4バイトを読み飛ばす)
  2. 単精度実数(C/C++言語のfloat型)

で用意する。 座標や場のデータは倍精度で与えるが、 曲面データは単精度であることに注意。 これは、すでに計算済みの曲面を仮想空間に表示する場合、 位置の指定にそれほど高い精度が要求されないのに対し、 場や座標のデータに関しては、 力線追跡などの際に高い精度が要求されるためである。

一つの曲面は滑らかな形状であることを仮定している。 球面や円柱の側面などは滑らかな曲面の典型的な例である。 四角柱の側面のように尖った角をもつ曲面は、 複数の曲面(四角柱の場合は四つ)を入力データとして与えることで実現する。

一般にコンピュータグラフィックスでは、 曲面を描く際に、曲面を構成する各頂点の座標データと共に、 各頂点におけるその面の法線ベクトルも指定する必要がある。 VFIVEでは、それぞれの曲面が滑らかであることを仮定して、 頂点座標のデータから法線ベクトルを自動的に計算している。

一つの曲面は二つの整数パラメータ(例えば i と j)で定義し、 複数の曲面を3番目のパラメータで区別する。

例:

   1番目の曲面が長方形: 
                 x(i,j,1) = i*dx          (dxは定数)
                 y(i,j,1) = j*dy          (dyは定数)
                 z(i,j,1) = 0.0

   2番目の曲面が円筒面:  
                 x(i,j,2) = cos(j*dphi)   (dphiは定数)
                 y(i,j,2) = sin(j*dphi)
                 z(i,j,2) = i*dz

   3番目の曲面が球面:
                 x(i,j,3) = sin(j*dtht)*cos(i*dphi)  (dtht, dphiは定数)
                 y(i,j,3) = sin(j*dtht)*sin(i*dphi)
                 z(i,j,3) = cos(j*dtht)

与える曲面のトポロジーは

  1. 正方形
  2. 円筒面
  3. トーラス

の3種類を想定している。 これらの違いは境界条件だけである。 これら3種類のトポロジーは入力データからVFIVEが自動的に判断する。 例えば、i=1とi=imaxでのx,y,zの値が全てのjについて正確に一致している (つまり浮動小数点の比較 val(i=1,j) == val(i=imax,j), val=x,y,z, が成り立つ) 場合は円筒面と判断する。 従って、例えば円筒面を10角形で表示する場合、i=1から(10ではなく) i=11のデータを用意し、

   x(11,j,men) = x(1,j,men)
   y(11,j,men) = y(1,j,men)
   z(11,j,men) = z(1,j,men)

という形で座標値をコピーしておくのがよい。

複数の曲面を表示する場合は、 それぞれの曲面を定義するパラメータiやjの最大値(imax, jmax) が必ずしも一致しなくても良い。 例えば(100グリッド x 200グリッド)の長方形と (80グリッド x 120 グリッド)の長方形を表示する場合は、

    real*4 x(100,200,2), y(100,200,2), z(100,200,2)

と宣言しておいて、 2番目(小さい方)の長方形のデータの不要なグリッドには、 ダミーデータを入れておく。 ダミーデータとして

    999.

の値を入れる。 実際にはVFIVEは、i=1の軸上をj=1からj=2,3,4と走査していき、 初めて999.に出会う直前のjをその面を定義するの実質上のjmax、 また、j=1の軸上をi=1からi=2,3,4と走査していき、 初めて999.に出会う直前のiをその面を定義する実質上のimaxと解釈する。 つまり、上の例では、

      x(81,1,2) = 999.
      y(81,1,2) = 999.
      z(81,1,2) = 999.
      x(1,121,2) = 999.
      y(1,121,2) = 999.
      z(1,121,2) = 999.

とだけ入れておけばよい。 以下に、一つのトーラスと一つの曲面(球面の一部、下図参照) を定義するサンプルプログラムを示す。 このプログラムは、上に示した曲面データフィアル test-surf.v5 と、 その座標バイナリデータを同時に生成する。

torus
+----------------------------------------------------------+   
| 曲面データ生成プログラム例(Fortran) 始まり

      parameter(nmen=2,nimax=30,njmax=50)
      parameter(pi=3.141593,twopi=2*pi)
      parameter(huge=999.0)

      character*50 xfile, yfile, zfile, v5file

      real*4 x(nimax, njmax, nmen)
      real*4 y(nimax, njmax, nmen)
      real*4 z(nimax, njmax, nmen)

      xfile = "/home/guest/test/test.surf.x"
      yfile = "/home/guest/test/test.surf.y"
      zfile = "/home/guest/test/test.surf.z"
      v5file = "/home/guest/test/test-surf.v5"

c     Torus
      rmajor = 10.0
      rminor = 2.0
      x0 = 32.0
      y0 = 32.0
      z0 = 32.0
      dphi = twopi / (nimax-1)
      dtht = twopi / (njmax-1)
      do j = 1 , njmax
	tht = dtht*(j-1)
	do i = 1 , nimax
	  phi = dphi*(i-1)
	  if (i.eq.nimax) phi = 0.0
	  if (j.eq.njmax) tht = 0.0
	  x(i,j,1) = x0 + (rmajor+rminor*cos(tht))*cos(phi)
	  y(i,j,1) = y0 + (rmajor+rminor*cos(tht))*sin(phi)
	  z(i,j,1) = z0 + rminor*sin(tht)
        end do
      end do

c     Psudo-sphere
      x0 = 10.0
      y0 = 10.0
      z0 = 10.0
      rad = 10.0
      niwork = nimax/2
      njwork = njmax/2
      dphi = twopi / (niwork-1)
      thtmin = pi*(2/6.)
      thtmax = pi*(4/6.)
      dtht = (thtmax-thtmin) / (njwork-1)
      do j = 1 , njwork
	tht = thtmax - dtht*(j-1)
	do i = 1 , niwork
	  phi = dphi*(i-1)
	  if (i.eq.niwork) phi = 0.0
	  x(i,j,2) = x0 + rad*sin(tht)*cos(phi)
	  y(i,j,2) = y0 + rad*sin(tht)*sin(phi)
	  z(i,j,2) = z0 + rad*cos(tht)
        end do
      end do

      x(niwork+1,1,2) = huge
      y(niwork+1,1,2) = huge
      z(niwork+1,1,2) = huge
      x(1,njwork+1,2) = huge
      y(1,njwork+1,2) = huge
      z(1,njwork+1,2) = huge


      open(11,file=xfile,form='unformatted')
      open(12,file=yfile,form='unformatted')
      open(13,file=zfile,form='unformatted')
	write(11) x
	write(12) y
	write(13) z
      close(13)
      close(12)
      close(11)

      open(10,file=v5file)
	write(10,8000) "# vfive sample surface data
	write(10,8001) "surfaceObj:nmen ", nmen
	write(10,8001) "surfaceObj:ni_max ", nimax
	write(10,8001) "surfaceObj:nj_max ", njmax
	write(10,8002) "surfaceObj:xfile ",  xfile
	write(10,8002) "surfaceObj:yfile ",  yfile
	write(10,8002) "surfaceObj:zfile ",  zfile
      close(10)

 8000 format(a)
 8001 format(a, i5)
 8002 format(a, a)

      stop
      end

| 曲面データ生成プログラム例(Fortran) 終わり
+----------------------------------------------------------+
+----------------------------------------------------------+
| 曲面データ生成プログラム例(C++言語) 始まり                    
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

const int nmen = 2;
const int nimax = 30;
const int njmax = 50;

const double pi = 3.141593;
const double twopi = 2.0*pi;
const float huge = 999.0;

int main(int argc, char **argv){

int i,j;

float x[nmen][njmax][nimax];
float y[nmen][njmax][nimax];
float z[nmen][njmax][nimax];

char xfile[]  = "/home/guest/test/test.surf.x";
char yfile[]  = "/home/guest/test/test.surf.y";
char zfile[]  = "/home/guest/test/test.surf.z";
char v5file[] = "/home/guest/test/test-surf.v5";

//	Torus
      float rmajor = 10.0;
      float rminor = 2.0;
      float x0 = 32.0;
      float y0 = 32.0;
      float z0 = 32.0;
      double dphi = twopi / (nimax-1);
      double dtht = twopi / (njmax-1);
      for(j = 0; j< njmax; j++){
	double tht = dtht*j;
	for(i = 0; i< nimax; i++){
	  double phi = dphi*i;
	  if (i == nimax -1) phi = 0.0;
	  if (j == njmax -1) tht = 0.0;
	  x[0][j][i] = x0 + (rmajor+rminor*cos(tht))*cos(phi);
	  y[0][j][i] = y0 + (rmajor+rminor*cos(tht))*sin(phi);
	  z[0][j][i] = z0 + rminor*sin(tht);
        }
      }

//     Psudo-sphere
      x0 = 10.0;
      y0 = 10.0;
      z0 = 10.0;
      float rad = 10.0;
      int niwork = nimax/2;
      int njwork = njmax/2;
      dphi = twopi / (niwork-1);
      double thtmin = pi*(2/6.);
      double thtmax = pi*(4/6.);
      dtht = (thtmax-thtmin) / (njwork-1);
      for(j = 0; j<njwork;j++){
	double tht = thtmax - dtht*j;
	for(i = 0; i < niwork;i++){
	  double phi = dphi*i;
	  if (i == niwork-1) phi = 0.0;
	  x[1][j][i] = x0 + rad*sin(tht)*cos(phi);
	  y[1][j][i] = y0 + rad*sin(tht)*sin(phi);
	  z[1][j][i] = z0 + rad*cos(tht);
        }
      }

      x[1][0][niwork] = huge;
      y[1][0][niwork] = huge;
      z[1][0][niwork] = huge;
      x[1][njwork][0] = huge;
      y[1][njwork][0] = huge;
      z[1][njwork][0] = huge;

      char dummy[4];
      FILE *fp;
      if((fp=fopen(xfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(&x[0][0][0], sizeof(float), nmen*nimax*njmax, fp);
      fclose(fp);

	.........(略).........

      if((fp=fopen(v5file,"w")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
	fprintf(fp, "# vfive sample surface data\n");
	fprintf(fp, "surfaceObj:nmen %d\n", nmen);
	fprintf(fp, "surfaceObj:ni_max %d\n", nimax);
	fprintf(fp, "surfaceObj:nj_max %d\n", njmax);
	fprintf(fp, "surfaceObj:xfile %s\n", xfile);
	fprintf(fp, "surfaceObj:yfile %s\n", yfile);
	fprintf(fp, "surfaceObj:zfile %s\n", zfile);
      fclose(fp);

return 0;
}

| 曲面データ生成プログラム例(C++言語) 終わり
+----------------------------------------------------------+

曲線データのフォーマット

あらかじめ計算済みの曲線をVFIVEで表示する場合には、 曲線データとして次のようなテキストファイルを用意する。

+------------------------------------------------------------------+
|               曲線データファイル例    始まり
% cat test-lines.v5

# vfive sample curve data
curveObj:nhon      3
curveObj:ntenmax   100
curveObj:xfile /home/guest/test/test-lines.x         
curveObj:yfile /home/guest/test/test-lines.y         
curveObj:zfile /home/guest/test/test-lines.z         
curveObj:cfile /home/guest/test/test-lines.c

|               曲線データファイル例    終わり
+------------------------------------------------------------------+

上の例では3本の曲線を定義している。 一本の曲線は最大100点の頂点からから構成され、 xfile, yfile, zfileには、 各曲線の頂点の座標値がバイナリデータで 保存する。 cfileは現在のVFIVEでは読み込みはするが、使用しない。 xfile, yfile, zfileと同じ大きさのダミーを用意する。 将来のバージョンではcfileの値を曲線に色をつけることなどに利用する予定である。 これらのファイルは、

  1. Fortranの書式なし出力(バイナリファイル。VFIVEは先頭の4バイトを読み飛ばす)
  2. 単精度実数(C/C++言語のfloat型)

で用意する。

各曲線を構成する頂点数は異なっても構わない。 その場合、最大の頂点数を ntenmx、本数をnhon として、

       real*4 x(ntenmx, nhon)
       real*4 y(ntenmx, nhon)
       real*4 z(ntenmx, nhon)
       real*4 c(ntenmx, nhon)

という配列を用意し、少ない頂点数の曲線には不要な頂点座標にダミーデータ を入れる。ダミーデータの値は、曲面データと同様に

     999.0

を用いる。 以下に3本の曲線データを作るサンプルプログラムを示す。

lines
+--------------------------------------------------------+
| 曲線データ生成プログラム例(Fortrn) 始まり                  
      implicit none

      integer ntenmx, nhon
      parameter(ntenmx=100,nhon=3)

      real*4 x(ntenmx,nhon),y(ntenmx,nhon),z(ntenmx,nhon)
      real*4 c(ntenmx,nhon)
      real*4 pi, twopi, theta, phase
      integer i,j

      character*50 xfile, yfile, zfile, cfile, v5file

c     xfile = "/home/guest/test/test-lines.x"
      yfile = "/home/guest/test/test-lines.y"
      zfile = "/home/guest/test/test-lines.z"
      cfile = "/home/guest/test/test-lines.c"
      v5file = "/home/guest/test/test-lines.v5"

      pi = atan(1.)*4
      twopi = pi*2

c     ... Define triple helix.
      do j = 1 , nhon
	phase = twopi / nhon * (j-1)
	do i = 1 , ntenmx
	  theta = twopi*float(i-1)/ntenmx
	  x(i,j) = 5.0*cos(theta + phase) 
	  y(i,j) = 5.0*sin(theta + phase)
	  z(i,j) = 20.0 / ntenmx * (i-1)
	  c(i,j) = 0.0
	end do
      end do

c     ... The 3rd line is short.
      x(ntenmx/2,3) = 999.
      y(ntenmx/2,3) = 999.
      z(ntenmx/2,3) = 999.
      c(ntenmx/2,3) = 999.

c     ... Make binary data file
      open(11,file=xfile,form='unformatted')
      open(12,file=yfile,form='unformatted')
      open(13,file=zfile,form='unformatted')
      open(14,file=cfile,form='unformatted')
	write(11) x
	write(12) y
	write(13) z
	write(14) c
      close(14)
      close(13)
      close(12)
      close(11)

c     make text data file
      open(10,file=v5file)
	write(10,8000) "# vfive sample curve data"
	write(10,8001) "curveObj:nhon ", nhon
	write(10,8001) "curveObj:ntenmax ", ntenmx
	write(10,8002) "curveObj:xfile ",  xfile
	write(10,8002) "curveObj:yfile ",  yfile
	write(10,8002) "curveObj:zfile ",  zfile
	write(10,8002) "curveObj:cfile ",  cfile
      close(10)

 8000 format(a)
 8001 format(a, i5)
 8002 format(a, a)

      stop
      end


| 曲線データ生成プログラム例(Fortran) 終わり
+--------------------------------------------------------+
+--------------------------------------------------------+
| 曲線データ生成プログラム例(C++言語) 始まり              
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

const int ntenmx = 100;
const int nhon = 3;

int main(int argc, char **argv){

  float x[nhon][ntenmx],y[nhon][ntenmx],z[nhon][ntenmx];
  float c[nhon][ntenmx];
  double pi, twopi, theta, phase;
  int i,j;

  char xfile[]  = "/home/guest/test/test-lines.x";
  char yfile[]  = "/home/guest/test/test-lines.y";
  char zfile[]  = "/home/guest/test/test-lines.z";
  char cfile[]  = "/home/guest/test/test-lines.c";
  char v5file[] = "/home/guest/test/test-lines.v5";

  pi = 3.14159;
  twopi = pi*2.0;

//     ... Define triple helix.
      for(j = 0; j < nhon; j++){
	phase = twopi / nhon * j;
	for(i = 0; i < ntenmx; i++){
	  theta = twopi*(double)i/ntenmx;
	  x[j][i] = 5.0*cos(theta + phase);
	  y[j][i] = 5.0*sin(theta + phase);
	  z[j][i] = 20.0 / ntenmx * i;
	  c[j][i] = 0.0;
	}
      }

//     ... The 3rd line is short.
      x[2][ntenmx/2] = 999.;
      y[2][ntenmx/2] = 999.;
      z[2][ntenmx/2] = 999.;
      c[2][ntenmx/2] = 999.;

//     ... Make binary data file

      char dummy[4];
      FILE *fp;
      if((fp=fopen(xfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(&x[0][0], sizeof(float), ntenmx*nhon, fp);
      fclose(fp);

      ..........(略).........

//     make text data file
      if((fp=fopen(v5file,"w")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
	fprintf(fp, "# vfive sample curve data\n");
	fprintf(fp, "curveObj:nhon %d\n", nhon);
	fprintf(fp, "curveObj:ntenmax %d\n", ntenmx);
	fprintf(fp, "curveObj:xfile %s\n", xfile);
	fprintf(fp, "curveObj:yfile %s\n", yfile);
	fprintf(fp, "curveObj:zfile %s\n", zfile);
	fprintf(fp, "curveObj:cfile %s\n", cfile);
      fclose(fp);

return 0;
}
| 曲線データ生成プログラム例(C++言語) 終わり
+--------------------------------------------------------+

最後に

VFIVEのメニューパネルで使用されているテクスチャデータの生成には、 核融合研のCOE研究員、 坂井豊一博士作成のプログラムを利用させていただいたことをここに記し、 感謝する。

参考文献

  1. 陰山 聡、 佐藤 哲也, VRシステムCompleXcopeプログラミングガイド,
    NIFS-MEMO-28, Sep. 1998
  2. Akira Kageyama, Yuichi Tamura, and Tetsuya Sato,
    Visualization of Vector Field by Virtual Reality,
    Progress of Theoretical Physics Supplement, No.138 (2000)

Last Update:2010.03.25
Akira Kageyama and Nobuaki Ohno, Advanced Visualization and Perception Research Group, Earth Simulator Center, JAMSTEC