De Jong アトラクターの応用:Processing 3D アニメーション作例
FALさんの De Jong アトラクターでの作図が面白かったので、これを使って Processing 3D アニメーションを作ってみたいと思います。
アトラクターとは?
この記事は全文無料でお読みいただけます。もしお気に召しましたら投げ銭お願いしますね。😉✨
De Jong アトラクター
様々なアトラクターが知られていますが、今回作画に使う De Jong アトラクターは下記の数式で表すことのできるアトラクターです。
x[n + 1] = sin(a * y[n]) - cos(b * x[n]);
y[n + 1] = sin(c * x[n]) - cos(d * y[n]);
パラメータ a, b, c, d の値によって様々な形が描かれます。
この例では 50,000個の点を描画していますが、パラメータ値によってはこのように数カ所に収束する場合もあります。
比較的単純な数式で、こんなにいろいろなパターンの図が描かれるなんて不思議ですね。
次元を超えろ!
この De Jong アトラクターでの作図、2D なのに 3D みたいに見えませんか?
これ、最初から 3D で描画したら一体どうなるんでしょう?
面白そうですね。 早速やってみましょう!
3D で描画する場合、数式はどうなるでしょうか?
元々の数式の右辺を見てみると、sin() と cos() は共通、 x, y がたすき掛けになっています。
x[n + 1] = sin(a * y[n]) - cos(b * x[n]);
y[n + 1] = sin(c * x[n]) - cos(d * y[n]);
3D の場合は z を求める式が必要になるわけですが、 sin() - cos() の他に何か別の項を追加してしまうと、それはもう De Jong アトラクターではなくなってしまいそうです。
x, y のたすき掛けのところを、x, y, z にするのが良さそうです。
x[n + 1] = sin(a * y[n]) - cos(b * x[n]);
y[n + 1] = sin(c * z[n]) - cos(d * y[n]);
z[n + 1] = sin(c * x[n]) - cos(d * z[n]);
x, y, z 3つのたすき掛けはこんな感じでしょうか。
でも、この数式で本当に De Jong アトラクターの 3D 版と言えるのでしょうか?
う〜ん、わかんない。
ここは「De Jong アトラクターをヒントに作る 3D アニメーション」と名乗ることにしときましょう。(謙虚♥)
Processing での 3D 描画
Processing で 3D 描画する場合、まずは setup() 中の size() で P3D を指定しましょう。
size(720, 720, P3D);
あとは描画時の座標指定で x, y, z の 3軸を指定すればよいのですが、ellipse() や rect() は x, y の 2軸しか指定できません。
このような場合は translate() を使って座標指定します。
translate(x, y ,z);
ellipse(0, 0, size, size);
何個も円を描画する場合、translate() は毎回ゼロ基準の絶対座標になるのではなく、以前に指定した座標からの相対座標になってしまうので、pushMatrix() と popMatrix() で囲っておきましょう。
pushMatrix();
translate(x, y ,z);
ellipse(0, 0, size, size);
popMatrix();
あとは、せっかくの 3D なのでいろんな角度から見られるように全体を回転させてみましょう。
rotateX(radianX);
rotateY(radianY);
rotateZ(radianZ);
De Jong アトラクターをヒントに作る 3D アニメーション作例
それらを組み込んだ作例がこちらです。
// De Jong アトラクターの応用:Processing 3D アニメーション作例
// Processing 3.2.1
// 2018.06.03
// 15fps x 30s
void setup() {
size(720, 720, P3D);
colorMode(HSB, 360, 100, 100, 100);
blendMode(SCREEN);
smooth();
noStroke();
textSize(20);
}
void draw() {
// 立方体、収束、曲線のパターン。
float pA = 1.90 - frameCount / 4000.0;
float pB = 0.30 + frameCount / 500.0;
float pC = 1.90 - frameCount / 2000.0;
float pD = 0.30 + frameCount / 500.0;
float pE = 1.90 - frameCount / 1000.0;
float pF = 0.30 + frameCount / 500.0;
background(0, 0, 0, 100);
translate(width / 2, height / 2, 0);
// パラメータ値を表示
fill(0, 0, 100, 100);
text("pA=", 240, 200); text(pA, 280, 200);
text("pB=", 240, 220); text(pB, 280, 220);
text("pC=", 240, 240); text(pC, 280, 240);
text("pD=", 240, 260); text(pD, 280, 260);
text("pE=", 240, 280); text(pE, 280, 280);
text("pF=", 240, 300); text(pF, 280, 300);
// 座標系を回転
rotateX(-frameCount * PI * 0.002);
rotateY(frameCount * PI * 0.003);
rotateZ(frameCount * PI * 0.002);
float prevX = 0.0;
float prevY = 0.0;
float prevZ = 0.0;
for (int i = 0; i < 50000; ++i) {
// De Jong アトラクター 3D の(つもりの)計算式
float x = sin(pA * prevY) - cos(pB * prevX);
float y = sin(pC * prevZ) - cos(pD * prevY);
float z = sin(pE * prevX) - cos(pF * prevZ);
// 点を描画
pushMatrix();
translate(x * width / 7.0, y * height / 7.0, z * height / 7.0);
fill(240, 40, 60, 100);
ellipse(0, 0, 3, 3);
popMatrix();
prevX = x;
prevY = y;
prevZ = z;
}
// 15fps x 30s 枚の画像を書き出し。
// これを別途動画に変換する。
saveFrame("frames/####.png");
if (frameCount >= 15 * 30) {
exit();
}
}
/*
Copyright (C) 2018- deconbatch
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
※ライセンスを追記(2018/06/04)
ソースはご自由にお使いください。
ちょっとずつパラメータ値を変化させることで様々なパターンが現れます。
各パラメータは少しずつ一定の値で単純に変化させているだけなのですが、その結果描画されるパターンは全く予想できないような変化をしています。
本当に不思議です。
パラメータを変化させずに 3D 感を満喫できる例はこちら。
途中で暗い筋が入るところがありますが、これは点の描画に平面である ellipse() を使っているので、角度によって見えなくなるためです。
立体の球である sphere() を使えばこれを防ぐことができますが、描画に時間がかかるようになります。
3D 化にあたって勝手にひねり出した数式でちゃんと描画されるのか不安でしたが、なかなか良い感じに描画できたように思います。
2D で描画した図形が 3D に見えていたので、3D で描画したこの図は、きっと 4D に見えているのでしょう。
さあ、あなたもご自身の手で 4D を描いてみませんか?
読んでくださってありがとうございました。
ここでこの記事はおしまいです。もしこの記事がお気に召しましたら投げ銭お願いします。😉✨
ここから先は
¥ 100
この記事が面白かったらサポートしていただけませんか? ぜんざい好きな私に、ぜんざいをお腹いっぱい食べさせてほしい。あなたのことを想いながら食べるから、ぜんざいサポートお願いね 💕