###### tags:`Precessing` `2023寒假` `Beady` `找專研題目` `寫程式`
# 2023寒假_串珠Beady
[Beady: Interactive Beadwork Design and Construction](https://www.is.ocha.ac.jp/~yuki/beady/index-e.html?fbclid=IwAR2IUOgB1pi31MR6ELdc6QyLu-EWcxvQiPpRAnbF7hKQN4yN4xMqplPbdLc)
## processing 的基礎3D功能
### 角度、打光、移動、旋轉
<font color="#f00">P3D</font> 開啟processing的OpenGL 3D功能
<font color="#f00">box( )</font> 類似電腦圖學C語言中的 glutSolidCube()
座標原點在左上角
為了讓物體在畫面中心,需要將物體移到==translate(寬度/2,高度/2)==
==radians( )== 是換算 degrees度數 及 radians弧度
<font color="#f00">linghts( )</font> 打光
```p
void setup(){
size(300, 300, P3D);
}
void draw(){
lights();
background(#FFFFF2);
pushMatrix();
translate(150,150);
rotateY(-radians(mouseX));
rotateX(-radians(mouseX));
box(100);
popMatrix();
}
```

### 頂點、畫圖、球體
==beginShape()== 開始畫 // glBegin(POLYGON);
==endShape()== 結束畫 // glEnd();
==vertex()== 頂點 // glVertex2f(x,y);
```p
void setup(){
size(300, 300, P3D);
}
void draw(){
lights();
background(#FFFFF2);
pushMatrix();
translate(150,150);
rotateX(-radians(mouseY));
rotateY(-radians(mouseX));
myShape();//box(100);
popMatrix();
}
void myShape(){
beginShape(); // glBegin(POLYGON);
vertex(-50, -50); // glVertex2f(x,y);
vertex(-50, 50);
vertex(50, 50);
vertex(50, -50);
endShape(CLOSE); // glEnd();
}
```
四個頂點 >>矩形
三個頂點 >>三角形..

==sphere( )== 表面有線條的球
加上 ==noStroke( )== 不要線條
加上打光、移動至視窗中心
```size(300,300,P3D);
lights();
noStroke();
translate(150,150);
sphere(112);
```

## 模仿Beady(1)在box的邊上擺球
* 方塊、球不相關
把sphere( )、box( )放進來
```p=
void setup(){
size(300,300,P3D);
}
void draw(){
lights();
background(255,255,250);
pushMatrix();
translate(150,150);
rotateY(-radians(mouseX));
fill(255,228,97);
box(100);
popMatrix();
drawshape(0,0,0);
}
void drawshape(float x,float y, float z){
fill(#6AA5F5);
translate(x,y,z);
noStroke();
sphere(50);
}
```

為什麼這兩顆球會疊在一起啊?
:::danger
新手茫區 :dart: :

記得要在pushMatrix、popMatrix的組合裡。不然移動會疊加
:::
* 把球放在方塊的邊上
```processing=
void setup(){
size(300,300,P3D);
}
void draw(){
lights();
background(255,255,250);
pushMatrix();
translate(150,150);
rotateY(-radians(mouseX));
fill(255,228,97);
box(100);
drawshape(50,0,50);
drawshape(-50, 0, 50);
drawshape( 50, 0, -50);
drawshape(-50, 0, -50);
popMatrix();
}
void drawshape(float x,float y, float z){
pushMatrix();
fill(#6AA5F5);
translate(x,y,z);
noStroke();
sphere(50);
popMatrix();
}
```

processing裡的Z軸指向使用者

## 讀入OBJ檔、縮放
下載[beady_en.zip](https://www.is.ocha.ac.jp/~yuki/beady/beady_en.zip)解壓縮,找到模型檔以記事本打開
>>發現頂點的範圍介於-1~1之間
把penguin.obj檔丟進processing裡
==**PShape**== name ; 宣告
name = ==**loadShape**("name.obj")==; 讀檔
==**shape**( name );== 畫出模型
因為頂點太小>>要放大
<font color="#f00">scale( )</font> 縮放
### 轉動的企鵝
```p
PShape penguin;
void setup() {
size(500, 500, P3D);
penguin =loadShape("penguin.obj");
}
void draw() {
background(255, 255, 255);
lights();
translate(250, 250);
rotateZ(radians(161));
rotateX(radians(379));
println(mouseX);
rotateY(radians(mouseX));
scale(300);
shape(penguin);
}
```

### 用sphere( )秀出頂點

v(頂點) 點座標
f(面) int1 int2 int3...第幾個頂點
把第一個面的頂點秀出來>>>
f 2 3 8 12 17
* **<font color="#f00">陣列</font>** : 設***已知數量***的點座標
* 宣告
float [ ][ ]v =new float[5][3];
[5][3]因為f1有五個點、每個點有xyz值
直接給每個頂點的值,再把五個頂點讀入v裡
把penguin秀出來
mySphere()在(x,y,z)處畫出球體
用迴圈在5個頂點處 畫出球體
==frameCount==楨數(60Hz)
```p
void draw(){
background(#FFFFF2);
lights();
translate(250,250);
rotateY(radians(frameCount));
noStroke();
scale(300);
shape(penguin);
for(int i=0; i<5; i++){
mySphere( v[i][0], v[i][1], v[i][2]);
}
}
void mySphere(float x, float y, float z){
pushMatrix();
translate(x,y,z);
sphere(0.03);
popMatrix();
}
```
### 用線串珠_把球連起來
:::danger
**第i個點與下一個點連接**,避免超出範圍 迴圈的範圍要減一

**頭跟尾無法連接、少一條**

:::
```p
for(int i=0;i<5;i++){
stroke(255,0,0); //紅色的線
strokeWeight(0.01); //線的粗細
line(v[i][0],v[i][1],v[i][2],v[(i+1)%5][0],v[(i+1)%5][1],v[(i+1)%5][2]);
//第i個頂點x、y、z
}
```
**i=0~i < N
==(i+1)%N取餘數==**...
v[0]-v[1]
v[1]-v[2]
v[2]-v[3]
v[3]-v[4]
v[4]-v[0]
i的範圍:0 1 2 3 4
當i=4時 與第一個點(整除為0)相連

## 自動讀obj檔,根據頂點找到邊edge,把邊變成珠珠
### 讀入模型的所有頂點
* 宣告字串,把模型檔以字串讀入
**String[] lines= ==loadStrings==(file);**


* 把頂點v和面f 分開
**字串的第幾個**lines[i]==**.charAt()**==
```p=
void myLoadShape(String file){
String[] lines=loadStrings(file);
int V=0,F=0;// How much vertex
for(int i=0;i<lines.length;i++){
println(lines[i]);
char c=lines[i].charAt(0);
if(c=='v')V++;
if(c=='f')F++;
}
println("total vertex:"+V,"total face:"+F);
}
void setup(){
myLoadShape("penguin.obj");
}
```

* 把讀到的頂點由String變成PVector

1. 宣告陣列來放頂點PVector [ ]OBJv;
2. 決定陣列大小=V+1(因為模型檔f的頂點v是由1開始數的)
3. 用 ==**split()**== 以空白鍵**分割字串**後,放入新設定的字串nums裡
4. V=1,由第一個點開始把向量丟進去x,y,z
5. 每丟好一個後,V++
```p
OBJv=new PVector[V+1];//obj檔裡的f的頂點v是由1開始數,盒子的總數要加一
V=1;//obj檔裡的f的頂點v是由1開始數
for(int i=0;i<lines.length;i++){
char c=lines[i].charAt(0);
if(c=='v'){
String[]nums=split(lines[i]," ");//把lines[i]切成3個數字
OBJv[V]=new PVector(float(nums[1]),float(nums[2]),float(nums[3]));//第一個是v
println(OBJv[V]);
V++;
}
}
```
* 用頂點做出模型
**beginShape()**
vertex....
**endShape()**

```p
void draw(){
background(#FFFFF3);
scale(300);
lights();
beginShape();
for(int i=1;i<V;i++){
vertex(OBJv[i].x,OBJv[i].y,OBJv[i].z);
}
endShape();
}
```