p5_underground

所謂クリエイティブコーディングとか音楽とかをぼちぼち楽しんでいきます

20180330_球を描く方法(球面座標系を使う)

ジェネラティブアートに出てくるやつ。説明になっているのかはわかりませんが、自分なりの理解で書いておきます。

 

まず球を三角関数で表現する数式がどっから出てきたのという感じなんですが、これです。

球面座標系 - Wikipedia

球面座標系。3次元空間上の任意の点を表すには、普通x, y, zの3つの座標を決めればいいんだけれど、それ以外の方法として、円柱座標系とかこれがある。平面でいうと、xyの直交座標の他に、極座標があるというのと同じ話。

 

Spherical with grid.svg
By Andeggs - 投稿者自身による作品, GFDL, Link

 

簡単に言うと、球面座標は、原点とその点とを結んだ線分の長さrと、その線分とz軸がなす角θと、その線分がxy平面につくる影とx軸とのなす角φを使って、3次元空間上の任意の点を表す方法です。3次元空間だしまあ3つのパラメータを固定してやれば1箇所に定まりますよね。で、これを直交座標に直すには次の式を使います。まあこれは当たり前というか、上の図を見ていけばすぐわかると思います。

x = r sinθ cosφ

y = r sinθ sinφ

z = r cosθ

 

ここでrが原点からの距離だったので、これを一定にして角度θとφはなんでもいいよ~としてやれば、これは球を表すことになりますね。これで本にでてくる公式になります。2つの角度θとφを決めてやれば、それに対応する球面上の点の座標がわかります。

 

じゃあこれを使って球を書いていく。サンプルだとθもφも同時に動かしているけど、たぶん片方固定しつつ片方動かしたほうが、公式の意味するところは分かりやすいはずなので、その方針でやっていきます。

 

2次元平面上で上から順に埋め尽くすように点を書いていくときには、xとyについて2重for文を書いて、2次元平面上を走査するということをしました。それと同様の要領で、角度θとφについての2重ループを作って、それぞれ0~360°の範囲を走査しつつ点を打っていけばいけるはず。

ということで、ジェネラティブアートのサンプルを少しいじって作ってみました。直観的にはθとφをforで変化させたかったけど、アニメーションにしたかったのでdrawループを使ってます。

import processing.opengl.*;

int radius = 100;
int phi = 0;
int theta = 0;
float lastx = 0; 
float lasty = 0;
float lastz = 0;

void setup() {
  size(500, 300, OPENGL);
  background(0);
  stroke(255);
} 
  
void draw() {
  translate(width/2, height/2, 0);  
  rotateX(radians(45));
  rotateY(radians(30));

  float radianPhi = radians(phi);
  float radianTheta = radians(theta);
     
  float thisx = 0 + (radius * cos(radianPhi) * sin(radianTheta));
  float thisy = 0 + (radius * sin(radianPhi) * sin(radianTheta));
  float thisz = 0 + (radius * cos(radianTheta));
     
  if (lastx != 0) {
    line(thisx, thisy, thisz, lastx, lasty, lastz);
  }
  lastx = thisx; 
  lasty = thisy; 
  lastz = thisz;

  phi += 10;
  if(phi == 360){
    theta += 10;
    phi = 0;
  }

}

見やすいように回転させてますが、さっきの球面座標でいうと、開始点である球のてっぺん方向がz軸の正の向きで、1段下にずれるところがx軸の正の向きということになりますね。φを0~360°で1周させて、360°になったらθを10°ずらしてφはリセット、また1周させて...というように動かしています。

 

以上。

20180329_3D描画と3Dノイズ

一応メモ。

・3D

Processingで3D画像を描くにはまずsize()に3番目の引数を追加し、レンダラーを指定する必要がある。

一番シンプルな例として、球を描画するサンプルプログラムがある。描くには、sphere()を使って、半径だけ指定してやれば原点中心で球ができる。位置を変えるには2Dの場合、描画関数の引数として指定してやることができたが、sphere()にはその機能はないので、translate()を使って原点を動かす。

