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. :)

沒有留言:

張貼留言