2011/07/30



只能說很多時候設計要賣得出去還是得靠好口才,
你不能期待一天到晚設計會自己說話.

2011/07/29

我都會隨時新增自己滿喜歡的網站,
不一定都是數位相關,不定時看他們在幹麻也很不錯噢!
把CCC的經典名句組成一個combo,



"如果真的不濟,至少看過豬走路."


看看厲害的人在幹麻,至少眼界比較開,
同時沒做東西時,至少可以跟老師說我看了很多參考價值極高的網站,
跟老闆說一樣的話有沒有用我就不知道了.

 
:)

簡單講一下好了,

Alex Hogrefe /
一個PS很強的人,感覺也是skp為主,rhino為輔.

Blogger Kuo /
同學郭偉廷的blog

Blogger MadeinCA /
一個寫script跟玩GH為主的blog,作者同時也是Zaha Hadid的員工

Blogger P&A Lab /
學長Gary的熊貓建築

Blogger S.Yuan /
學長識源的blog

Blogger SpringfieldPunx /
這個人專門畫一些我最喜歡的辛普森

co-de-it /
MadeinCA Blog作者的網站

Complexification /
一個用大量flash,少數Processing的數位藝術家

EMAG Likecool /
介紹有趣設計的網站

Flickr F.Franchi /
我很喜歡的一個主編,排版比例拿捏很強,以拉也很強

Paul Lukez Architecture /
Alex Hogrefe現在加入的公司,你可以看到裡面作品滿多是skp建的,
其實skp的plugin玩很兇也是可以看起來很猛的.

Vimeo Casey Reas /
發明Processing的作者之一,它的vlog

Vimeo PHOS /
2010年Vimeo最佳影片得者的vlog

Vimeo UrbanScreen /
專門po一些大尺度的牆面動畫作品

Visual Complexity /
以前去Berkeley唸書時老師介紹的diagram網站,
看看人家diagram在幹麻就不會一天到晚在做風,光,動線的diagram

Youtube Traphik /
美國的一個藝人,很白癡我喜歡,我常update他的作品跟他的vlog channel 




每天光看別人的作品就飽了,雖然一直被開導不要在乎別人多厲害,
但真的很難啊,自己不管是眼界還是心境都還是太淺了.

就連離computer geek都還差遠了,永遠不滿足,我是熟女嗎?
Casey Reas is a professor in the department of Design Media Arts at UCLA, 
and the co-founder of Processing with Ben Fry.

男怕入錯行,女怕嫁錯郎(錯嫁狼?),
千金難買早知道,何況我沒有千金(娶千金?).

2011/07/26

論文在暑假仍在探討的階段,你永遠不知道一開始想的跟最後結果是否相同,
以老師的經驗通常都是不一樣的,有時候喜歡的題目做不下去,本來覺得還好的卻做的異常起勁.

自從學了processing以後,對隨機有更深刻的依賴,因為它某種程度上會超出你的預期,
這不可預測的生成模式的而且確地對凡事追求邏輯推理的我們造成一定程度上的衝擊.
不過如果單純討論隨機的話,那可能就無法進行下去了,畢竟如果沒有一定的範疇,
那在論述隨機時只會淪為空談.

首先先從維基百科內對隨機的定義進行了解.

隨機這個詞是用來表達目的、動機、規則或一些非科學用法的可預測性的缺失。
一個
隨機的過程是一個不定因子不斷產生的重複過程,但它遵循一個機率分布。
術語隨機經常用於統計學中,表示一些定義清晰的、徹底的統計學屬性,例如缺失偏差或者相關。
隨機與任意不同,因為「一個變數是隨機的」表示這個變數遵循機率分布。
而任意在另一方面又暗示了變數沒有遵循可限定機率分布。


這很重要的指出兩點,一是隨機其實並不是沒有範疇的,二是它其實只是一種機率的變形.
所以儘管我們在看某些隨機生成的作品時,它其實還是有規則可循的.
也就是說,隨機是在一定的規範體系下所保持的一些彈性變化,也正是我喜歡它的地方.

而在processing裡面,隨機甚至有了尺度跟向度上的差別,
例如 Random Noise 便是不同的隨機指令.
如果隨著尺度不同,其實隨機所帶來的印象也會有極大差異,
左右兩張圖其實都是隨機旋轉方體角度,但因尺度的不同,右圖似乎沒變化.




所以如果套用到建築領域上時,便可以探討在這凡事講求秩序的年代,
我們是否可以透過較細微的隨機手法達到城市裡更多變的可能,
整體看似一樣,但其實魔鬼(變化)藏在細節裡.
這之後可能就會探討noise,因為它基本上即是一範圍極小的隨機作用.


End.



