2010年9月20日

用MEL打造系統時鐘

本篇文章我已上載至http://www.aboutcg.net/
地址為:
http://www.aboutcg.net/showthread.php?t=2203


零、 前言
這是一篇MEL簡單應用的教學文章,並非什麼高深的理論。對於現在互聯網的各種言論現象,有幾點不得不說的。如果能給各位讀者起到拋磚引玉的作用,筆者這裡會比較欣慰。能幫助學習maya及學習MEL的朋友提高技術是作者寫本篇教學的初衷。當然,如果您不喜歡,認為這個太easy了,也請幫忙進行改進批評。如果只是看著不爽,也免開尊口罵人,這樣不好。本篇文章用一個極簡單的模型:“時鐘”來闡釋MEL對動畫、特效方面的一些應用,不需要很高深的MEL功底,當然更不需要高深的模型能力。如果沒有什麼問題我們就開始吧。




一、 概論
其實實現系統時鐘3D化的手段有很多,可以用MEL也可以用Python。
大致可以分為3段思路:
0.系統CMD
這個還是要從Maya論壇的一個發起的帖子說起,有一篇名為“mel問題。大夥幫忙看看”(作者是“我恨我癡心”),當時他發的是一個系統時間的問題:
string $cmd = "date /t";
chdir "C:";
string $date = `system $cmd`;
$date = `substring $date 1 10`;
$cmd = "time";
string $time = `system $cmd`;
$time = `substring $time 22 26`;
string $dateTime = strip($date) " " $time;

// Result: 2010-03-23 新時間: //


為什麼在我另一台上顯示的是
// Result: 2010-03-23 0:21 //
這是個正確的。我想得到當前的系統日期和當前時間,應該怎麼改。 。

2010-03-23 00:22 像這樣。 。後面加上秒也行
機器貓給的回復是
string $date = `system "date"`;

string $res = `match "[0-9] .*[0-9] " $date`;
這就告訴我們,有一種思路是用MEL間接調用系統CMD,這是一個很好的思路,用系統中的date取系統時鐘,但是問題也隨之發現了,會因為部分設置的不同導致有非需要的字符串產生。

而且這種狀態是以修改time為代價的,個人不是很贊同這種思路,但是也不能說不對,仁者見仁智者見智。


1. Python
這個也是我當時解決這個問題的一個方案,因為Python內建time模塊,所以直接import就可以了。下圖是Maya2011導入time模塊後的反饋,我很喜歡這個新功能,很方便也很實用。...



我的第一套方案是這樣:
import time
time.strftime("%b %d %Y %X", time.localtime() )
# Result: Mar 23 2010 13:46:10 #
這套解決方案的有點是利用Python內建time模塊對時間的操作非常的豐富,語句精煉不拖沓。但是缺點就是如果要拋出給maya執行字符串操作最後還要轉成MEL語句,這點很討厭。 XSI這點就做的比MAYA要好。當然maya也不是不可以,需要def給內存一下才能用python調用到表達式裡,格式也是很麻煩的,比如python(ct(”(“+”time”+”)”)).


2. MEL
經過一些思考,因為MAYA最終還是MEL內核,不管是寫還是算,MEL都顯得比較方便,所以最終還是採取了這套解決方案。
代碼很簡單:
About –ct;
// Result: 11:36:36 //
這樣就可以用一個string來接,當然它不是list,以後還要轉換,不過相對於前兩種思路這種思路要更容易操作。


二、 前期準備
前期要準備模型,模型是比較簡單的:
0. 一個圓盤
1. 3個時鐘的針
2. 1~12一共12個數字模型
3. 當然你也可以選擇做一個大櫃子,這個就隨便了
注意軸心要在同一個軸上,否則轉起來就比較詭異了:


拼裝後:(當然,你的模型可能一開始都是00:00:00,這是一個很好的狀態)


三、 程式分析
0. 現在要做MEL返回值的測試:
使用about –ct;的返回值是一個字符串,// Result: 11:46:21 //。也就是說結果存在於11:46:21,準確的講它應該是一組Unicode,當然也屬於字符串。
所以在這裡用string來接:
string $ct=`about -ct`;
此時$ct就包含結果11:46:21
1. 事實上11:46:21想讓指針發生轉動,是不能直接進行的,必須轉換成角度數值,這樣才能讓指針發生轉動。此時狀態:




我們命名秒針為Second,分針為Mins,時針為Hour。我們的目的就是秒針與秒針度數對應,分針時針亦然。
2. 這裡要進行數學換算。
圓周是360度,錶盤上有60個格子,所以每個格子是6度。這樣當我把系統時間讀出來以後,換算度數就是:
秒數*6=秒針度數
分針*6=分針度數
時針*30=時針度數(因為1小時=5個格子,所以應該*30,這裡很容易出錯)
因為maya中順時針的旋轉的負向的,所以最後都要乘以負度數。
此時進行虛擬變量帶入表達式:
設定$s $m $h分別為字符串轉換為數據類型的變量:
setAttr Seconds.rotateZ ($s*-6);
setAttr Mins.rotateZ ($m*-6);
setAttr Hour.rotateZ ($h*-30);
3. 現在的問題就是圍繞著$s $m $h如何能把之前的字符串$ct中的11:46:21字符串轉換為整數或者浮點。這個不是很容易想。這裡我使用指令tokenize,它可以把字符串中以一種符號進行分割,然後傳送到另一個新的變量數組中。
格式如下:
string $ct=`about -ct`;
string $cts[];
tokenize($ct,":",$cts);
現在表述的意思是用“:”冒號來拆分$ct,然後把新的變量放入數組$cts[]中,當然這也是一個字符串數組。不過此時變量就不是一個Unicode,而是一個List:
$cts={“11”,”46”,”21”}這樣的形式
4.$cts已經接納了3個元素,這時候需要做的就是賦予$s $m $h這三個變量,用聲明變量的格式就可以達到轉換的目的:
string $ct=`about -ct`;
string $cts[];
tokenize($ct,":",$cts);
int $s = $cts[2];
float $m = $cts[1];
float $h = $cts[0];
setAttr Seconds.rotateZ ($m*-6);
setAttr Mins.rotateZ ($m*-6);
setAttr Hour.rotateZ ($h*-30);
4. 下面的數字碼時鐘是比較簡單的:
用Text命令任意創建3D立體字,通過MEL可以達到間接修改
如:setAttr -type "string" textForBevel1.text “aaa”;
就會讓立體字變成aaa的樣式,所以經過嵌套變量可得出:
String $ct=`about -ct`;
setAttr -type "string" textForBevel1.text $ct;
string $cts[];
tokenize($ct,":",$cts);
float $s = $cts[2];
int $m = $cts[1];
float $h = $cts[0];
setAttr Second.rotateZ ($s*-6);
setAttr Mins.rotateZ ($m*-6);
setAttr Hour.rotateZ ($h*-30);


利用下圖變量:
此時播放時間線,即可得到系統時間。


四、 渲染及其他
渲染用了較為簡單的occ》SurfaceShader的做法,這個就不做贅述。推薦occ的sample用256,渲染器0-2精度採樣,基本上還是不錯的結果:


Render輸出+簡單PS:


五、 結語
本篇教學用簡單MEL闡釋了腳本與動畫之間的聯繫與應用,希望會對各位學習和研究MAYA的朋友們有所幫助,僅此。謝謝觀看!

沒有留言:

張貼留言