pearl_necklace.jpg


真珠のネックレス

 真珠って、形は丸いだけ(球体、球面)なんですけど、色がね、ただの「白い球」ではないのですよ。今回は、真珠のネックレスに挑戦します。

真珠のモデリング

 モデリングと言っても、「形は球面」で以上終了。問題は色ですね。白っぽい真珠、黄色っぽい(ゴールド?)真珠、青味がかった真珠、ピンクの真珠、と、ベースの色合いもさることながら、何層も重なった構造による虹色。どうやって表現するか?ですね。
 まず、ベースのカラーは、適当に「こんな感じかな?」とブレンドしてみて、RGB=(236, 229, 209)としました。ほぼ白だけど、少し黄色がかった色。Olive+で新規ウインドウを開き、「編集メニュー ⇒ 簡易編集」、「アンドゥ」ボタンの下の領域をクリックして、カラーピッカを起動、適当にイメージでブレンドして、RGB値を拾いました。

colpick.png

 ピンクパールとか、ベースのカラーを変えたい場合は、同様にして色をブレンドし、ベースカラーを決めてメモしておいてください。お手本(真珠の写真等)がお手元にある時は、簡易編集画面の「スポイト・(点)」や「スポイト●(範囲内平均)」などもご活用ください。

 さて、真珠が虹色に見えるのは、真珠の表面に複数の層が重なっているため、屈折なのやら、回折なのやら(良く知りませんが(1^^;))、で、分光するんですね。作者のページでも何度か説明した記憶がありますが、分光するのは光が波だからです。でも、レイトレーシングでは、光は光線(レイ)でしかないので、黙っていても分光して虹色に輝くことはありません。
 何か他の方法で、それらしく見せる工夫が必要です。思いつくのがカラーマッピング。読み込んだ画像をそのまま物体の色として貼り付ける技法です。今回の用途にベストなのは、「反射マッピング」でしょう。

 先に、「通常のマッピング」を球面へのマッピング(attr命令−msph)を例に説明します(下図)。

mapping.png

 一方、「反射マッピング」は、交点で鏡面反射したと仮定した場合の反射ベクタを算出し、この反射ベクタの延長線上に見えている色を交点の色とするマッピング手法です(下図)。

maprefl.png

 二つの図を見比べていただくと、交点の色として画像データを引っ張ってくる場所がずれていることがお解りになるでしょう。この手法は、金属面や鏡面に映り込む、周囲の景色を貼り付ける(マッピング)するための機能であり、反射光が虹色に分光する現象のエミュレートとは相性が良いはず。
 使い方ですが、いつもの様にマッピングの指定をして、「option mrefl;」を追記するだけです。

  attr pearl=
  {
    refl 0.20,2,0.5;
    diff 1.00,0.20;
    nmap pearl;
    msph 0,0,0, 0,-1,0, 0,0,1, 1,1;
    mreg 0,0, 0,0, -0.5,-0.5;
    option mrefl;  // 追加した反射マッピングの指定。
  };

虹色を描画する

 次は、マッピングデータの準備(作成)。「虹色」って、どんな色ですか?作者のイメージだと、「赤燈黄緑青藍紫、虹の七色」というフレーズが頭に浮かびます。でも、虹が七色なのは、どうやらニュートンさんの虹の研究を元にした、近代教育の賜物らしいです。外国では、5色だったり6色だったり、古来の日本でも七色ではなかったとか。
 そもそも物理的には、屈折率が光の波長の関数になっていて、空中の水滴の中を太陽光が屈折・反射することで分光して虹色に見える現象です。すなわち、虹とは連続したスペクトルで、n色と限定できるものではないことを知っていますが、今回は、「虹の七色」にこだわって、虹色を描画してみたいと思います。

 その前提で七色、赤燈黄緑青藍紫、を眺めてみると、HSV座標系における、色相(Hue)の順番に並んでいるようです。

huerainbw.png

 HSVの色相は、360°でぐるっと一周しているのですが、その中の0°〜300°までの間が虹の七色ですね。ただ、色と色の位置関係、間隔がバラバラです。色相の数値をそのまま等間隔で、7色に量子化してみると、こんな感じ(↓)。

huerainbwq.png

 橙(オレンジ)だか、黄色だかが飛んでしまっているし、緑から青にかけての色も、何だか違和感があります。そこで、補正テーブルを作って、「赤燈黄緑青藍紫」で七色を描画してみます(↓)。

huerainbw7.png

 色相については、いい感じ。上の図だと、HSVのH以外は、S=1、V=1に固定して描画しているのですが、これだと藍色と紫色が明るすぎて、それらしく見えません。そこでさらに、明度(Value)の値もテーブルを作って補正してみます(↓)。

huerainbwf.png

 補正値(テーブル)は以下の通り。他の色に比べて明るすぎる黄色の明度も少し抑えてあります。

   
  varray rh:0= 0, 30, 60, 120, 220, 240, 280; // 色相の補正値
  varray rv:0= 1, 1, 0.9, 1, 0.9, 0.6, 0.6; // 明度の補正値

 下図上側がHSVそのまま、下側が補正後の虹色を滑らかに描画してみた結果。