從確立要設計一組板凳而開始發想,
不斷地從迪化街中抽絲剝繭出其精神元素,
而其中最令人印象深刻的便是那一袋袋裝著南北乾貨的袋子.


在乾貨不同的質量體積下,擠壓出袋子外惻不同的曲線,
這些曲線遂成為一個非常好的出發點,進而產生出板凳的設計.






首先透過3D軟體的voronoi功能,可以將一平面製造出不均質的分割,
再把分割面的邊線進行更多邊的切分進而柔化出八塊大小不一的面,
因此生成的圖形就彷彿從上往下看裝著不同乾貨的袋子俯視圖.






再來為了達到像袋子側面一般長短不一的曲線,進而形構出一外形扭曲的袋子.
因此在垂直向度上複製了10次先前生成的面,並對每個面做不同比例的調整.






最後透過3D軟體的loft功能將所有面進形接合,便可以形塑出板凳的雛型.
透過不停的轉化,最後形成的板凳便是隱諱地向迪化街致意.




                                                                                                                        End.

2011/07/25

Recursion (processing教學)

各位好久不見,著實過了好一陣子沒有更新processing的介紹了.
沒辦法,我只要一找到機會可以打懶可是從來都不客氣的,
所以最近都很心安理得的告訴自己因為要弄迪化街的東西,
沒有做processing介紹也是情非得已啦.

不過好景不常,昨天上課就被道德勸說是不是該繼續processing的研究了?
套用我爸的名句"伸頭是一刀,縮頭也是一刀",不如就乖乖繼續吧. :)

------------------------------------------------------------------------------------------------------------------

除了後來才補講的noise之外,
我們的課本進度已經來到如何以void來做2D的GIF動畫了.

http://tesignstudio.blogspot.com/2011/07/blog-post_917.html

而那一篇能含蓋的內容我覺得一該從p173-200應該看一看都會懂,
所以我就不多說了,不過還是自己做過一遍比較穩當囉.
唯一額外需要講的我覺得是p201-205的小單元, Recursion

Recursion顧名思義就是遞迴,循環.
因此我們可以簡單推測如果在使用這方法時,
沒有告訴電腦什麼時候停(一個終點)的話,那它就會一直算到電腦燒起來為止.
以下就先來一盤小菜讓大家簡單了解,p201的22-07.


 void setup(){
  size(200,200);
  background(255);
  smooth();

  noLoop();
}


int a = 10; //a對應的是x
int b = 18; //b對應的是num


void draw(){
  frameRate(10);
  drawLines(a,b);
  //saveFrame("p201-##.jpg");
}


void drawLines(int x, int num){
  strokeWeight(x/30);
  line(x,20,x,180);

  if(num > 0){
    drawLines(x+10,num-1);
  }
}




最重要的部分就是 
  if(num > 0){
    drawLines(x+10,num-1);
  }
我們可以看到在drawLines這集合裡又跑了drawLines,

這意味著drawLines會先把自己內裡的drawLines都跑完,
之後才會再丟給上面的void draw去畫出來.(很饒舌我知道.)

所以到底它是怎麼跑的呢? 
首先我們知道b = num = 18,
因此一開始跑就會符合if(num > 0)
因為每畫一次就會drawLines(x+10,num-1);
到減第18次時num都還會大於1,
同時還要加最原本的那條,所以線會依序畫19條,
至於x方面因為drawLines(x+10,num-1);因而為呈現為
                line(  x  ,  20  ,  x  ,  180  );
第00代            10            10

第01代            20            20
第02代            30            30
第03代            40            40
                          .               .
                          .               .
                          .               .
第17代          180           180
第18代          190           190

所以我們知道recursion其實是在還未丟入void draw的集合內進行其內部的自行運算.
再來進階一點的是p203的22-10,以下


void setup(){
  size(200,200);
  background(255);
  noStroke();
  smooth();
  noLoop();
}


int xx = 100;
int r = 85;
int n = 4;


void draw(){
  drawCircles(xx,r,n); 
  //saveFrame("p203-##.jpg"); 
}


void drawCircles(int x, int radius, int num){
  float tt = 200 * num/4;
  fill(tt);
  ellipse(x,100,radius*2,radius*2);
 
  if(num > 1){
    num -= 1;
    drawCircles(x - radius/2, radius/2, num);
    drawCircles(x + radius/2, radius/2, num);
  }
}


在這部分最重要的是
  if(num > 1){
    num -= 1;
    drawCircles(x - radius/2, radius/2, num);
    drawCircles(x + radius/2, radius/2, num);
  }
除了num的處理跟上面一個案例一樣之外,

