質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

Q&A

解決済

1回答

5653閲覧

processing 泡の落下の再現をしたいです。

datuota00

総合スコア20

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

0グッド

1クリップ

投稿2017/08/19 15:44

課題

今、processing3の3Dマッピングを使って、水(?)の落下を再現したいと考えております。
まず2dでellipseを描写したところうまくいきました。以下コードです。

int numDrops = 4000; drop[] drops = new drop[numDrops]; float maxRad = 10; float gravity = 9.8/20; void setup(){ size(480, 720); background(255); smooth(); frameRate(15); for(int i = 0; i < numDrops; i++){ int c = color(0, random(200, 255), random(200, 255), random(100, 255)); drops[i] = new drop(random(200, width-200), random(0, height/4), random(2, maxRad), c, i); } } void draw(){ background(0); for(int j = 0; j < numDrops; j++){ drops[j].display(); drops[j].move(); drops[j].update(); } if(keyPressed){ if(key == 's'){ saveFrame("frames/frame_####.tif"); } } } class drop{ float posx, posy; float velx, vely; float rad; color clr; int idno; drop(float x, float y, float r, color c, int id){ posx = x; posy = y; velx = random(-4,4); vely = sqrt(2*gravity*posy); rad = r; clr = c; idno = id; } void display(){ fill(clr); noStroke(); ellipse(posx, posy, rad*2, rad*2); } void move(){ posx += velx; posy += vely; vely = sqrt(2*gravity*posy); } void update(){ if((posx >= width+rad) || (posy >= height+rad)){ color c = color(0, random(200, 255), random(200, 255), random(100, 255)); drops[idno] = new drop(random(200, width-200), random(0, height/4), random(2, maxRad), c, idno); } } }

これを本来の目的である三次元描写にしようとし、以下のコードに書き換えました。