Processingにおける3D空間は、z軸の正の方向からxy平面を見ている形になっている。すなわち、zの値を0にしてやれば、2Dで描画した場合と同じ風景が見える。最初の視点でどれくらいxy平面から離れているのかはいまいちよくわからないのだが、たぶん233ぐらい。(sizeの初期設定などで変わったりするのかもしれないが。)視点を動かせば、球の中に入ったりも当然する。

 

・2次元のノイズを3Dで見る

2次元のノイズの可視化のプログラムを少しいじったようなもの。ノイズ空間としては2次元なのだけれど、表示する際、ノイズ空間上のyを、描画空間でyと同時にzにも対応させてやる。そうすることで、yが大きいほど奥に表示されることになり、後ろへ傾いた板を見ているような形になる。

これの面白いところは、ノイズの出力値を従来通りの濃度透明度に加え、各座標に表示される球の大きさにも対応させているところ。そもそもグラフとして考えた場合、2次元空間に対応するノイズの大きさを表現するには、3次元のグラフである必要があった。もともとはそれを各点の濃度や透明度に対応させて、サーモグラフィーのような形で表現していた。視点が3Dになったことで、本当の3Dグラフのように、ノイズ値が山脈のようになっているのがわかる。球の大きさを一定にしてやると、雲の絵が傾いている状態になる。

 

・3Dノイズ

3次元のノイズ空間をそのまま3次元空間に対応させる。見づらいので視点移動させて、箱の中に煙が充満したようになってるのを見るなど。

20180329_ノイズシーケンス

通称「ジェネラティブアート本」におけるノイズの扱いをまとめてみる。

 

まず予測不可能な形状を生み出すことの面白さが語られて、それをコンピュータで作り出す方法として、random()→noise()が導入される。まずは線をえがく方法として。次に、サインカーブや螺旋との組み合わせを例に、自分なりのアイデアにノイズを用いるという考え方を深める。さらにもっと面白くするには、というので次元を加える。2次元のノイズをいくつかの表現方法で可視化する。そこに時間という次元を加え、アニメーションにする。

このあたりから最近やった内容なので詳しく。アニメーションで何を動かすかというと、それまでは2次元のノイズ平面をforで走査して値を取得し、描画平面に投射していたのだが、その走査1ステップよりも小さい幅で、時間経過によってノイズ平面上を動く。これによって雲が流れているような表現ができたりする。

しかしまだこれでは1方向に流れているだけなので面白くない。そこで、毎時間ステップにおけるノイズ平面上の移動幅に、ノイズによる変動を加える。このノイズの入力値自体は、毎時間ステップで一定量増加させる。

これによって、かなり複雑で自然現象っぽい表現が可能になる。(急にあいまいな文章表現なのは、いまいち見ても何が起こっているのかよくわからなくなってきたから。)雲でいうと、不規則に流れつつ、雲の形自体も変化しているような。

この手法について、「2つの(1次元の)ノイズシーケンスをカメラ位置に与えるのに使った」と表現されている。さらに、コード全体におけるノイズシーケンスについて「結びつけることで2次元のノイズ値を得るためのxnoiseとynoise、そして動きの1次元的な方向性を与えるxstartNoiseとystartNoiseの4つを使っています」とある。

このあたりの表現がわかるようでわからないので今考えている。変数名にnoiseと入ってる変数は、ノイズの入力値。xnoiseとynoiseは2次元のノイズって言ってる通りnoise(xnoise, ynoise)の形で使って、この出力値はそれぞれの座標における描画パラメータ(色とか)に用いる。xstartNoiseとystartNoiseはnoise(xstartNoise)の形で使って、出力値はノイズ平面上の移動幅に用いる。

つまりノイズシーケンスというのは、規則的に変化するノイズの種(入力値)のことということでいいのかな。というか、そのノイズの種を変化させるためのループのことか。別のところでfor文自体をシーケンスと言ってるような記述があった。

表現をどうこう言ってるのは、自分で好きなタイミングで使えるテクニックとして体系化しておきたいから。

 