我們可以看到在畫完第一個中心為(100,100)的大圓之後,
隨著recursion每次會畫兩個圓,其直徑為之前圓的一半,
同時其兩個圓的圓心會一往左一往右順x軸偏移,
移動大小為之前圓直徑的1/4.
所以最後我們可以看到因為總共算了4次,
除了原本大圓之外還分裂了3次,所以可以看到
1 + 2 + 4 + 8 = 15個大小不一的圓.


所以最後的終極魔王就是p204的22-11,
它不但用if的recursion,同時還在if中加了for,以下.


void setup(){
  size(200,200);
  background(255);
  noStroke();
  smooth();
}


int x = 100;
int y = 100;
int r = 50;
int n = 5;


void draw(){
  frameRate(10);
  drawCircle(x,y,r,n);
 
  //if(frameCount < 200){
  //  saveFrame("p204-###.jpg");
  //} 
}


void drawCircle(float x, float y, int radius, int num){
  float value = 126 * num / 6;
  fill(value,153);
  ellipse(x,y,radius*2,radius*2);
 
  if(num > 1){
    num = num - 1;  // num的多少決定會算幾次
    int branches = int (random(2,6)); //這更可怕,branch的多少決定它之後衍生的數量
    for(int i = 0; i < branches; i += 1){
      float a = random(0,TWO_PI);
      float newx = x + cos(a) * 6 * num;  //每次新的圓心x點會偏移
      float newy = y + sin(a) * 6 * num;  //每次新的圓心y點會偏移
      drawCircle(newx,newy,radius/2,num);
    }
  }
}

如果還看不懂,嘗試把int n改小,而int branches也改成不要random,
同時在setup裡加上noLoop,好好看一張圖是怎麼運算的,可以幫助你理解.
所以只要稍做調整,我們也可以很輕易的做出類似潑油漆的畫作.



void setup(){
  size(200,200);
  background(255);
  noStroke();
  smooth();
}


int x = 100;
int y = 100;
int r = 50;
int n = 8;
int c = 0;


void draw(){
  frameRate(100);
 
  c += 1;
  if(c>2){
    background(255);
    c = 0;
  }

  drawCircle(x,y,r,n);
 
  //if(frameCount < 200){
  //  saveFrame("p204-2-###.jpg");
  //} 
}


void drawCircle(float x, float y, int radius, int num){
  float value = 126 * num / 6;
  fill(value,random(255),random(255),50);
  ellipse(x,y,radius*2,radius*2);
 
  if(num > 1){
    num = num - 1;
    int branches = int (random(2,6));
    for(int i = 0; i < branches; i += 1){
      float a = random(0,TWO_PI);
      float newx = x + cos(a) * 6 * num;
      float newy = y + sin(a) * 6 * num;
      drawCircle(newx,newy,radius/2,num);
    }
  }
}


Try it. :)
如果真的問我是在怕什麼,
我怕的是時間,我總是會逼自己很快並有效率的做完事,
只為了讓我其餘時間能回到我緩慢而懶惰的節奏,
因為做事時不是自己所期望的節奏,所以有時候會滿不開心的,



要是不會死就好了.

2011/07/23

把樹枝貼到面上去做插集,
所以pattern可以較晚整的呈現,大概會長這樣.


進度update.

單純嵌入pattern /














解構,無法做一張椅變兩張,一定有一組要多切奇數片 /


紋路,放樣時有困難,只能在組時憑眼睛去抓位置 /


切完時大概的木板狀況,桌子雛形 /


剩餘廢材裝成天花示意圖 /



End.

2011/07/20


挖空與外皮的pattern還沒想要怎麼生成,
可能太複雜會太細,不但切很久效果不好還容易斷,
不過基本上問題應該不大.
今天討論完先簡單的把大概會怎麼組起來的圖跟構件畫出來.





跟今天下午討論的一樣,下面幾塊的壓克力是切斷的,
最上面一層跟屁股會有親密接觸的則是單純去把切割線洗出來不切斷.
現在是一片之後每隔四片再放一片.





為了避面到時組裝放樣不好對,所以在較寬的部份以兩根6mm的圓木條貫穿整個體,
這樣到時每一片應該都會較精準的被組裝.






一張小單元大概就是這些構件.





整個高約46cm, 以兩條6mm木條來固定每片位置,
基本上板與板大概是抹白膠固定,





但以發現一問題是因為是採9mm厚的密集板,
所以當放如2mm厚的壓克力板在凹槽時會有高低落差,
尤其是最上面那片屁股一下去應該會裂掉,
一是疊多片, 二是最上面一片單獨為一有切pattern的密集板.

今天先到這裡.

2011/07/19


透過skp + rhino的搭配運用,做出一個椅子的原型.
voronoi, smooth, slice,等等什麼招都搭一搭做出來,
希望椅子不要太一體,這樣展完才有機會帶回家. :3