huerainbws.png

 補正後の方(下側)が、緑〜青の範囲が圧縮され、赤〜黄と紫の範囲が引き伸ばされているイメージ。「どっちもどっち」とも言えるし、「どっちでもいいじゃん」とも言えそう……。

真珠(完成?)

 マッピングデータを生成する準備が整いましたので、データを作成します。
 最初に決めたベースの色:

  var pix_pearl;
  col2pix 236/255, 229/255, 209/255, pix_pearl;


 拾ってきた色データ、RGB=(236, 229, 209)は、各成分の値の範囲が0〜255ですが、col2pixに渡す成分は0〜1ですので、255で除することによって、調整しています。生成したピクセル値をpix_pearlという名前の変数に格納して使います。
 手順は以下の通り:

1) ベースカラー(pix_pearl)で塗りつぶす
2) 1)に虹色を描画する
3) 2)をスクランブルする
4) 2)と3)をブレンドする
5) 4)と1)をブレンドする
6) 5)の全体をぼかす

 完成動画の所でDLできるスクリプト(pearl_necklace_mkmp.xitr)を実行すると、最後に6)の画像だけが残ります。が、ここで完成ではありません。
 実際には、この画像を「金魚鉢」で貼り付けたように、360°のequirectなマッピングデータとして使用します。

scrimg.png

 つまり、画像の右端と左端は(共に真後ろの映像なので)、滑らかにつながっていないといけません。Olive+で6)のデータを開き、「編集メニュー ⇒ 簡易編集」で簡易編集モードに入ります。「フィルタ→変形→スクロール」で画像の横幅の半分だけスクロールしてみると、中央に不連続な線が現れます。

