> For the complete documentation index, see [llms.txt](https://masaki-yamabe.gitbook.io/dda2023-vie-visualization/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://masaki-yamabe.gitbook.io/dda2023-vie-visualization/3d-biao-xian.md).

# 3D表現

<figure><img src="/files/3qGhMyuwZLIraimyDGVh" 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="/files/xNita0JCBlUzPsJEE8Yg" %}

## 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 %}