首先先去放樣一個比60x60方形稍大的voronoi, 用的是skp外掛的Qhull.



再來用skp外掛的subdivide and smooth來把邊邊角角修成圓滑的線.




之後把做好的面往上複製到40cm處(一個座椅較舒服的高度),
中間除以10個間隔好去做loft的塑形.
每一個垂直向度的板則做介於0.5至1的隨機比例縮放(沒辦法,我中random毒太深),
用的則是skp外掛的scale and rotate multiple




透過skp外掛的curviloft,可以很細緻的把每條不同比例的曲線loft起來,
所以整體會像相似但不同的手拉坏.




最後因為形實在太曲太多面無法在skp裡順利intersect,
所以丟到rhino裡切片之後再丟回來,
然後每一片offset之後就會變空心的椅子,同時也能減輕重量.
因為是分散的,所以可以應現場佈展需要來做應用(其實是為了方便帶回家),
而挖出來的板材則打算拿來做更矮的板凳或是CD架,拿去現場廉價出售,多少補貼一點材料費.

整張椅子就是透過一堆0.5的密集板堆疊而成,
至於中間的洞可能會在最上層再蓋上一塊切分更細的板來避免有人一做屁股就陷下去拔不出來.


It's just a rough prototype design, so feel free to give some opinion. :3

2011/07/17

Greg Lynn FORM Toy Furniture /
Lynn uses the same method of algorithmic design that punctuates
all of his work to piece recycled toys together into works of art.


http://www.glform.com/toyfurniture.html 
http://www.youtube.com/watch?v=tDbr4WYgP3o





ETHZ MAS CAAD 2009/2010 - Voxopolis /
3D city engine based on Conway's Game of Life and developed in Processing.



http://www.youtube.com/watch?v=zmSqwxpte9g&NR=1 
http://www.flickr.com/photos/mas0910/4329438061/in/photostream






NOIZ Architects - Morphing Furniture /
The morphing table and chairs are derived from iconic pieces of modern designed furniture.
The forms morph from one typology of a chair or table into another in one continuous form.


http://noizarchitects.com/top/
http://noizarchitects.com/projects/morphing-furniure/
中文論文名稱  拼裝建築
英文論文名稱  Architecture of Patched
研究生中文姓名 高紹軒


/

中文論文名稱  數位模擬自然紋理於建築設計的過程
英文論文名稱  Encoding Natural Patterns into Architecture
研究生中文姓名 江青澤


/

中文論文名稱  數位生活與藝術之空間研究
英文論文名稱  Applying Digital Arts and Media into Digital Livings
研究生中文姓名 黃亦

2011/07/15

Noise (processing教學)

之前跳過沒講的p130-132的noise在好好看完CCC提供的資料後(謝謝老師),
總算從從完全不懂到似懂非懂了 ....................
其實有時候指令就是這樣子,你知道它在幹麻,但你不知道它為什麼這樣,
就跟劉子千的唸你MV一樣,你知道他在拍MV,但不知道它為什麼拍成這樣.


以下我會對noise做簡單的註解,也不能說一定對,只能說是我的推論,
至於說可以拿來幹麻,我還真不知道.


----------------------------------------------------------------------------------------------------------------------------




processing的noise指令原理是來自Perlin noise,是由一個叫做Ken Perlin的人所提出的,
也就是上圖右邊那位跟吳老合照的人兄,你不要看他貌似瘋瘋癲癲,
他除了獲獎無數外,還用他的noise參與了第一代Tron的製作.


noise基本上可以說是一種演算法,噪聲演算法.
而它所產生的基本圖形就像以前偷偷轉到鎖碼頻道一樣,
結果電視不但一直沙沙沙的鬼叫外,還會產生一堆黑芝麻的畫面如圖,令人不勝唏噓.
因為再介紹下去就太數學性,我會想嘔吐,
所以有興趣知道的朋友可以參考以下的網站多加了解. 


http://zh.wikipedia.org/wiki/Perlin%E5%99%AA%E5%A3%B0


----------------------------------------------------------------------------------------------------------------------------


透過CCC提供的線索下(黃金傳奇?),
我找到了一個我覺得在說noise上較課本清楚的網站,
是由一個叫Anthony Mattox的數位藝術家的blog
http://anthonymattox.com/perlin-noise


在交互參考課本與網站之後,
我理解上是說noise基本上是random的一種,
但相較於random, noise還帶有方向性, 很詭異吧?
這也是為什麼p130的noise有(x,y,z),
同時noise的數值永遠應介於0到1之間的,
所以他就像sin,cos一般,當我們使用它時,
通常都還會給他乘以更大的數來做rescale的效果.


以下我會針對p131的15-09來講三個例子,
因為15-08太簡單自己看就可以,15-10又太難非我族類 .............


