candy_pot.jpg


論理演算のいじめパタン

 Xi-TRACEは、球面や円柱面などに代表される二次曲面を使い、それらをandやorと言った論理演算を使って組み合わせることによって、複雑な形状を定義できるようになっています。
 今回は、論理演算のいじめパタンとして、キャンディポットを作ってみたいと思います。
 ガラスの瓶の中に、カラフルな四角いキャンディが詰まっていて、コルクの栓がはまっている、そんなイメージ。底面が四角い瓶ですが、ガラスの瓶ですから、手が切れそうな角ばった直方体ではなく、面取りをします。


二次曲面の組み合わせ

二次曲面

 二次曲面と言うのは、以下図に示すような球面、円柱面、円錐面など、x、y、zの二次式で決定される曲面の総称です。

quadratic.png

 方程式にすると以下の式で一般化できます。

quadeq.png

 a1〜a3=1、a4〜a9=0、a0=-R×Rと設定すると、見覚え有りませんか?x2+y2+z2=R×Rとなり、原点を中心とした半径Rの球の方程式になります。a1〜a6=0とすると:a7×x+a8×y+a9×z=−a0となり、平面の方程式となります。こんな感じで、上に示した長い方程式の係数a1〜a9、a0を適切に設定すると、球面や平面、円柱面、円錐面などが表現できるんです。
 この、10個の係数を持った方程式を設定するのは大変ですので、Xi-TRACEでは、shpere(球面)、plane(平面)、cylind(円柱面)、cone(円錐面)と言った命令が用意されており、もう少し簡単にデータを記述できるようになっています。

二次曲面の組み合わせ(論理演算)

 二次曲面の方程式で作った円柱面は、無限に長く伸びています。円柱面を使って柱やテーブルの脚などを表現するためには、有限の長さに切り詰めてやる必要があります。この時、ソリッドモデルという考え方が登場します。定義した曲面は、ペラペラな紙や板のようなものではなく、中身の詰まった(ソリッドな)物体である、と言うモデルです。
 cylind命令で定義される円柱面と、plane命令で定義される平面は、以下図の様な「中身の詰まった側」を持っています。

solid.png

 円柱面は中心が存在する側、平面は法線ベクタの向きと反対側、が中身の詰まった側となっています。
 円柱面1つと平面2つを以下図の様に組み合わせて、「中身の詰まった側」の共通部分(and)を取ると、有限の長さの円柱面を作ることができます。

and.png

 データの記述は、以下の様になります。

  and
  {
    cylind 0,0,0, 0,0,1, R;  // 原点を通り、z軸方向に伸びて、半径Rの円柱面
    plane 0,0,10, 0,0,1;  // x-y平面に平行で、(0,0,10)を含む平面
    plane 0,0,-10, 0,0,-1;  // x-y平面に平行で、(0,0,-10)を含む平面
  }

削る

 例えば、円柱面の半径を負の数に設定すると、「中身の詰まった側」が反転します。「中身の詰まった側」の反転は、not演算を使っても実現できます。

  cylind 0,0,0, 0,0,1, -R;
    ↓ 下の記述と同じ
  not
  {
    cylind 0,0,0, 0,0,1, R
  }


 not演算を使うと、半径2Rの円柱面の中身を半径Rの円柱面でくりぬいて、パイプ状の物体を定義することができるわけです。

not.png

和集合

 物体の論理演算には、もう一つ和集合(or演算)があります。
 例えば、以下の様に、同じ長さの円柱面を2本同時に切り取ろうとして、and演算を使った場合、どうなるでしょうか?

or.png

 データ記述は以下のような感じ。

  and
  {
    cylind -10,0,0, 0,1,0, R;
    cylind 10,0,0, 0,1,0, R;
    plane 0,R,0, 0,1,0;
    plane 0,-R,0, 0,-1,0;
  }


 図の方がわかりやすいと思うのですが、円柱面×2と平面×2の計4つの物体には、共通部分(and集合)が1つもないことがわかります。つまり、この4つにand演算を掛けてしまうと、「何も残らない」のです。実はこの場合、or演算を使って2つの円柱面を1つの物体に結合しておくと、期待通り、同じ長さの円柱面が2つ出来上がります。

  and
  {
    or
    {
      cylind -10,0,0, 0,1,0, R;
      cylind 10,0,0, 0,1,0, R;
    }
    plane 0,R,0, 0,1,0;
    plane 0,-R,0, 0,-1,0;
  }


 2つの「円柱面」だったのが、1つの「2か所に分かれた円柱面の集合」になったことで共通部分が残るようになった、という事です。


面取り

平面で面取り

 それでは、複雑な物体を組み合わせて作ってみます。工業品にせよ、工芸品にせよ、角が面取りされていると、優しい感じを受けます。丁寧に作り込まれた印象もあり、高級感みたいなものも生まれます。二次曲面によるモデリングでは、なにしろ数学的曲面同士の組み合わせのため、普通に組み合わせてしまうと、手が切れそうな尖った角が登場します。可能なら面取りをしておきたいですね。

