3. 言語指示


3. 言語指示

言語指示とは、様々な方法でシーンの記述法を拡張するものである。 言語指示はシーン・ファイル内のほとんどの場所で使用できる。

言語指示には次のようなものがある。

●シーン・ファイルの中に別のデータ・ファイルを挿入する(#include
●識別子の宣言(#declare, #local
●ファイル入出力の指示(#fopen, #fclose, #read, #write)
●テクスチャのデフォルト値の設定(#default
●バージョンの指定(#version
●条件指示、ループ(繰り返し)指示(#if#switch#while
●特定のメッセージの表示
●マクロ定義(#macro)

このセクションではPOV-Rayの言語指示の使用法ついて説明する。

言語指示キーワード一覧
#break #case #debug #declare
#default #else #end #error
#fclose #fopen #if #ifdef
#ifndef #include #local #macro
#range #read #render #statistics
#switch #undef #version #warning
#while #write      


3.1 インクルード・ファイル(#include)

#includeはインクルード・ファイル(ファイル名が " 〜.inc " のファイル)を読み込むために使用する。 インクルード・ファイルとはシーン・ファイルの中に挿入するデータ・ファイルのことである。 インクルード・ファイル自身はシーン・ファイルではないため、そのままレンダリングすることはできないが、どんなシーン・データでも記述することができる。 これによって、シーンを部分ごとに分けて作成することや、同じデータを複数のシーン・ファイルで共有することなどが可能となる。

< #include の構文>

#include " FILENAME.inc "
#include インクルード・ファイルを読み込むキーワード
" FILENAME.inc " 40文字以下(またはコンピュータの制限内)のファイル名
※ .incはインクルード・ファイルの拡張子
※ ファイル名は " " で囲まなければならない。

#includeはシーン・ファイル中のどこでも指定できる。 インクルード・ファイルはこのステートメントを記述した場所に挿入され、その部分のデータとして解析される。

インクルード・ファイルは最大10までネスト(入れ子)することができる。 ネストがないインクルード・ファイルはいくつでも使用できる。

※ インクルード・ファイルを使用する場合、POV-Rayがファイルを自動的に参照するのは 次の場所だけである。

●カレント・ディレクトリ(その時使っているシーン・ファイルがあるディレクトリ)

●Library_Pathを指定したディレクトリ(標準インクルード・ファイルのディレクトリなど)

使用するファイルがこれらの場所にあればファイル名だけを指定すればよいが、これ以 外の場所にある場合は、次のようにパス名で指定しなければならない。

例)DドライブのpovfileディレクトリにあるInc_1.incファイルを指定する場合

#include " d:\povfile\Inc_1.inc "

ただし、パス名による指定ではファイルの場所が変わってしまうと使用できなくなるため、 他のコンピュータにファイルをコピーして使用するような場合は注意が必要である。

以上のことから、自分で作成したインクルード・ファイルは、それを使用するシーン・ファイルと同じディレクトリに入れておくべきである(コピーする場合はそのディレクトリごとコピーすればよい)。 他のコンピュータで使用しないのであれば、標準インクルード・ファイルのディレクトリ(POV-Rayのincludeディレクトリ)などのLibrary_Pathを指定したディレクトリに入れておけばよい。

※ Library_Pathの指定法:POV-RayのメニューバーからTools→Edit Master POVRAY.INIを 選択し、最後の方にLibrary_Path=ディレクトリ名(フルパスで記述)を追加する。


3.2 宣言(#declare, #local)

#declare, #localは識別子を宣言するために使用する。 識別子を宣言することによってシーン・ファイルを読みやすくすることができる。 また、パラメータとして使用することもでき、識別子の値を変更することで、その識別子が含まれた式などの値を自動的に変更することができる。

< #declare, #local の構文>

#declare IDENTIFIER = ITEM
#local IDENTIFIER = ITEM
#declare
#local
識別子を宣言するキーワード
IDENTIFIER 識別子の名前(40文字以下)
ITEM 識別子のタイプ。下記のものはすべて識別子として宣言できる。
●実数、ベクトル、色 ---> 最後にセミコロン(;)を付けることを忘れないこと。
●文字列表現
●変形(transform)
●物体(object)
●テクスチャ、ピグメント、法線、フィニッシュ、インテリア、メディア、密度
(texture、pigment、normal、finish、interior、media、density)
●カラー・マップ、ピグメント・マップ、スロープ・マップ、ノーマル・マップ 、密度マップ
(color_map、pigment_map、slope_map、normal_map、density_map)
●カメラ(camera)
●光源(light_source)
●大気(atmosphere)
●霧(fog)
●虹(rainbow)
●天球(sky_sphere)
●変形(transform)

例)
          #declare Rows = 5;
          #declare Count = Count+1;
          #local  Here = <1,2,3>;
          #declare White = rgb <1,1,1>;
          #declare Cyan = color blue 1.0 green 1.0;
          #declare Font_Name = "ariel.ttf"
          #declare Rod = cylinder {-5*x,5*x,1}
          #declare Ring = torus {5,1}
          #local  Checks = pigment { checker White, Cyan }
          object{ Rod scale y*5 }     // not "cylinder { Rod }"
          object {
            Ring
            pigment { Checks scale 0.5 }
            transform Skew
          }
識別子はシーンのどこでも宣言できる(他のステートメントの中でもよい)。
例)
          #declare Here=<1,2,3>;
          #declare Count=0;         // 変数の宣言と初期化
          union {
            object { Rod translate Here*Count }
            #declare Count=Count+1;     // 再宣言(この場合Countは1になる)
            object { Rod translate Here*Count }
            #declare Count=Count+1;     // 再宣言(この場合Countは2になる)
            object { Rod translate Here*Count }
          }
この例のように、識別子を再宣言することや、前に宣言した値を別の宣言の中で使うこともできる。 また、POV-Rayにはあらかじめ宣言された識別子がいくつか組み込まれている。 ⇒「1.7 組み込み識別子」参照。

※ 識別子を再宣言する場合は元のタイプと同じものにしなければならない。 例えば実数識別子をベクトル識別子として再宣言することはできない。

※ ほとんどの宣言はそれぞれの制限の範囲内でネストすることができるが、実数、ベクト ル、色表現だけは宣言の中で他の言語指示を使うことができない。

※ 識別子が#macro.. #end の中で宣言された場合、マクロが呼び出された時のみ作られる。(マクロについては、「3.8 Macros 」 を参照)

3.2-1 #declare と#local の違い

識別子の宣言は、#declare と#localの2種類ある。 #declareはシーン全体で有効であり、#localは宣言された場所でのみ有効である。

<#declare>
この宣言によって作られた識別子は、通常、シーン全体において有効である。この宣言による識別子は、すべての構文解析が完了するか、#undefにより解除されるまで有効である。

<#local>
この宣言によって作られた識別子は、宣言された場所でのみ有効である。同じ名前の識別子が宣言されると、以前の同名の識別子は一時的に無効となる。

・ #macro内で使われると・・・
識別子はマクロ内でのみ有効である。マクロが呼び出され、#localが構文解析されるときに識別子が作られ
る。マクロ終了の#endまで識別子は有効であり、それ以降は無効になる。

・ インクルードファイル内で使われると・・・
インクルードファイルに限定された一時的な識別子を作る。インクルードファイルが読み込まれ、
#localが構文解析されるときに識別子が作られ、インクルードファイルの最後で
識別子が無効になる。

・ メインシーンファイル内で使われると・・・
#localは#declareと同じ働きをする。一般的に、メインのシーン記述には#declareを使用するべきである。

※ #localによる識別子についても、#undefの使用により削除することができるが、#localによる識別子は自動消滅するため一般的にそのようにする必要はない。

3.2-2 #undef による識別子の削除

#declareのよる識別子は、シーン全体で有効であり、#localによる識別子は、識別子が宣言された場所(マクロ、インクルードファイル)で有効である。有効な識別子を無効にしたいときは#undefにより、削除することができる。
 #undef  IDENTIFIER
#undef undef を指定するキーワード
IDENTIFIER 無効にしたい識別子の名前


3.3 ファイル入出力

この指示によりPOV-Rayのシーン記述においてファイルの取り扱いをすることができる。ASCII テキストファイルに対してopen(開く)、read(読み込む)、write(書き込む)、append(追加)、close(閉じる) の操作が可能である。アニメーション作成などを考慮して追加された機能である。

ファイル入出力機能は、POV-Ray シーンにおけるインクルードファイルの生成やスクリプトの自動修正などに使用することを想定している。

3.3-1 #fopen の宣言

テキストファイルは、#fopen を使用して開くことができる。

< #fopen の構文>

   #fopen IDENTIFIER "filename" OPEN_TYPE    
#fopen
#fopenを宣言するキーワード
IDENTIFIER
識別子の名前(40文字以下)
filename
ファイル名(40文字以下)
OPEN_TYPE
read, write, append の3つのどれかを指定する。read は読み込みモードとしてファイルが開かれる。write は、書き込みモードとしてファイルが開かれる。ファイルが存在しない場合には新規に生成され、ファイルが既に存在する場合には頭から上書きされる。append は、書き込みモードとしてファイルが開かれるが、既に存在するファイルの場合は最後に追加して書き込まれる。

#fopen によって宣言された識別子はシーン全体で有効であり、シーンの構文解析が完了、もしくはファイルを#fclose にするまで有効である。ファイルが開いているかどうかをチェックするには、#ifdef を使うと良い。

3.3-2 #fclose の宣言

#closeの使用により、開いたファイルを閉じることができる。#fopenで開いたファイルは、#closeを使用しなくてもシーンの構文解析が完了するとき自動的に閉じられる。

< #close の構文>

   #fclose   FILE_HANDLE_IDENTIFIER
#fclose
#fcloseを宣言するキーワード
FILE_HANDLE_IDENTIFIER
ファイルの識別子

3.3-3 #read の宣言

#readを使用すると、ASCIIテキストファイルから、string, float, vector の値を読み込むことができる。ファイルは#fopenにより"read"モードで開いておく必要がある。

< #read の構文>

   #read(  FILE_HANDLE_IDENTIFIER,  DATA_IDENTIFIER[,DATA_IDENTIFIER]...) 
#read
#readを宣言するキーワード
FILE_HANDLE_IDENTIFIER
ファイル識別子
DATA_IDENTIFIER
データが読み込まれる識別子。宣言されていない識別子の場合は自動的に#declareで宣言された識別子として生成され、データが読み込まれる。文字列, 実数, ベクトルの読み込みができる。

(注意) #readによる読み込みでは、文字列は引用符でくくり、それぞれの入力値はコンマで区切る。データ例を参照せよ。

記述例)
         #read(Myfile, mystring, myfloat, myvector)
データ例)
         "POV-Ray", -123.55, <1,5,8>
3.3-4 #write の宣言

#writeを使用すると、ASCIIテキストファイルへ、string,float,vectorの値を書き込むことができる。ファイルは#fopenにより"write"もしくは"append"モードで開いておく必要がある。

< #write の構文>

   #write(  FILE_HANDLE_IDENTIFIER,  DATA_IDENTIFIER[,DATA_IDENTIFIER]...) 
#write
#writeを宣言するキーワード
FILE_HANDLE_IDENTIFIER
ファイル識別子
DATA_IDENTIFIER
データが書き出される識別子。文字列, 実数, ベクトルのどれかである。実数は浮動小数点として出力される。配列のコントロールが必要ならば、str(VALUE,L,P)機能を使うべきである。ベクトルは3つの浮動小数点としてコンマ区切られ、ブラッケットを付けて出力される。

(注意) #writeによる出力は、コンマや引用符を自動的に出力しない。#writeで出力したものを#readにより入力を行う場合は、値を区切るコンマや文字列の引用符も書き出す必要がある。

記述例)
          #declare Val1 = -123.45;
          #declare Vect1 = <1,2,-3>;
          #write (MyFile,"\"A quote delimited string\",",Val1,",",Vect1,"\n")
出力例)
          "A quote delimeted string" , -123.45, <1,2,3> 


3.4 デフォルト・テクスチャ(#default)

物体を作ったとき、テクスチャをなにも指定しなければデフォルト・テクスチャが適用される。 このデフォルト・テクスチャは言語指示#defaultによって変更することができる。

< #default の構文>

 #default {
   texture {
     pigment {...}
     normal {...}
     finish {...}
   }
 }
#default デフォルト・テクスチャを指定するキーワード
texture テクスチャを指定するキーワード ⇒「12. テクスチャ1」
pigment {...} ピグメントの指定 ⇒「12.1 ピグメント」
normal {...} ノーマルの指定 ⇒「12.2 ノーマル」
finish {...} フィニッシュの指定 ⇒「12.3 フィニッシュ」

※ 各パラメータはすべてオプションである。

※ 各パラメータの指定法と元のデフォルト値については上記の各セクションを参照せよ。
※ tiles、material_map、texture_mapのような特殊テクスチャは、デフォルト・テクスチャ として使用できない。

※ デフォルト・テクスチャはピグメント、ノーマル、フィニッシュで個別に適用される。 例えば物体にピグメントだけを指定した場合は、ノーマルとフィニッシュにデフォルト値 が適用される。

例)
         #default {
           texture {
             pigment { rgb <1,0,0> }
             normal { bumps 0.3 }
             finish { ambient 0.4 }
           }
         }