----------------------------------------------------------------------------------------------------------------------------

這是課本的範例




size(200,200);
background(255);
smooth();


float xnoise = 0; 
float ynoise = 0;
//因為是做2D圖面,所以只需noise(x,y),
//同時我們知道noise是random的一種,所以性質為float
float inc = 0.04;
//這行只是讓作者方便一次改 += 多少

noiseSeed(0); 
//跟random有randomSeed一樣,
//noise也有noiseSeed,但如果在跑動畫時是不能寫這行的.

for(int y = 0; y <= height; y += 1){
  for(int x = 0; x <= width; x += 1){
    xnoise += inc; //本來是xnoise = xnoise + inc;
    float k = noise(xnoise,ynoise) * 255; //因為k是要拿來當顏色的值,所以要再乘以255
    stroke(k); //單純的灰階
    point(x,y);
  }

  xnoise = 0;
  ynoise += inc; //本來是ynoise = ynoise + inc;
}

//saveFrame("p131-2-##.jpg");


這範例比較麻煩的是你會看到
xnoise = 0;
ynoise += inc;
出現在外層的for loop.
因為noise本身也有向度性,所以就像我們之前做一整片方塊排列一樣,
xnoise(x向度)要先算,之後再算ynoise(y向度).

因為一開始已設
float xnoise = 0; 
float ynoise = 0;
所以在先算x的for loop時,
ynosie會永遠為0,但因為xnoise有寫xnoise += inc;
所以會先算好x軸的noise,(也就是一排點構成的)
但當要算外圈y的for loop時,
如果xnoise同時在變,那效果就是那條一路順y軸重覆
這也就是為什麼除了設ynoise += inc;之外還要設xnoise = 0;
可能有點難理解,但只要移動看看ynoise += inc;的位置或//它你可能比較好懂





所以我們如果要改寫成一個超短比較好理解的noise程式的話,
以下是個好範例


size(200,200);
background(255);
smooth();
noiseDetail(22,0.6); //這是一個課本沒有但官網有的指令,下面會詳加介紹
noiseSeed(17);

for(float y = 0; y <= height; y += 1){
  for(float x = 0; x <= width; x += 1){
    float k = noise(x/200,y/200) * 255;
    //單純取消掉xnoise跟ynoise,讓x,y直接代替,就無需煩惱雙層for loop的問題
    stroke(k);
    point(x,y);
  }
}

//saveFrame("p131-3-##.jpg");



noiseDetail(octaves, falloff)這指令是控制我們所設的noise密度跟均勻度.
官網的介紹如下


Adjusts the character and level of detail produced by the Perlin noise function.
它是用來調整noise的性質和細節的功能

Similar to harmonics in physics, noise is computed over several octaves.
有點類似於物理學中的和聲學(蝦米?),而noise即是由幾個八度音來產生的

Lower octaves contribute more to the output signal and as such define the overal intensity of the noise,
whereas higher octaves create finer grained details in the noise sequence.
較低的八度音控制nosie整體的粒子強度,而高八度音則加強noise的細膩度

By default, noise is computed over 4 octaves with each octave contributing exactly half than its predecessor,
starting at 50% strength for the 1st octave.
在processing的預設裡,noise是由4個八度音所組成的,
而每個八度音為前一次強度的50%(預設的,可更改)

This falloff amount can be changed by adding an additional function parameter.
也就是每下一次八度音的衰弱率可被設置,不一定為預設的50%
Eg. falloff factor of 0.75 means each octave will now have 75% impact (25% less) of the previous lower octave.
例如衰減係數為0.75意味著每個八度音將有前一次八度音75%的強度 

Any value between 0.0 and 1.0 is valid,
however note that values greater than 0.5 might result in greater than 1.0 values returned by noise().
任何衰減係數介於0.0至1.0之間是有效的,但是請注意,
值大於0.5,可能會導致返回值大於1.0的noise
(這裡我不懂,請自己參悟,或是就不要設超過0.5,但我範例設0.6也沒事)

也就是說noise裡的兩個數,第一個是有幾個八度音,第二個是每下一個八度音會衰減多少.
透過這功能我們可以控制noise的細節跟強度來達到我們的需求.



最後一個案例就是把noise直接變成void draw的動畫,基本架構其實沒什麼差別.


void setup() {
  size(200,200);
  noiseDetail(8,0.4);
}

float age = 0;
void draw() {
 
  frameRate(50);
  background(255);
  age += 0.02;
 
  for (float x=0; x<=width; x++) {
    for (float y=0; y<=height; y++) {
      stroke(noise(x/200,y/200,age)*255);
      point(x,y);
    }
  }
 
  //if(frameCount < 201){
  //  saveFrame("p131-4-###.jpg");
  //} 
}

