33448


言葉でうまく表現できないのですが、下の画像を見ていただいてイメージが伝わると幸いです。  
３D空間状に画像のようなトゲを持った球体を描いているのですが、それぞれのトゲは球体の動きの影響を受けるようになっています。  
[![画像の説明をここに入力](https://i.stack.imgur.com/TVF0K.gif)](https://i.stack.imgur.com/TVF0K.gif)

ただしこのようトゲが全て一定の方向を向いているのではなく、それぞれのトゲの向きが全方向を向くようにしたいと思っています。その上で球体が動いた時に上の画像のような影響を受けるという風にしたいです。

[code]

    for (int i=0; i<num; i++) {
      if (i==0) {
        x[i]=_x;
        y[i]=_y;
        z[i]=_z;
      } else {
        x[i]=x[i]+(x[i-1]-x[i])*speed;
        y[i]=y[i]+(y[i-1]-y[i])*speed;
        z[i]=z[i]+(z[i-1]-z[i])*speed+2;
      }
    
      en_size = (num-i)*1.2;
    
      translate(x[i], y[i], z[i]);
      rotateZ(kakudo);
      rotateY(kakudo2);
      ellipse(0, 0, en_size, en_size);
      rotateY(-kakudo2);
      rotateZ(-kakudo);
      translate(-(x[i]), -(y[i]), -(z[i]));
    
    }
    
[/code]

トゲ一つ一つは上記のようなコードになっており、一つのクラスとしてまとめています。トゲは円の重なりでできており、numがトゲを構成している円の数です。それぞれの円は球体の表面上の傾斜に合わせてkakudoとkakudo2を使って回転できているのですが、トゲ自体は回転できていません。（トゲ自体の回転とは、それぞれの円の傾斜に対して垂直の方向に円を重ねたいというイメージです。）  
z座標に2を足しているのは、円錐形の形を維持するためです。

試しにこのクラスを丸ごと回転するようにrotateを使ってみたのですがうまくできませんでした。  
色々と考えて試してみたのですが、なかなかうまくできなかったので、質問させていただきました。お力添えいただけたら幸いです。

初心者のため、わかりづらい文章とコードかと思います。申し訳ありません。必要な補足等あれば随時直しますのでよろしくお願いいたします。


CC BY-SA 3.0
2017-03-21T13:47:53.910
33445
2017-03-22T04:55:55.310
2017-03-21T14:59:17.283
21145
21145
question
java processing
任意の方向性と長さを持たせながら、動きの影響を受ける物体の書き方


> トゲ一つ一つは上記のようなコードになっており、一つのクラスとしてまとめています。...

まずコードがクラスやメソッドになっていませんが、クラスはどんな設計でしょうか？  
次の解釈で合っていますでしょうか？ そうである前提で進めます。

  * このfor文全体は1つのトゲを構成する円集合の描画処理である
  * `x` `y` `z` 配列要素は円の絶対座標を示すクラスのフィールドであり、前回の描画時の座標が記憶されている
  * `_x` `_y` `_z` はトゲの原点の絶対座標を示すクラスのフィールドである
  * `kakudo` `kakudo2` は球を基準としたトゲの[球面座標系](https://ja.wikipedia.org/wiki/%E7%90%83%E9%9D%A2%E5%BA%A7%E6%A8%99%E7%B3%BB)の角度を示すクラスのフィールドである

* * *

まずfor文末の3行は非効率かつ分かりづらいので行列スタックを使ってください。  
行列スタックとは回転や平行移動等の操作を保存したり戻したりできる機能のことです。  
[`pushMatrix()`](https://processing.org/reference/pushMatrix_.html)と[`popMatrix()`](https://processing.org/reference/popMatrix_.html)を使います。

次に目的ですが、トゲの各円を放射的（球面の法線方向）に並べたいという解釈でよいでしょうか。  
そうであれば、あなたが示した絶対座標系のZ軸ではなく、rotateされた後のローカル座標系に対してZ軸を操作することで達成できます。

[code]

    for (int i=0; i<num; i++) {
      if (i==0) {
        x[i] = _x;
        y[i] = _y;
        z[i] = _z;
      } else {
        x[i] = x[i] + (x[i-1]-x[i])*speed;
        y[i] = y[i] + (y[i-1]-y[i])*speed;
        z[i] = z[i] + (z[i-1]-z[i])*speed; //←ココは絶対座標なので何もしない
      }
    
      en_size = (num-i)*1.2;
    
      pushMatrix();
        translate(x[i], y[i], z[i]);
        rotateZ(kakudo);
        rotateY(kakudo2);
        translate(0, 0, 2*i); //←ココ （kakudoの計算方法によっては-2*i）
        ellipse(0, 0, en_size, en_size);
      popMatrix();
    }
    
[/code]

このローカル座標系は本来であれば円錐（トゲ）の座標系（最初のtranslateが円錐の原点）である必要があります。しかし、上記のように円の座標系であっても円錐を構成する円の向きがそれぞれ同じであれば問題ありません。ここでは`kakudo`と`kakudo2`が個々の円で同値なので問題ないわけです。

> 試しにこのクラスを丸ごと回転するようにrotateを使ってみたのですがうまくできませんでした。

その手法であってもできると思います。できなかったのは座標が全て絶対座標だったからだと思われます。それらを球からの相対座標に変えて、トゲ（クラス）を丸ごと回転するだけでなく球からの並行移動もすれば上記と似た結果が導けるはずです。  
ただし、トゲの先が遅れて動くような実装は絶対座標に基づく為、座標系の変換が必要になります。ややこしいので先に説明した方法をお勧めします。

* * *

補足ですが、`rotate`や`translate`、`scale`、`popMatrix`などの変換操作の振る舞いですが、これは「座標系」を変えるメソッドです。円や球などを動かすメソッド、と考えると不正確なので注意しましょう。  
詳しくは「Processing pushMatrix rotate」で調べてください。


CC BY-SA 3.0
2017-03-22T03:16:51.507
33448
2017-03-22T04:55:55.310
2017-03-22T04:55:55.310
19925
19925
33445
answer