# 3D表現

<figure><img src="https://401456337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsuKkxdoQ8ipy9uxnNRNp%2Fuploads%2FccQl4hvxeqJcWCfSEEPB%2F3d.gif?alt=media&#x26;token=1e1a826b-558b-4501-a07a-0e6b2a2f16c9" alt=""><figcaption><p>実行画面</p></figcaption></figure>

## サンプルコード：

* 実行手順
  * **PeasyCamライブラリをインストール**
    * **\[スケッチ] > \[ライブラリインポート] > \[Manage Libraries]**&#x20;
    * **開いたウインドウで 「PeasyCam」を検索してinstall**
  * Vieを装着し、Vie StreamでVieに接続
  * 「計測開始(Activate Sensor)」ボタンを押す
  * 「OSC転送(OSC Streaming)」ボタンを押す
  * 「ポート番号」と「デバイス識別子」を確認。（通常はそれぞれ、65001、1）
  * コードの実行
  * キーボードの1\~0キーで表現を切り替える

{% file src="<https://401456337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsuKkxdoQ8ipy9uxnNRNp%2Fuploads%2FeHOPMSFF58HRQh6KusNB%2Fsample03_3D_BrainWave.zip?alt=media&token=6a8c933e-f626-42fc-a739-807da20cbd7e>" %}

## map()について

```processing
//deltaの値は最小0、最大100なので、これを0〜500にスケーリングする場合
float delta = 50;
float m = map(delta, 0, 100, 0, 500);
println(m);  // Prints "250"
```

## コード全体

{% code overflow="wrap" lineNumbers="true" %}

```processing
import peasy.*;
import oscP5.*;
import netP5.*;

//OSCP5クラスのインスタンス
OscP5 oscP5;

//PeasyCam
PeasyCam cam;

float [] waveLeft  = new float[5]; //左用
float [] waveRight = new float[5]; //右用
float [] waveMean = new float[5];  //左と右の平均

//脳波を一定数記録するバッファ
ArrayList<BrainWave> bwBuffer = new ArrayList<BrainWave>();

int bwBufferSize = 300;
int circleVerticiesNum = 6; //円環を何角形で描くか。ここでは6角形
float marginPerCycle = 5;   //一つのバッファを描くごとにz方向に何ピクセル移動するか
float distMax = 600.0;      //最も強い脳波を何ピクセルで表現するか
float distMin = 5.0;        //最も弱い脳波を何ピクセルで表現するか
float posX = 0.0,  posY = 0.0,  posZ = 0.0;
float posXp = 0.0, posYp = 0.0, posZp = 0.0;

int vizMode = 1;



void setup() {
  size(800,600,P3D);
  //ポートを65001に設定して新規にOSCP5のインスタンスを生成
  oscP5 = new OscP5(this,65001);
  //カメラの初期化
  cam = new PeasyCam(this, 700);
  
  //バッファを初期化する
  for(int i=0; i<bwBufferSize; i++){
    bwBuffer.add( new BrainWave() );
  }
  colorMode(HSB,255,255,255,255);
  blendMode(ADD);
}

void draw() {
  background(0);
  noStroke();
  
  //脳波をバッファに格納
  BrainWave bw = new BrainWave();
  bw.set(waveMean[0],waveMean[1], waveMean[2], waveMean[3], waveMean[4]);
  bwBuffer.add(bw);
  
  //バッファサイズが上限に達したら先頭を削除
  if(bwBuffer.size() > bwBufferSize){
    bwBuffer.remove(0);
  }
  
  //描画
  float anglePerBuffer = 2*PI / circleVerticiesNum;
  float distFromCenter = 0.0;
  

  pushMatrix();
  translate(0,0,-posZ - (0.5 * bwBufferSize * marginPerCycle));
  
  //線として描画
  if(vizMode ==0){
    beginShape();
    for(int i=0; i<bwBuffer.size(); i++){
      
      //バッファされたデルタ波の数値を中心からの距離に変換
      distFromCenter = map( bwBuffer.get(i).delta, 0, 100, distMin, distMax);
      
      //頂点の座標を計算
      posX = distFromCenter * cos( anglePerBuffer * i );
      posY = distFromCenter * sin( anglePerBuffer * i );
      posZ += marginPerCycle; 
      
      stroke(0,0,255,255);
      noFill();
      vertex(posX,posY,posZ);
      
    }
    endShape();
  }
  //面として描画
  else if(vizMode == 1){
    beginShape(TRIANGLES);
    for(int i=0; i<bwBuffer.size(); i++){
      
      //バッファされたデルタ波の数値を中心からの距離に変換
      distFromCenter = map( bwBuffer.get(i).delta, 0, 100, distMin, distMax);
      //バッファされたデルタ波の数値を色相と再度に変換
      float hue = map( bwBuffer.get(i).delta, 0, 100, 160, 255);
      float sat = map( bwBuffer.get(i).delta, 0, 100, 0, 255);
      
      //一つ前のバッファで計算した頂点座標を保存
      posXp = posX;
      posYp = posY;
      posZp = posZ;
      
      //頂点の座標を計算
      posX = distFromCenter * cos( anglePerBuffer * i );
      posY = distFromCenter * sin( anglePerBuffer * i );
      posZ += marginPerCycle; 
      
      //ポリゴンの3頂点を登録
      //頂点の色に色相と再度を反映
      fill(hue,0,255,10);
      stroke(hue,0,255,255);
      vertex(0,0,posZp);
      
      fill(hue,sat,255,10);
      stroke(hue,sat,255,255);
      vertex(posXp,posYp,posZp);
      
      fill(hue,sat,255,10);
      stroke(hue,sat,255,255);
      vertex(posX,posY,posZ);
    
      
    }
    endShape();
  }
  
  popMatrix();

}

//OSCメッセージを受信した際に実行するイベント
void oscEvent(OscMessage msg) {
  
  if(msg.checkAddrPattern("/wave/L/1")==true) {   
    for(int i=0;i<5;i++){
      waveLeft[i] = msg.get(i).floatValue();
      //左右の平均を取る
      calWaveMean(i);
    }    
  }
  if(msg.checkAddrPattern("/wave/R/1")==true) {   
    for(int i=0;i<5;i++){
      waveRight[i] = msg.get(i).floatValue();
      
      //左右の平均を取る
      calWaveMean(i);      
    }    
  }

}

void calWaveMean(int n){
  waveMean[n] = 0.5*(waveLeft[n] + waveRight[n]);
}


class BrainWave{
  
  public float delta;
  public float theta;
  public float alpha;
  public float beta;
  public float gamma;
  
  BrainWave(){
    this.delta =0.0;
    this.theta =0.0;
    this.alpha =0.0;
    this.beta =0.0;
    this.gamma =0.0;
  }
  
  void set(float d,float t,float a,float b,float g){
    this.delta =d;
    this.theta =t;
    this.alpha =a;
    this.beta =b;
    this.gamma =g;
  }
  
}

void keyPressed(){
  
  if(key == '0'){
    vizMode = 0;
  }
  if(key == '1'){
    vizMode = 1;
  }
  
  
}
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://masaki-yamabe.gitbook.io/dda2023-vie-visualization/3d-biao-xian.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