noise基本上就是random的一種,就像sin與cos一樣也可以是一種-1至1的數,
都是用來改變向量或正負的,應該是這樣子吧吧吧吧吧?
所以簡單應用一下我們也可以偵測敵軍   ..............



void setup() {
  size(200,200);
  noiseDetail(6,0.4);
  smooth();
}

float age = 0;
float a = 0;

void draw() {
 
  frameRate(50);
 
  age += 0.02;
  a += 10;
 
  for (float x=0; x<=width; x++) {
    for (float y=0; y<=height; y++) {
      stroke(noise(x/200,y/200,age)*255);
      point(x,y);
    }
  }
 
  stroke(255,150);
  strokeWeight(1.5);
  noFill();
  ellipse(100,100,160,160);
  ellipse(100,100,120,120);
  ellipse(100,100,80,80);
  ellipse(100,100,40,40);
 
  pushMatrix();
  translate(100,100);
  rotate(radians(a));
  line(0,0,170,170);
  line(0,0,170,0);
  popMatrix();
 
  stroke(255,0,0,150);
  strokeWeight(8);
  point(random(40,160),random(40,160));
  point(random(40,160),random(40,160));
  point(random(40,160),random(40,160));
 
  //if(frameCount < 201){
  //  saveFrame("p131-5-###.jpg");
  //} 
}


Try it. :)

2011/07/14

Structure 2 : Continuous (processing教學)

最近深居簡出下,自己都會好好的穩定心情好好精進,  才怪.

不是一會兒昏死在床上,要麻就是去游泳(暢游無邊的網海)
.............  但還好我良知未泯,快活過後總會看個一兩頁課本
.............  總知我知道只要持之以恆好漢也能磨成繡花針

anyway,  希望對processing有興趣的人可以自己多看一點,
因為我的進度實在是忽高忽低,正確來說是忽低忽無,
所以如果你真的很有興趣的話,多看點然後換你來教我. :)

------------------------------------------------------------------------------------------------------------------


在其一段落嘗試畫一張圖之後,我們即將進入如何做動畫,
但processing基本上只會生產圖面,也就是無論今天是2D或3D,
它所顯示的動畫都是靠一張一張圖接續而成的,
也就是我們常可以在網站上看到那些會動的圖片, GIF.

一切會從p173的Structure 2 : Continuous講起,
我們跳過了p144-172總共28頁(好爽噢),
因為這些內容主要是在介紹一些數位藝術家,
可能是靠寫flash或processing之類的來作畫,
我個人比較喜歡的是p153跟p157的內容,
詳情可以參考以下兩個網站

p153 Mandelbrot Set
http://processing.org/learning/topics/mandelbrot.html

p157 Complexification
http://www.complexification.net/
這網站我好喜歡啊,可是它絕大多數的作品都是用flash做的,
真的是永遠學不完啊,人真的要會取捨.

以下我想把東西講得直接一點(也就是不要問為什麼),可能還比較好理解.
當要做動畫時, void這個詞是很重要的,它代表一個空集合.
舉例來說當我們要吃牛排時,
void就是一些罐子,裡面裝的是胡椒跟海鹽,
當我們要喝濃湯時,我們拿胡椒罐,當我們要吃牛排時,我們拿海鹽罐.

也就是這些罐子(void)是預先準備好的,當有需要時再拿來用,
這可以避免當我們processing要寫很長時,往往會因為一個小地方寫錯而整個程式動不了,
雖然以我這猶如128mb隨身碟的腦袋要寫什麼可歌可泣落落長的程式是不可能地.

一個動畫的基本是絕對要有void setup()跟void draw()的,
setup指的是背景設定,也就是我們長長在設的size(),background(),smooth()等等.
而draw則是指畫void裡面的東西,通常我們會有void apple, void ball等等很多void,
但只會有一個void draw, 因為畢竟我們只有一個畫面,你同時draw一堆也看不到,
所以才會有很多void,然後叫進void draw內一起畫.
讓我以一個簡單的畫圓來解釋.會有兩組寫法,但結果一樣.


void setup(){
  size(200,200);
  background(255);

  noFill();
  smooth();
  //noLoop(); 
}

//我們可以看到setup裡面有我們常用的定義尺寸跟背景顏色和smooth,
//而noLoop這東西指的是不要loop,也就是不要畫動畫的意思
//所以通常我們是無需打它的,在這只是打給你試試看.


int n = 0;
int r = 0;

//這是一定要記得的一件事,所有在void draw內有用到的float或int
//請一定要打在void draw之外,p174有解釋