次のように1つのパラメータだけを変更することもできる。 この場合texture{}で囲む必要はない。

例) #default { pigment {...} }

次のようにtexture{}を記述することでデフォルト・テクスチャを指定することもできる。

例) sphere { <0,0,0>, 1 texture {} } // デフォルト・テクスチャが適用される

デフォルト・テクスチャは1つのシーン内で何度も変更することができ、変更は#default指示を記述した場所から有効になる。 途中でPOV-Rayの元のデフォルト・テクスチャに戻したい場合は、次の例のように最初に識別子として宣言しておけばよい。

例)
          #declare Original_Default = texture {}   // POV-Rayの元のデフォルト・テクスチャ
          #default texture { ... }                 // デフォルト・テクスチャを変更
            ...                                    // ここでは変更したデフォルト・テクスチャ
            ...                                    // が適用される。
          #default {texture {Original_Default}}    // 元のデフォルト・テクスチャに戻す

3.5 バージョン指定(#version)

#version指示を使ってシーン記述言語のバージョンを変更することができる。 現行のPOV-Rayはバージョン3.5なので、通常はシーン・ファイルの最初に

#version 3.5

を記述するだけである。

組み込み識別子versionを使ってシーンの途中で違うバージョンの構文を使用することもできるが、通常は変更する必要はない。 バージョンの変更に興味があれば、POV-Rayのヘルプ(英語版)の「Version Directive」を参照せよ。


3.6 条件指示

条件指示は、条件によってシーンの解析法を変えるための言語指示である。 これによってシーン・ファイルのデータをプログラムのように扱うことができる。 条件指示は200までネストできる。

3.6-1 #if

#if 指示は最も簡単な条件指示である。 #ifの後の条件が真であるかどうかによって、解析される項目を指定することができる。
< #if 指示の構文>

 #if(COND)
   TRUE_ITEM ...
 #else
   FALSE_ITEM ...
 #end
#if (COND) 条件指示を指定するキーワード。 CONDの部分には論理値を評価する実数表現を指定する。 結果が0.0であれば否、そうでなければ真と評価される。※ 1e-10程度のきわめて小さい値は0とみなされる。
TLUE_ITEM ... CONDが真のときに解析される部分
#else
FALSE_ITEM ...
CONDが否のときに解析される部分
※ #elseはオプションであり、指定されていなければ#endに向かう。
#end 条件指示の終了を示すキーワード

#ifの代わりに#ifdefか#ifndefを使用することによって、ある識別子がすでに宣言されているかどうかを条件にすることもできる。 #ifdefは識別子がすでに宣言されていれば真と評価し、#ifndefは否と評価する(それ以外は#ifと同じである)。 上記の構文の#if (COND)の部分を#ifdef (IDENTIFIER)または、#ifndef (IDENTIFIER)とすればよい(IDENTIFIERは識別子)。

例)
          #declare Which=1;
          #if (Which)
            box { 0, 1 }
          #else
            sphere { 0, 1 }
          #end