mentori.png

 上図の様に、斜めに角を落とすだけでもだいぶ違います。しかも、この面取りは比較的簡単です。1つ平面を追加して、平面×2のand演算から平面×3のand演算にしてあげるだけです。

  and
  {
    plane 0,0,0, -1,0,0;
    plane 0,0,0, 0,1,0;
  }

    ↓ 面取り
  and
  {
    plane 0,0,0, -1,0,0;
    plane 0,0,0, 0,1,0;
    plane 0.2,-0.2,0, -1,1,0;  // 面取り用に追加した平面
  }

円弧を使って面取り

 今回は、ガラスの瓶や四角いキャンディを作ろうとしているので、平面と言うより、円弧を使って丸めたいところです。

mentori2.png

 さて、ゴールが見えたところで、これがまた結構しんどい。パズルみたい。どうやって、この形に持っていくか?「なに悩んでるの?こんなの簡単じゃん」と、思っているかもしれないですが……。いや、確かに簡単なのかもしれません。ただ、面倒くさい。答えは何通りもありますが、一番簡単そうなのは、下図の様な感じ。

divide.png

 補助で引いてあった十字の点線のところで分割して、各々別々の物体として作成し、分割した面と面がぴったり重なるような位置に調整します。境界面がぴったり重なっていて、全ての部品の屈折率が同じ値に設定されていれば、境界面は見えず、一繋ぎの物体に見えるようにレンダリングされます。

重なり

 複数の物体を組み合わせて透明な物体を作る時に、注意すべきことが1つあります。それは、物体と物体が重ならないように作ることです。「円弧を使って面取り」の時に出てきたように、境界面がぴったり重なる場合は問題ないのですが、例えば下図の様に、ある物体が別な物体の領域を侵食してしまうような重なり方はダメです。

overlap.png

 透明な物体の場合、物体の内部構造が外から見えてしまうのですが、上図の様な重なりがあると、物体の内部に境界面を生じてしまいます(下図上側)。

overlap2.jpg

 ちなみに、下側は、重なった2つの球面を和集合(or演算)で1つに結合した時のレンダリング結果です。

or2.png

 今回のキャンディポットでも、本体と口の部分の結合など、領域が重なっている部分が何か所かあり、or演算で一繋ぎの物体になるようにしてあります。


いじめパタンと検証

 と、いう事で、以下図の様なイメージ図を描いて、モデリングしてみました。目標の物体を構築していく中で、and/or/notなどの論理演算が何重にも入れ子になって、いじめパタンと言えるべきデータになったと思います。

image.png

 いじめパタンですが、データ作成中、バグらしきものは見つかりませんでした(安堵)。ただ、このデータ、レイトレーシングしてみると、所々「穴」が開くんですよ。

hole.jpg

 いくつかのパートに分割して作った物体をぴったりとくっつけるとき、一応、算数上はぴったりになるように動かしているのですが、何しろ、内部的には、最初に示したような10個の係数を持った二次曲面の方程式を使っていますし、更に、回転・拡大縮小・平行移動などの一次変換を実現するために4×4行列を計算していて、その逆行列を算出したりと、とにかく実数(浮動小数点数)計算が鬼のように繰り返される結果、ぴったりくっつけたつもりが、誤差の蓄積によってものすごく狭いギャップができていて、そこに引っかかると穴が開いたりします。

 後で示すデータソースを見ていただくと分かりますが、ソースの中ごろに「全体のorで一体化させるため、少々大きめに定義するためのマージン」として、変数mmを定義し、mm=1.005に設定してあります。1を超えた0.005の部分がマージンで、「ほんの少し大きめに定義することで、隣の物体とくっつける」作用を担っています。よって、mm=1と設定すると、本来のマージン無しの画像がレイトレーシングできるのですが、以下図の様に、ガラスの平らな面(直方体)が、周りの部品とつながらず、境界面が見えてしまいました……。

hole2.jpg

 「穴」どころじゃないですね……。半分は「仕様」みたいなものですので、うまく付き合ってやってください(と、開き直ってみる……)。


完成動画

 完成したデータと動画です。

  Xi-TRACEデータ:candy_pot.xitr
  マッピングデータ:candy_pot_cork.jpg (candy_pot.xitrと同じディレクトリにおいてください)

 論理演算のいじめパタンなので、あまり動かす意味は無かったですが……。さっきの「演算誤差」の例もありますので、いくつか角度を変えてみてみることも必要だったかと。



 余談ですが、マッピングデータはコルクの模様になるのですが、繰り返しマッピングした時に画像の切れ目で不連続にならないようにOlive+で加工してあります(簡易編集機能−相対スタンプで手動加工)。昔のドラクエの地図の様に、画像の上と下、右端と左端が連続しているので、繰り返しマッピングしても不連続な境界を生じません。


おまけの別バージョン

 別バージョンです。キャンディを食べきって空になったポットに指輪が入っています。正面の文字がかすれて、背面に新たなメッセージが……。

  Xi-TRACEデータ:candy_pot_ring.xitr



home

download

gallery