void draw(){
 
  frameRate(50); 

//frameRate代表的是播放速度,也就是每隔多久換下一張圖
//數字越高越快,但過高或過低則不會有效果了


  r += 1;
  n += 1;
 
  if(n > 0){
    background(255);
    n = 0;
  }

//因為我是要畫一個圓不斷放大,但如果我沒有把之前的圖蓋掉的話
//那前面的圖就會一直墊在下面遮不掉
//因為我在setup裡設noFill(),如果沒設其實效果一樣,但在這我想講的比較細些
//為了確保我每換一張圖的時候前面的圖都被蓋掉
//所以我設了一個int n, n += 1,並if它只要 > 0時馬上背景刷白,然後n再度為0

  if(r > 200){
    r = 0;
  }

//r是我圓的半徑,如果我今天不限制它一到200(也就是圓碰到圖框邊時)歸0
//那你就會看到圓一直畫然後就跑出圖框,一片白了


  ellipseMode(CENTER); 
  ellipse(100,100,r,r);

//簡單的畫圓

  //if(frameCount < 201){
  //  saveFrame("p178-1-###.jpg");
  //}

//我們前面在畫單張圖時,可以簡單的以saveFrame輸出
//但當動畫時,我們要每一步驟的圖片才能後續用軟體制成GIF
//所以就用if告訴電腦在算到201張圖之前,每一張圖都幫我存起來
//也就是frameCount,最後總共我們會算輸出200張
 
}




另一種的寫法就像我剛剛提到的,
我先寫好一個要畫圓的void,然後在我需要的時候再把它叫進void draw內,如下

void setup(){
  size(200,200);
  background(255);
  noFill();
  smooth();
}


int n = 0;
int r = 0;


void draw(){  

  frameRate(50);
 
  n += 1;

  r += 1;


  if(n > 0){
    background(255);
    n = 0;
  }

//到這都跟上面一樣,唯一不同的是下面

  cr(100,r);
//這代表我要把一個叫cr的void叫進來(就跟設int或float一樣)
//而它裡面的(100,r)對應的正是下面void cr內的(int x, int y)
//所以得到的結果我知道x永遠為100,而y會+=1
}


void cr(int x,int y){
  ellipseMode(CENTER);
  ellipse(x,x,y,y);

//這邊一定要記得的是,除了void draw外
//你任何void內所設的float或int都要寫在( )內
//這樣把它丟入void draw時,它才會抓得到你所設的參數


在經過簡單的介紹後,你應該知道void基本是在幹麻了,
再來就是如何絞盡腦汁去想怎麼畫囉.
另外請不要在void draw內寫for loop,
不是不能寫,只是不要寫卡好啦,自己試就知道為什麼了.

另外關於動畫怎麼後製,
一個是直接錄螢幕(我用的是Cam Studio)
一個是把圖片們做成GIF(我用的是Photoscape) 
應該都滿好在網路上找到 ? ? 版的 
再來就是今天的無題作品囉!


void setup(){
  size(200,200);
  background(255);
  smooth();
}

int n = 0;
int a = 0;
int r = 0;

void draw(){
 
  frameRate(50);
 
  r += 1;
  n += 1;
  a += 5;
 
  if(n > 300){
    background(255);
    n = 0;
  }
 
  if(r > 300){
    r = 0;
  }

  pushMatrix();
  rectA(a,r);
  popMatrix();
 
  translate(100,100);
  rotate(radians(a));
  strokeWeight(random(1,4));
  stroke(255,222);
  line(0,0,150,150);

  //if(frameCount < 301){
  //  saveFrame("p180-###.jpg");
  //}
}

void rectA(int q,int k){
  translate(100,100);
  rotate(radians(q));
  stroke(0,20);
  strokeWeight(0.5);
  fill(random(255),random(255),random(255),20);
  rectMode(CENTER); 
  rect(0,0,k,k);
}

Try it. :) 

2011/07/12

Transform 1 : Translate, Matrices (processing教學)

這可以算是我們在畫2D的最後一篇介紹(要哭了),
因為之後會進入如何把2D的圖整合起來變成動畫,也就是大家所熟知的gif.


主題是p133-143的Transform 1 : Translate, Matrices跟Transform 2 : Rotate, Scale
Transform 1 的基本指令有
translate()
pushMatrix()
popMatrix()


Transform 2 的基本指令有
rotate()
scale()


------------------------------------------------------------------------------------------------------------------


Transform 1是在談一個移動基楚座標點(0,0)的概念
讓我們上一下英文課,這樣好把指令記得比較清楚.
translate一般我們都指翻譯,但其實它也有轉移調動的意思
而Matrix正是駭客任務的英文麻,它的意思是母體,
在processing裡代表的是我們所看不到的基礎點(0,0).
因此pushMatrix就是移動基礎點,popMatrix則是炸掉被移動的基礎點