3.6-2 #switch、#case、#range

#switch指示を使うとより細かい条件指示ができる。

< #switch 指示の構文>

 #switch (VALUE)
   #case (TEST_1) または #range (LOW_1,HIGH_1)
     ITEM_1 ...
   #braek
   ...
   #case (TEST_n) または #range (LOW_n,HIGH_n)
     ITEM_n ...
   #braek

   #else
     ELSE_ITEM ...
 #end
#switch (VALUE) 条件指示を指定するキーワード。 VALUEの部分には#case及び#rangeと比較する実数表現を指定する。※ 比較の結果、値の差が1e-10以下であれば等しいと見なされる。
#case (TEST_n)
ITEM_n
VALUE = TEST_nのときに解析される部分 TEST_nにはVALUEと比較する実数表現を指定する。
#range (LOW_n,HIGH_n
ITEM_n
LOW_n≦VALUE≦HIGH_nのときに解析される部分 LOW_nとHIGH_nにはVALUEと比較する実数表現を指定する。
#break それぞれの#case、#range の終了を示すキーワード
#else
ELSE_ITEM
すべての#case、#rangeが否であった場合に解析される部分 ※ #elseはオプションであり、指定されていなければ#endに向かう。
#end 条件指示の終了を示すキーワード

#caseと#rangeは指定した順序でVALUEと比較される。 比較の結果が否であるものは無視され、最初に真となった部分のITEMだけが解析される。 その後に真のものがあったとしてもそれらは無視されて条件指示は終了する。

