[Processing]pointSphereを見てみる

 少し前にVimeoにpointSphereという作品が投稿されていたのですが、ソースコードがダウンロードできることに気がついて、少し気になった点があったので、中身を覗いてみました。

 気になった点というのは、

  1. 球の表面上の点はどういう計算で配置したのか(位置を求めたのか)
  2. 球の表面上の点の太さをどのように実現したのか

です。

 中身を見てみると、球の表面上の点の配置はtoxiclibsのgeomutilsに含まれている、Vec3Dクラスを用いているようです。これはいいライブラリですね。Vec3D.randomVector()で適当な方向のベクトルを作り、Vec3D.scaleSelf(r)でベクトルの長さを半径分まで伸ばしています。もし、このライブラリを使わずに、(少しいい加減だけど)球の表面上の点を配置するなら、たとえばこんな方法はどうでしょうか。

[p5code]float px = random(radius);
float pl = sqrt(sq(radius) – sq(px));
float py = random(pl);
float pz = sqrt(sq(pl) – sq(py));
px *= (random(1) < 0.5 ? 1 : -1);
py *= (random(1) < 0.5 ? 1 : -1);
pz *= (random(1) < 0.5 ? 1 : -1);[/p5code]

px < radius

 1行目で、半径以下の範囲で、pxを定めます。

py2 + pz2 = radius2 – px2
pl = √(py2 + pz2) = √(radius2 – px2)

 2行目で、px⊥pyの直角三角形の斜面plを求めます。

py < pl

 3行目で、pl以下の範囲で、pyを定めます。

pl2 = pz2 + py2
pz = √(pl2 – py2)

 4行目で、pzの長さが自ずと定まります。
 5?7行目で、符号の±をランダムにとります。

 一応これで、球の表面上に点を配置できます。結構適当な書き方ですが、数式で考えれば一応あってるはずです。

 さてさて、お次は点の太さの実装方法です。ソースコードを良く見ると、表面上の点はellipse()で描いているようです。普通に考えるとカメラが回転してしまうと、円の描く方向が変わってしまうので、変な風に見えるのですが、このプログラムでは、円を描く前にrotateY()で回転をかけています。どうやら、ビルボードという手法を用いることで、ellipse()でも大丈夫なように調整しているようです。

 ビルボードというのは、2Dの画像を3D空間上でいい感じに表示させる方法の1つで、常にカメラの正面の方向を向くように画像を回転させるテクニックです。「ビルボード 3D」とかで検索すると関連記事が出てくると思います。

 たぶん私だったらビルボードなんてテクニックをすっかり忘れていたので、sphereDetail()で精度を落としてsphere()で球を描いてしまうと思います。sphere()なら、もともとどの方向から見ても球ですから。もちろん、ellipse()に比べたらその描画コストは計り知れませんけれども。

 うまいの人のプログラムはやっぱり参考になりますね

About: uechoco