當我們用translate移動了基礎座標軸(意即畫面左上的(0,0)點)
代表母體被移動了,當然我們可以靠translate再把它移回去,
但萬一我們translate一用多時,很容易忘記(0,0)被移到哪去了,
就可以靠pushMatrix和popMatrix來幫我們找回原始的左上(0,0)點
讓p135的16-06範例講應該比較容易懂





pushMatrix();  //當我知道要移動基礎點時,我就先設一個push告訴電腦我待會要移動基礎點了
translate(20,20);  //本來的(0,0)點被我移動到(20,20)這個點上定義為基礎點
rect(0,0,10,10);  //所以儘管我說要畫一個10x10的方形在(0,0)點上,它實際是畫在本來的(20,0)這點上
pushMatrix();  //當我又要移動在(20,20)的基礎點時,我就再設一個push告訴電腦又要移動基礎點了
translate(30,30);  //因為基礎點被改成(20,20),移動它至(30,30)等於把基礎點改至(50,50)這點上
rect(0,0,10,10);  //因此10x10的方形實際是畫在本來的(50,50)這點上
popMatrix();  //此時我想要回到本來的(0,0)點,但因為上面有兩個pushMatrix,因此我需要兩個popMatrix
popMatrix();  //如果只用一個popMatrix,則基礎點只會停在(20,0)
rect(60,0,10,10); //此時基礎點已回歸到(0,0)了






所以當我們如果要畫一個瓢蟲殼的圖案時,
我們可以很簡單的定義每個黑點的座標,也可以靠translate,pushMatrix跟popMatrix來做.








size(300,200);
background(255,0,0);
noStroke();
fill(0);
smooth();



ellipse(0,0,100,100);  //此時基礎點未改變,直接在(0,0)畫一黑點


pushMatrix();
ellipse(300,0,100,100);  //儘管已經在pushMatrix下,但我仍未translate,所以基礎點仍為(0,0),畫右上角的黑點
translate(width/2,height/2);  //translate基礎點至圖的中心,意即(150,100)
ellipse(0,0,100,100);  //在中心畫一黑點
translate(width/2,height/2);  //再次移動基礎點,因為再往x移動150,y移動100,所以新基礎點為(300,200)
ellipse(0,0,100,100);  //在右下角畫一黑點
popMatrix();  //因為我只有用一次pushMatrix,所以當我pop掉它時,它回直接回到(0,0)原始基礎點



ellipse(0,200,100,100);  //因為已經回歸(0,0),所以要在左下畫黑點就要定義座標(0,200)


//saveFrame("p135-##.jpg");


------------------------------------------------------------------------------------------------------------------

Transform 1懂了之後就要進入Transform 2的scale()rotate(),

也就是比例縮放旋轉角度基本上旋轉跟縮放比例會造成原訂座標點的錯亂,
所以會用到前面的translate加以校正,以下的範例是把所有概念一次包了




size(200,200);
background(255);
smooth();
noFill();
strokeWeight(2);



float s = 1.5; //這決定我的縮放倍率


rectMode(CENTER);
translate(width/2,height/2);  //基礎點被移至圖面中心(100,100)
rect(0,0,50,50);  //先畫一50x50正方形

scale(s); //此時縮放倍率為1.5
strokeWeight(2/s);  //把原本線粗除比例即可確保線粗不會因為縮放而不一
rotate(radians(45));  //讓正方形旋轉45度
rect(0,0,50,50);

scale(s);  //此時的倍率為原本1.5倍的再1.5倍,scale是會疊加的
strokeWeight(2/s/s);  //把上面線粗(2/s)再除以一次新比例
rotate(radians(-45)); //把方形轉回來
rect(0,0,50,50);

//saveFrame("p139-##.jpg");


因此儘管我們都是在中心畫50x50的正方形,但我們可以看到除了線粗外
角度跟大小都因旋轉跟縮放而改變了,translate可以幫我們把因rotate跟scale而錯亂的座標點重新統整.
有人喜歡先rotate再translate,有人則喜歡先translte再rotate(我!),p140有非常清楚的diagram,一定要看!
我個人認為除非已經寫到下一階段的gif,否則不要用到scale,因為它關不掉(至少現在是這樣),
不像rotate跟translate有方法回歸到原本狀態.

金針菇的俯視圖?





size(200,200);
background(255);
smooth();


translate(100,100);
for(int divd = 0; divd < 120; divd += 1){
  stroke(random(0,150),90);
  strokeWeight(random(1,4));
  rotate(radians(3));
  int k = int(random(10,75));
  line(0+(k/8),0+(k/8),k,k);
 
  stroke(25,150);
  strokeWeight(random(6,10));
  point(k,k); 
}


//saveFrame("p143-##.jpg");


Try it. :)