つまりは、何かに予測不可能な揺らぎを与えたいとき(空間的、時間的に)、対象とする次元の変数についてのノイズの種を用意してやって、それをノイズに放り込んで出力させればいいということか。わかったかもしれない。

うーん、こう一般的に書いてみるとかなりなんでも一般的に使えそうなテクニックに思える。

 

以上。まとめると言ったもののまだ途中です。書こうと思ったら書くと思います。

20180327_ピクセル操作

昨日の発光表現ででてきたPImageを調べて出てきたページを一通り試して理解。

www.d-improvement.jp

 

まとめると以下のようなことをやってる。

・画面の色を調べて、ほかのところで使う。

 

・↑を使うと、モザイクのようなことができる。(最初から全体を表示するパターンのほか、draw()内でランダムな座標を指定して一個一個描画するというのも。ここでrandom()ではなくnoise()を使ってみたところ、noiseだとかなり中心付近に偏りやすくなるというのがよく分かった)

f:id:nu2k:20180327223101p:plain

 

・色としてだけでなく、色相彩度明度や各色の成分の値としても取得できる。

 

 

画面上にある画像情報をぱっと取得できるというのは自分にとっては割と目新しく感じる。すべてを計算で設計して作っていく、というところからは一つ次元が変わって、今ある状況から直感的に動かすことができるってことだと思うし。

20180326_2

さっきの書いたらちょっと疲れたけど、忘れんうちにもう一個。

 

・2Dパーリンノイズの視覚化(ジェネラティブアート本より)

processingにはnoise()という関数があって、これは乱数を返してくれるものなんだけれど、ただでたらめに返すんじゃなくて、入力された値に対してある程度連続的な関数のような形で値を返してくれる。3次元まで対応してるらしい。

 【構文】 
noise(x) 
noise(x, y) 
noise(x, y, z) 

【パラメータ】 
x ノイズ空間におけるx座標(float) 
y ノイズ空間におけるy座標(float) 
z ノイズ空間におけるz座標(float) 

【戻り値】 
0.0から1.0の間の値(float)

http://www.musashinodenpa.com/p5/index.php?pos=476

 

このノイズ空間というのをそのまま描画空間の座標に対応づけて、ノイズの出力値をアルファ値とかに対応させて点を書いてやれば、視覚化できる。雲みたいなテクスチャ感。gimpでなんかこういうの描けた気がする。

f:id:nu2k:20180326210659p:plain

ノイズの値を回転角度で表現してやると、なにやら風に吹かれる草原のようになる。

f:id:nu2k:20180326210606p:plain

20180326

ではまたやっていきたいと思います。

とりあえずやったことの記録だけでも。

 

・processingにおける発光表現

p5aholic.hatenablog.com

 

新しいPC(もらった)のテストついでにprocessing入れて動かした。

前のPCだと加算合成を使おうとするとグラボの関係かエラー吐いていたのだが、こっちでは問題なくいけた。

動かしたついでに理解を試みる。

PImageとかcreateImageとかが今まであまりなじみなかったけれどざっくり把握。

 

1.PImage型の変数(クラス?)というのがあって、createImage()を使うとサイズとフォーマットが指定できる。

【構文】 
createImage(width, height, format) 

【パラメータ】 
width 幅をピクセル数で指定 (int) 
height 高さをピクセル数で指定 (int) 
format 画像フォーマット (RGB, ARGB, ALPHA) 

【戻り値】 
PImageまたはnull 

http://www.musashinodenpa.com/p5/index.php?pos=1053

 

2.(PImage型変数).pixels[番地] = color(r, g, b)    て感じでその画像のピクセルの色を直接指定できる。

www.d-improvement.jp

 

この2つは多分前提知識で、元記事の本題は次。

 

3.ランダムに決定したrgbの値を、各ピクセルの物体中心からの距離に相当する量(「distance」とする)で割ることで、発光球体の表現ができる。

 

直接色指定してるわけだから、この表現自体には加算合成は関係ないよね?切ったらどうなるの?と思って切ったらこんな感じ。記事に書いている通り透過のための処理なんだろう。

f:id:nu2k:20180326203725p:plain

 

これからは積極的に発光していきたい。