例)
          #switch (VALUE)
            #case (TEST_1)
                  // VALUE=TEST_1のとき、ここを実行 
            #break    //1番目のcase文の終わり、ここで終了 
            #case (TEST_2)
                  // VALUE=TEST_2のとき、ここを実行
            #break    //2番目のcase文の終わり、ここで終了
            #range (LOW_1,HIGH_1)
                  // VALUE>=LOW_1でかつVALUE<=HIGH_1のとき、ここを実行
            #break    //3番目のcase文の終わり、ここで終了
            #range (LOW_2,HIGH_2)
                  // VALUE>=LOW_2でかつVALUE<=HIGH_2のとき、ここを実行
            #break    //4番目のcase文の終わり、ここで終了
            #else
                  // どのケースにもあてはまらないとき、ここを実行
           #end  // swich文の終わり

3.6-3 #while

#while 指示は、あるステートメントを指定した回数だけ繰り返すために使用する。 複数のオブジェクトを決まったパターンで配置する場合などに便利である。

<(典型的な)#while指示の構文>

 #declare C = INITIAL_VALUE
 #while ( C < END_VALUE )
    ITEM ...
 #declare C = C + N
 #end
#declare C = INITIAL_VALUE 繰り返しの初期値の設定。 Cは繰り返しの回数を制御する識別子であり、INITIAL_VALUEには繰り返しの初期値を指定する。
#while ( C < END_VALUE ) 繰り返しを指定するキーワード。 #whileから#endでを繰り返す。 CがEND_VALUEより大きくなったところで繰り返しは終了する。
ITEM ... 繰り返す内容
#declare C = C_INC Cを増加させる宣言。 C_INCにはCを増加させる式を指定する。
例) #declare C = C + 1
#end 繰り返しの終了を示すキーワード