edit.jpg

 ここからは手作業です。このまま簡易編集モードで、左上のツールメニューから「スタンプ●(相対)」を選び、「設定」ボタンで「図形描画(■、●) ⇒ 半透明(中心→周辺」を選択、「図形描画(■、●) ⇒ 不透明度:0.75」を指定します。上の図の様に、丸いカーソルが同じ高さで横に並ぶようにして、中央の線を消していきます(Shiftキーを押しながら、線の部分を左クリックしていく)。
 これで、360°ぐるっと、綺麗に連続したマッピングデータになりましたので、簡易編集モードを抜けて、セーブします。

 試しに球面にマッピングしてみた結果がこちら(↓)。

pearl1.jpg

 真珠に見えない??しかし、この辺でご容赦を……m(1__)m。
 最後の手作業は、納得の行くマッピングデータが完成した後で、最後に1回だけ実施すれば良いので、スクリプトの方のパラメータをいじってみて、真珠っぽく見えるマッピングデータに挑戦してみてください。作者は上の状態でギブアップ。結構、センスが問われるようです……。

ネックレスのモデリング

 個人的にも納得の出来には程遠いですが、ひとまず、真珠(らしきもの)が完成したので、次はネックレスをモデリングします。
 ネックレスの形に真珠を配置します。規則的に、円形や楕円形に並べるのは楽ですが、それって、ネックレスに見えますかね??ただ、丸く球面が並んでいるだけ、ですよね?「首から外して、無造作に机の上に置いた」様な感じで真珠を並べるため、以下図の様な、フリーハンドで描いた図形を使用することにします。

necklace.png

 図は、白黒画像とします。白地に黒い線でネックレスの形を描いたグラフィックデータです。まず、探索開始位置(プログラム上は(0, 0)点)から、斜め下方向へ黒点を探していきます。探索対象座標のピクセル値を取り込み(getpix命令)、輝度値に変換(pix2lum命令)して、輝度値が0.5より大きい(白点)か小さいか(黒点)で判定します。

necks1.png

 斜めに下がりながら、最初に見つけた黒点を中心に真珠(緑円)を配置します。緑の円周上で黒点を探します。上図では2か所に見つかりますが、どちらか、最初に見つかった一方を選択して進みます。

necks2.png

 ここ、大事なのですが、真珠を置いたら、その円(緑円)を包含する領域を塗りつぶして、その範囲の黒点を消去します。ここから先の黒点探索で、一旦真珠を置いた地点の黒点が再び見つかってしまう事を避けるためです。
 先ほど、塗りつぶす前に見つけていた赤丸を中心とする赤円周上で、再び黒点を探します。塗りつぶしたおかげで、赤円周上には黒点が1つしか見つからない状況になっていることにお気づきになりますか?

necks3.png

 赤円周上に見つけた黒点を中心に、2個目の真珠(緑円)を配置します。さらに、緑円周上の黒点を探します。

necks4.png

 1個目と同様に、真珠を置いた緑円を包含する領域を塗りつぶします。塗りつぶす前に見つけておいた黒点を中心とする赤円周上で黒点を探します。
 後は、この繰り返し。真珠の半径を持つ円周上の黒点を探索しているため、緑→赤→緑→赤→……の繰り返しで、2回に1回、緑の時だけ真珠を配置します。
 円周上に黒点が見つからなくなったら、終了します。うまく探索できた場合は、ぐるっと一周に真珠が配置されるはずです。

 最初に示したフリーハンド図形の探索結果がこちら(↓)。

neckse.png

 あまりまじめに作り込んでいないので、線が細かったり、曲がり方が鋭角すぎたり、線と線が接近しすぎたり、交差していると、探索を誤るケースがあります。太めの線で滑らかに描画した画像を使用することを推奨します。

金具のモデリング

 ネックレスを止めるのに使用する金具(丸環)の写真がこちら(下図)。

fitting.jpg

 んー、まじか。「トーラス」ではないですか!「数学曲面のモデリング」のページで解説したように、トーラスは二次曲面では表現できないため、Xi-TRACEが苦手とする形状なんですよね。とは言え、「数学曲面のモデリング」のページでも作成したように、ポリゴンを使ってトーラスを作り出す機能がXi-TRACEにはありますので、それを活用することにします。
 トーラスのポリゴンデータ(.obj)を以下の様に作成します。

  ifnacc $(dir)$/$(file)"_1_out.obj"
  {
    var polygon.torus.R1=R1;
    var polygon.torus.R2=R2;
    polygon torus, -R3,-R3,-R2, R3,R3,R2, R3/20,
      $(dir)$/$(file)"_1_out.obj";
  }
  ifnacc $(dir)$/$(file)"_2_out.obj"
  {
    var polygon.torus.R1=R1;
    var polygon.torus.R2=0.6*R2;
    polygon torus, -R3,-R3,-R2, R3,R3,R2, R3/20,
      $(dir)$/$(file)"_2_out.obj";
  }


 組み込み手続きtorusのお陰で、生成時間は短縮されましたが、毎回作り直すのは芸が無いので、ポリゴンデータファイルが見つかったらそのまま使う、見つからなかったら生成する、という論理にしてあります。また、外側のトーラスと、内側のトーラスで、少し太さが異なるトーラスが2種類必要ですので、2種類生成しています。
 次に、生成したポリゴンデータを読み込んで物体を定義する部分。

  procedure トーラス l,m,n, typ
  {
    // 中心座標(l,m,n)、中心軸がz軸方向のトーラスを定義する。
    // typ:1/2(それ以外だとERROR)
    nvar typ=1;
    para l,m,n;
    boundary cuboid 0,0,0, R3,R3,R2
    {
      or
      {
        wobj $(dir)$/$(file)"_"#(typ)"_out.obj";
      }
    }
  }
  procedure 丸環 l,m,n
  {
    // ネックレスの金具を定義する
    para l,m,n;
    and
    {
      トーラス 0,0,0, 1;
      or
      {
        rotz -25;
        plane 0,0,0, 0,-1,0;
        rotz 50;
        plane 0,0,0, 0,1,0;
      }
    }
    トーラス 0,0,0, 2;
  }


 手続き「トーラス」で、ポリゴンデータ(.obj)を読み込み、ポリゴン物体を定義します。
 手続き「丸環」で、手続き「トーラス」を2回呼んで、太いトーラスと細いトーラスを定義します。太いトーラスには、二次曲面の平面を使って、論理演算(andとor)を施し、切り欠き部分を作っています。
 試しにレイトレーシングした結果が以下図です。

fittingrt.jpg

 Xi-TRACEに於いて、ポリゴンで作った物体はサーフェイスモデル(表面だけ、中身が空っぽ)なので、二次曲面で切り取った切り欠き部分から空洞の内部が見えています。ネックレスの金具も同様な構造なので、今回は丁度良いかと思われます。

 まあ、こんなところで良いでしょう。最終的には真珠のネックレスを俯瞰するので、留め具の部分なんて、小さくてほとんど見えないはず……。ちなみに、見えないかもしれない、この2つのトーラスに使用されたポリゴン数は3500枚超でした。

 折角、トーラスのポリゴンモデルを生成したので、チェーンもトーラスで作ろうかと思いましたが、無駄にポリゴン数を喰うだけなので、チェーン部分は二次曲面で作ることにしました。「リングが回転しながら倒れる」で作成した、円錐を使ったリング状の物体を使って、チェーンをつなげてみます。

chain.jpg


完成動画

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

1) Xi-TRACEデータ pearl_necklace.xitr
2) ネックレスの形状データ pearl_necklace_shape.xpic
3) 真珠の色マッピングデータ pearl_necklace_cmap.jpg
4) 真珠のマッピングデータ生成スクリプト pearl_necklace_mkmp.xitr
5) 真珠単体のテスト用 pearl_necklace_pearl.xitr

 レイトレーシングに必要なのは、1)〜3)です。4)は、3)を自分で生成したり、調整したりする時に使用するスクリプトになっています。4)で生成したマッピングデータのテスト用に5)を使うことができます。



 ヒドイ……、苦労して作った色合いも、ネックレスにして引きの画像にしてしまうと、「ただの白い球」、トホホ(昭和)。金具の丸環も同じ、相当な数のポリゴンを使って作り込んでも、小さくて、ほとんど見えない……。
 せめて、アップにした画像を使いたくて、ネックレスをぐるっと一周眺める動画にしてみました。


home

download

gallery