シーンの構成
シーンフォーマットの記述概要
シーンの構成ファイルはYAMLを用いて書かれています。 前のセクションで前述した通り、このファイルを記述するだけでレンダリング画像を生成できます。
研究開発においてシーンファイルは手作業で記述する可能性があるため、拡張性の高さと可読性に焦点を置いた書式仕様になっています。 また、ユーザーが定義した構成、すなわち新しいデータ入力をプラグインとしてユーザーが作成することができます。 詳しくはプラグインセクションを参照してください。
この章ではシーンの仕様の基礎的な構造について、それぞれの構成要素の役割についてと任意のシーンを作成するためにどのようにシーンファイルを記述すべきかを説明します。シーンファイルはユーザとレンダラー間のインターフェイスの役割を果たしています。そのため、任意のシーンを作成し始める前にこの章を理解することをお勧めします。
YAML 入門
シーンの構成ファイルはYAMLを用いて書かれています。 YAMLはリーダブル性に富んだ書式になっています。そのため多様なデータを記述しても読みやすい構成になる特徴があります。 ここでは最低限のYAMLを使ってシーンファイルを記述するためのHow toを説明します。
Scalar(スカラー)
スカラーはYAMLの基本データタイプです。
全ての文字や数字のデータは一つのデータタイプ(Scalar)で書かれます:boolean
,integer
,floating point
,string
がその対象です。
例えば、true
は自動的にbool型のスカラーとなり、3.14
は自動的にfloot型のスカラーとして判別されます。
Mapping(マッピング)
マッピングはキーと値のペアを一つのデータ構造として表現できます。
「キー:値」の形式で表します。
また、半角スペースでインデントすることで、マッピングをネストさせることができます。
例えば、下の例では4つのキーと値のペアのマッピングを定義しています。
A
は10
と、B
は20
と関連付けられています。
またC1
とC2
はネストされたマッピングとして定義されています。
A: 10
B: 20
C:
C1: 30
C2: 40
Sequence(シーケンス)
シーケンスにより、YAMLでは行頭に-
をつけることで配列を表現できます。
同じ配列レベルの際は、-
は同じインデントレベルで記述する必要があります。
同じ配列のレベルでない際はインデントを一つ下げることで配列をネストさせることができます。タブキーでのインデントは使えません。半角スペースを用いてください。
例えば、下の例ではA
,B
,C
とa1
,a2
の5つの要素をシーケンスとして表現しています。A
は二つの要素(a1
,a2
)をネスト構造で持っています。
- A
-
- a1
- a2
- B
- C
Tips
#
で1行をコメント化することができます。tab
キーでのインデントは禁止です。半角スペースを2回押してインデントを下げることをお勧めします。
シーンの構造
ここからはシーンファイルの様式について説明します。全てのシーンファイルにはlightmetrica:
をキーとしたマッピングを記述する必要があります。
lightmetrica:
...
シーンの構成は幾つかの構成要素に分けることができます。
(1)version
部分はシーン様式のバージョンを意味します。
(2)assets
部分はメッシュや材質やテクスチャ等のアセットを定義します。
(3)scene
部分はそれぞれのアセット同士の関係を定義してシーンの構成を定義します。
(4)accell
部分はレンダラーのスピードアップのためにどのアクセラレーションデータ構造を用いるかを定義します。
(5)renderer
部分ではレンダリング手法とそのパラメータを設定します。
次の章からはそれぞれの要素の詳細を説明します。
lightmetrica:
version: ... # (1)
assets: ... # (2)
scene: ... # (3)
accel: ... # (4)
renderer: ... # (5)
バージョン
version
はx.y.z
のような文で書き、シーンファイルのバージョンを表します。
値x
, y
, z
はそれぞれ、メジャー、マイナー、パッチのバージョンの値が入ります。現在のバージョンは1.0.0
です。inputのシーンがバージョンの範囲を超えている場合はレンダリングプロセスが排除されます。
シーンのバージョンとフレームワークのバージョンは違います。
フレームワークのバージョンは(major).(minor).(patch).(build)
の形式です。
buildにはいる数字は最新のレポジトリから自動的にアサインされます。
現在のフレームワークのバージョンはです。
アセットライブラリ
assets
はアセットの集合を定義します。これをアセットライブラリと呼んでいます。
トライアングルメッシュやマテリアル定義や他のユーザー定義のアセット等全てのアセットはここに記述されます。
それぞれの要素はアセットのIDとそれの定義式のマッピングで書かれています。
assets:
<asset_id_1>:
interface: <asset_interface>
type: <asset_type>
params:
<asset_params>
<asset_id_2>:
...
...
asset_id_1
, asset_id_2
, … がアセットのキーを表し、interface
, type
, and params
等がアセットを定義する値になります。
それぞれのキーはscene
部分でアセットを区別する際に用いられる参照名となります。ユーザが任意数のアセットを定義することができます。
アセットインターフェイスはinterface
によってアセットの中のどのカテゴリを選択するかを決定できます。(例えばtextureやbsdf)。また、type
によってそのアセットカテゴリの中のどのタイプ・手法を用いるかを決定します。
詳しいインターフェイスとタイプはAssetsセクションで紹介します。
シーンヒエラルキー
基本的にシーン構造はシーングラフ と呼ばれるそれぞれのノードが3Dメッシュデータと材質の情報を持った木構造を取ります。また、このノード部分で回転や移動といったトランスフォーメーションを行います。 詳しくはこの後のトランスフォーメーションで記述します。 このメカニズムは階層的に物体同士の関係を記述する際に便利です。 テーブルと幾つかのコップからなるシーンで考えてみましょう。 もしテーブルの子ノードとしてカップたちをアサインすれば、テーブルの位置を変えた際に、カップの位置は変えずとも、子ノードになっているので自動的にテーブル上のカップの位置も移動します。
scene:
sensor: <sensor_node_id>
nodes:
- id: <node_id_1>
...
- id: <node_id_2>
...
...
トランスフォーメーション
それぞれのノードはノードのタイプによって幾つかの要素を含みます。
その一つがtransform
要素で、これによってノードのトランスフォーメーション(回転や移動といった)を行うことができます。方法は幾つかあります。
一つ目の方法はtransformation matrixと呼ばれる、マトリックス形状のノードを用いることです。
matrix
は4*4=16の要素で書かれます。
- id: <node_id>
transform:
matrix: 1 0 0 0 0 1 0 0 ...
matrix
要素の命令はcolumn-major(行優先) で書かれているので、列のベクトルは横方向に定義されます。
例えば、
$$
\begin{bmatrix}
1 & 0 & 0 & 1 \\
0 & 1 & 0 & 2 \\
0 & 0 & 1 & 3 \\
0 & 0 & 0 & 1
\end{bmatrix}
$$
というマトリックスは以下のように記述します。
- id: <node_id>
transform:
matrix: >
1 0 0 0
0 1 0 0
0 0 1 0
1 2 3 1
ベクターとマトリックスはストリング型のスカラで書かれます。シーケンスでは書きません。すなわち、レンダラーは以下のような形は受け付けません。
transform:
matrix: [1, 0, 0, 0, …]
他のトランスフォーメーションを表現する方法はtranslate
とrotate
とscale
を用いる方法です。translate
で移動、rotate
で回転,scale
で大きさを決定することができます。
- id: <node_id>
transform:
translate: 1 2 3
rotate:
axis: 1 0 0
angle: 90
scale: 2 2 2
translate
は 3つのベクター値からなっており、それぞれ3次元空間(x,y,z)の値によって定義されています。例では(x,y,z)方向がそれぞれ(1,2,3)移動しています。
rotate
は2つの要素からなります: axis
and angle
axis
は回転軸を定義し angle
ではその軸に対して反時計回りに何度回転させるかを記述します。 この例では、x軸方向に90度回転させています。
scale
は3次元のベクトル値で表され、それぞれ(x、y、z)方向にどれだけ大きくしたいかを定義します。例では、全方向に2倍の大きさに設定されています。
メッシュノード
mesh
と bsdf
ノードからなります。
mesh
は3Dモデルを表すトライアングルメッシュを参照します。 bsdf
はメッシュの材質情報を表すBSDFアセットを参照します。
- id: <node_id>
mesh: <mesh_asset_id>
bsdf: <bsdf_asset_id>
mesh
と bsdf
の両方を定義する必要があります。もしどちらか片方が記述されていない場合はレンダリング時にエラーが出て中断されます。
ライトノード
light
では光源の種類を選択します。
光源なしでは、レンダー画像は真っ黒になってしまうので少なくとも一つの光源は含む必要があります。
幾つかの種類の光源(例えば面光源)はメッシュと関連付けしなくてはいけません。
すなわちmesh
とbsdf
要素をlight
要素に付け加える必要があります。
- id: <node_id>
light: <light_asset_id>
センサーノード
sensor
はカメラを表します。
複数のセンサーノードを定義できますが、レンダリングに用いられるセンサーは必ず一つになります。シーン部分の子構造としてセンサーを表します。
scene:
sensor: <sensor_node_id>
- id: <sensor_node_id>
sensor: <sensor_asset_id>
センサーのトランスフォーメーションについては、OpenGLのシステムを採用しています。(詳しくはここを見てください) そのため、デフォルトのセンサーは上が+y方向に、正面が-z方向になっています。 この仕様はセンサーの視点トランスフォーメーションにのみ用いられます。
また、センサーノードに特化した形のトランスフォーメーションも利用可能です。
lookat
は センサーの位置(eye
)とセンサーの視点方向(center
)と真上を表すベクトル(up
)によって定義します。
transform:
lookat:
eye: <sensor_position>
center: <lookat_position>
up: <up_vector>
アクセラレーション構造
アクセラレーション構造はレイと三角形の交差判定に用います。 この要素の記述は省略できますが、もし明確な制御が必要である場合には選択することができます。
accel:
type: <accel_type>
params:
<parameters_for_accel>
...
レンダラ
renderer
部分で、レンダリング手法を選択できます。
レンダリング時間やサンプル数などの制御もここで行います。
細かい説明はレンダラで行います。
renderer:
type: <renderer_type>
params:
<parameters_for_renderer>
...