fishbowl.jpg


金魚鉢

 金魚鉢をモチーフに、泳ぐ2匹の出目金を作ってみました。

出目金

 出目金は、球面と平面だけの組み合わせで作った、だいぶデフォルメされた形状。今回はそこに、球面へのマッピングを適用して、赤系と黒の出目金を作ってみました。

  load $(dir)$/$(file)"_1.jpg";
  cmap cdeme1, 0,0, fwid - 1,fhei - 1, fwid,fhei, interpol;
  attr deme=
  {
    refl 0.10,10,0.2;
    diff 0.90,0.00;
    nmap cdeme1;
    msph 0,0,0, 0,0,1, 0,1,0, 1,1;
    mreg 0,0, 0,0, -0.5,-0.5;
  };

 球面へのマッピングだと、水平方向360°、鉛直方向180°の全方位に画像データが張り付きます。←←最近どこかで使ったような表現……。「YouTubeの360度動画を生成する」で解説した、正距円筒図法(equirectangular)ですね。

scrimg.png

 最初は、下図の様に、マッピングデータとの対応を取りやすい画像を貼り付けて、出目金のどのあたりに、画像のどの部分が張り付くかを確かめてみました。

fishbowl_equi.png

demequi.jpg

 これを眺めながら、出目金のマッピングデータを作図します。

fishbowl_1.jpg

 正距円筒図法で説明した通り、画像の右端と左端はつながっていて、真後ろの映像になっていますので、時折、画像をスクロール(Olive+の「フィルタメニュー ⇒ 変形 ⇒ スクロール」を使用)して、右端と左端の映像が連続する(つながる)ように気を付けて作図します。お腹側が白っぽい金魚を意識して、下の方は白くしてみました。

fishbowl_2.jpg

 出目金が動いた時に、不規則に光を反射するように、マッピングデータと同じ画像データを使って、凹凸マッピングをかけておきました。

  load $(dir)$/$(file)"_1.jpg";
  bmap bdeme1, 0,0, fwid - 1,fhei - 1, fwid,fhei;
  bump deme=
  {
    nmap bdeme1, 3;
    msph 0,0,0, 0,0,1, 0,1,0, 1,1;
    mreg 0,0, 0,0, -0.5,-0.5;
  };

 本当は、うろこの形を凹凸データとして用意しておき、マッピングした方がリアルだったのかもしれませんが、ちょっと手を抜いてます。

玉石

 金魚鉢の底には、玉石を敷いてみました。その「敷き方」を少し解説しておきます。まず、単純にランダムに玉石をちりばめた場合、以下のようになります。

stone1.jpg

 玉石同士がくっついてしまったり、たくさんの玉石をちりばめているにもかかわらず、空き地が目立っていたり、今一つでした。
 問題の根っこは、玉石同士がくっついてしまったことにあると考えました。そこで、以下の様に座標を決定するルールを作りました。

  1. ランダムに玉石の座標を求める
  2. 玉石の座標を配列変数として記憶する
  3. 再びランダムに玉石の座標を求める
  4. 2回目以降は、既に決定した玉石の座標を配列変数から参照して、新たに求めたランダム座標に玉石を置いた場合に、玉石同士がくっつかないことを確認する
  5. 配列内の玉石とくっついてしまう場合は、ランダムな座標を求めるところ(3)からやり直し
    1. 一定回数以上繰り返しても座標が決まらなかった場合は、「空き地がなくなってしまった」と判断して、終了する(指定数より少ない数で終了する場合あり)。
    2. 乱数を使っているので、実際には「空き地」が残っていても、誤判定してしまう可能性があることに留意。
  6. 配列内の玉石とくっつかなかった場合、新しい座標を配列変数に記憶してから、次の玉石座標を求める手順(3)へ戻る

 玉石の半径は全てTRと言う変数で一定にしたので、配列には中心座標値だけを記憶しておけば、新たに求めたランダム座標(cx,cy)と、i番目の配列に記憶した中心座標(ax[i], ay[i])の玉石がくっつくかどうか?は、以下の式で判定できます。

tamaeq.png
なら、重なってくっついてしまう。

 くっつかないように対策した結果がこちら(下図)。

stone2.jpg

 いい感じで、まばらに散らばってくれました。

 乱数を使って空き地を探しながら座標を求めること、決定した座標が増えていくと参照すべき配列数が増えて処理時間が増大すること、等から、処理時間がかかるので、求めた座標値はファイルに出力しておき、ファイルが見つからなかった場合だけ、作り直すようにしてあります。

※注)見直してみたら、玉石の色を決定するところ(HSV色座標系のH(ue、色相))で、値の範囲を間違っていました。たまたま、作者のイメージ通りに出来上がってしまったため、気が付きませんでした(当初のイメージでは、もう少し、オレンジっぽい色を混ぜるつもりでしたが……)。と、いう事で結果オーライにしておきます。

水草

 水の中でユラユラと揺れる水草。これって結構表現難しいですよね。我ながら、それらしく動かせたのではないか?と満足しているのですが、理論も何もなくカットアンドトライでやって見たらそれらしくなっただけなので、特に説明できることはありません(1^^;)。

 クネクネ曲がった茎と葉っぱ、一段分を作り:

  // 一段分
  para 0,GL,0;
  screwy -30 + sind (360*(fpda + lv/5))*2;
  screwz -20 + sind (360*(fpda + lv/5))*2;
  leaf;
  rod 0,0,0, 0,GL,0, GR;
  lv=lv + 1;

mizukusa.png

 これを五段繋げてみました。rod(茎)とleaf(葉っぱ)は、水草を構成する部品を定義する手続きです。中身はソースデータをご参照ください。
 変数lvが一段毎にインクリメントされていて、動きを付けるscrew命令(等)に使っている三角関数の位相を変化させています。結果、段ごとに少しづつずれて動きが発生するようになっており、なんとなく、ユラユラして見えるようにできているものと思われます。


完成動画

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

Xi-TRACEデータ fishbowl.xitr
マッピングデータ(赤系) fishbowl_1.jpg
マッピングデータ(黒) fishbowl_2.jpg
マッピングデータ(木目) fishbowl_m.jpg



home

download

gallery