int numDrops = 200; drop[] drops = new drop[numDrops]; float maxRad = 10; float gravity = 9.8/20; void setup(){ size(480, 720,P3D); background(0); smooth(); frameRate(15); for(int i = 0; i < numDrops; i++){ int c = color(0, random(200, 255), random(200, 255), random(100, 255)); drops[i] = new drop(random(200, 280), random(0, 150),random(200,240), random(2, maxRad), c, i); } noStroke(); } void draw(){ background(0); lights(); for(int j = 0; j < numDrops; j++){ drops[j].display(); drops[j].move(); drops[j].update(); } translate(240,360,-150); rotateX(map(mouseY, 0, height, PI, -PI)); rotateY(map(mouseX, 0, width, -PI, PI)); } class drop{ float posx, posy, posz; float velx, vely, velz; float rad; color clr; int idno; drop(float x, float y,float z, float r, color c, int id){ posx = x; posy = y; posz = z; velx = random(-4,4); vely = sqrt(2*gravity*posy); velz = random(-4,4); rad = r; clr = c; idno = id; } void display(){ fill(clr); noStroke(); translate(posx,posy,posx); sphere(rad*2); // ellipse(posx, posy, rad*2, rad*2); } void move(){ posx += velx; posy += vely; posz += velz; vely = sqrt(2*gravity*posy); } void update(){ if((posx >= 480+rad) || (posy >= 720+rad)){ color c = color(0, random(200, 255), random(200, 255), random(100, 255)); drops[idno] = new drop(random(200, 240), random(0, 150),random(200, 240), random(2, maxRad), c, idno); } } }

このコードで実行してみても動きませんでした。。。
考え方的にはあっていると思っているので私ではどうにもできそうにないです。わかる方いらしゃったらご教授ねがいます。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

pushMatrix()とpopMatrix()を使い
修正したコードを以下に書きます

Processing

1省略 2 3void setup(){ 4 省略 5} 6void draw(){ 7 background(0); 8 lights(); 9 10 pushMatrix();//追加 11 translate(240,360,-150);//for文の前に移動 12 rotateX(map(mouseY, 0, height, PI, -PI));//for文の前に移動 13 rotateY(map(mouseX, 0, width, -PI, PI));//for文の前に移動 14 for(int j = 0; j < numDrops; j++){ 15 drops[j].display(); 16 drops[j].move(); 17 drops[j].update(); 18 } 19 popMatrix();//追加 20} 21 22class drop{ 23 省略 24 void display(){ 25 fill(clr); 26 noStroke(); 27 pushMatrix();//追加 28 translate(posx,posy,posz);//一部変更 29 sphere(rad*2); 30 popMatrix();//追加 31 } 32 省略 33}

以下解説です

例えば

Processing

1translate(100,0,0); 2sphere(50); 3translate(100,0,0); 4box(80);

と書くと球と立方体はどのように描画されるでしょうか?
重なるでしょうか?
それとも並ぶでしょうか?

答えは並びます

それはtranslate()やrotateX()が
描画する立体の「座標」ではなく
描画される「空間」を変形するメソッドだからです

呼び出せば呼び出すほど空間は変形していきます
あなたのコードではこれが起こっています

重ねて書くためには

Processing

1translate( 100,0,0);//空間がx方向に100移動した状態に 2sphere(50); 3translate(-100,0,0);//空間がx方向に100移動した状態から-100移動した状態(=最初の状態) 4translate( 100,0,0);//空間がx方向に100移動した状態 5box(80);

と書かなくてはなりません
これは面倒です

それを解決するのが
pushMatrix()とpopMatrix()で囲み
同じ空間の状態で描画する方法です

ちょっと込み入った話をすると
実は3次元空間の状態は
マトリックスと呼ばれる16個の値(4×4の行列)に格納されていて
変形するメソッドはマトリックスを書き換えます
sphere()などの描画メソッドは
そのマトリックス(=空間の状態)に基づいて
座標を変形して描画を行います

translate()やrotateX()などのメソッドを使う場合
pushMatrix()とpopMatrix()で囲うことで
これらのマトリックス(=空間の状態)を
保存したり削除したりでき
またこれを入れ子状にすることもできます

Processing

1pushMatrix(); //今の空間の状態Aを保存 2translate(100,0,0);//空間の状態A→状態B 3sphere(50); //空間の状態Bで描画 4popMatrix(); //空間の状態Bが削除→保存しておいた状態Aに 5 6pushMatrix(); //今の空間の状態Aを保存 7translate(100,0,0);//空間の状態A→状態B 8box(80); //空間の状態Bで描画 9popMatrix(); //空間の状態Bが削除→保存しておいた状態Aに

このように書けば
球も箱も空間の状態Bの時に描画されることになります
また次に変形メソッドやpushMatrix();を使う時に
状態Aであることが保証されます

下にもう少し複雑な入れ子の例を書いておきますが
やりたいことは全く同じです

Processing

1pushMatrix();//今の空間の状態Oを保存 2translate(0,100,0);//空間の状態O→状態A 3 4pushMatrix(); //今の空間の状態Aを保存 5translate(100,0,0);//空間の状態A→状態B 6sphere(50); //空間の状態Bで描画 7popMatrix(); //空間の状態Bが削除→保存しておいた状態Aに 8 9pushMatrix(); //今の空間の状態Aを保存 10translate(100,0,0);//空間の状態A→状態B 11box(80); //空間の状態Bで描画 12popMatrix(); //空間の状態Bが削除→保存しておいた状態Aに 13 14popMatrix();//空間の状態Aが削除され保存しておいた状態Oに戻る

最後のpopMatrix()で保存しておいた状態Oに戻るのは
空間の状態がスタックの形で複数保存されるからです

Processingでは32個まで空間の状態を保存することができるようです
つまりpopMatrix()をはさまずに
pushMatrix()を連続32回までなら使えるということです

修正したコードは連続2回しか使っていないのでまったく問題ありません

投稿2017/09/26 18:16

編集2017/09/28 00:26
e-cube

総合スコア284

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問