#whileの後の()の中に指定するものはブール値を評価する実数表現なら何でもよいが、通常は上記の構文のように指定する。 Cの名前やCを増加させる式はどんなものでも良い。

例)
          #declare C=0
          #while (C < 2)

            #declare D=0
            #while (D < 20)

              object{Tree translate <C*10, D*5, 0>}    // y方向に間隔5で20本並べたものを
                                                       // x方向に間隔10で2列に配置する
            #declare D=D+1
            #end

          #declare C=C+1
          #end
この例では#whileの中にもう一つ#whileがネストされている。 内側の#whileは木(識別子Tree)の奥行き方向の並びが制御され、外側の#whileによって2列に並べられる。 #whileを使えば、このような繰り返しのパターンを簡単に作ることができる。


図3.6.3 #whileの使用例


3.7 ユーザー・メッセージ

POV-Rayでは、レンダリングの情報やエラーメッセージを表示するための言語指示が使用できるが、通常は使うことはないので省略する。 興味があれば、POV-Rayのヘルプ(英語版)の「User Message Directives」を参照せよ。


3.8 マクロ定義

マクロ定義により、さまざまな形状を関数のような形で定義することができ、マクロを呼び出すことでマクロ定義を使用することができる。この機能をうまく使用すると複雑なシーン記述を容易にすることもできる。また、マクロライブラリとしてさまざまな形状を部品化することも可能になる。

3.8-1 #macro の宣言

<マクロ宣言の構文>

 #macro IDENTIFIER ( [PALAM_IDENT][, PALAM_IDENT]…)
   TOKENS…
 #end
#macro
マクロを宣言するキーワード
IDENTIFIER
識別子の名前(40文字以下)
PALAM_IDENT
コンマや括弧で分けられたパラメータの括弧はパラメータがなくても必要。
TOKENS…
マクロの記述部分
#end
マクロの終了

同じ名前のマクロが複数存在することは許されない。マクロでは#ifdef, #ifndef、#undef を使用することができる。
マクロ記述において、"#if…#end"、"#while…#end"のような条件指定はマクロの中、またはマクロの外で使用し、マクロ定義をまたがって使用できないことに注意する。

3.8-2 #macro の呼び出し

<マクロ呼出の構文>

 MACRO_IDENTIFIER ( [ACTUAL_PALAM][, ACTUAL_PALAM]…  )
MACRO_IDENTIFIER
マクロの識別子
ACTUAL_PALAM
識別子や変数などを指定する。

・ 例としてウィンドウフレームを作成。

 #macro Frame (OW ,OH, IW, IH, D)   // OW-外側の幅、  OH---外側の高さ
 #declare Horz = (OH-IH)/2;     // IW---内側の幅、IH---内側の高さ
 #declare Vert = (OW-IW)/2;     // D---深さ
 difference{
          box{<0,0,0>,<OW,OH,D>
              pigment{color Red}}
          box{<Vert,Horz,-0.1>,<OW-Vert,OH-Horz,D+0.1>
              pigment{color Blue}}
 }
 translate<-OW/2,0,0>
 #end
            
 object{Frame(8,10,7,9,3)}        // macro の呼び出し

上記のマクロを使用し、複数回呼び出して作成した画像が下記のものである。


図3.8.2 window_Frame