2009年4月29日 星期三

Copy UV 注意事項

如果你想把一個 polygon 模型的UV複製到另外一個一摩一樣的模型的話, Maya 的 Mesh->Copy Mesh Attributes 就是你的好幫手. 可是你可能不知道的是,就算形狀,點數,線數,面數一模一樣的模型,也不見得可以成功的把 UV複製過去,因為Copy UV成功條件有三個:
  1. 兩個模型的點數,線數,面數是一樣的.
  2. 兩個模型的點順序和面順序是一樣的.
  3. 兩個模型的 face winding order 是一樣的.

face winding order

我們就拿以下三個 case 來做範例...



A, B, C, D 這四個模型的點數,線數,面數都一樣,形狀也一模一樣(除了 D 是反方向). 我們就用 Copy Mesh Attributes 來把 A 的 UV 複製到 B, C, D 看看吧.


case1 : A 複製到 B

A可以成功的把 UV 複製到 B, 因為 它們都符合 (1), (2), (3) 這三個條件.



case2 : A 複製到 C

A 和 C 雖然 符合條件 (1) , 但不符合條件 (2), 所以 Copy UV 失敗了. C 因為作過某些更動(裡如 split, combine 等等的動作) 使得 vertex order 或face order 變得跟 A 不一樣. 如果你遇到這種 情況的話就必須用其他方法複製(例如 Mesh ->Transfer Attributes),除非你手動寫程式把 順序轉回跟A 一樣 再複製.


case3 : A 複製到 D

A和D 符合 條件(1) , (2) ,可惜的是它們不符合(3), 因為 D 這模型是用 scale = -1 去複製的,導致它們的 face winding order 相反. 這種 case 常常發生 (在做對稱模型時健模師通常都會先做一邊然後用 scale = -1 來複製另一邊). 這樣的話如果你直接用 Copy Mesh Attribtues 也是會失敗(注意左邊模型D 手臂的貼圖很明顯是錯的). 好消息是這種 case 還有得救. 你需要執行以下四個步驟:

  • 先把 D 的 normal 翻轉 (Normal->Reverse). 執行這步驟之後,條件 (3) 就符合了.
  • 執行 Copy Mesh Attributes
  • Delete History.
  • 再把 D 的 normal 翻轉一次.

用完之後你會發現雖然出來的 UV 方向是反的 (D的 UV是紅色, A的是藍色), 但出來的貼圖變正確了.


網路上有一個拆 UV 軟體叫 Zebruv, 其中一個功能就是讓你可以輕鬆診對 case 1 和 case來Copy UV. 它可以自動判斷兩個模型是否相反的,然後再做適當的處理. 除此之外,它也可以做多個模型 UV 複製 (maya的 copy mesh attribute 只讓你一對一複製).

2009年4月27日 星期一

何謂 non-manifold 問題

簡單來說,一個模型被稱為 non-manifold 如果它不能被攤開成一片連續的2D 平面.


2-manifold geometry :可以攤開成一片連續的2D 平面



non-manifold geometry : 必須攤開多片連續的2D 平面


non-manifold 的模型通常會造成後續的許多麻煩,例如 bevel無效,subdivision 失敗, render 錯誤等等的問題,所以建模時必須注意並且盡量避免做出non-manifold模型.

基本上一個non-manifold 模型會有至少以下三個因素之一:

non-manifold edge : 一個線(edge) 連到三個以上的面



non-manifold vertex :
  • 兩個以上的面分享一個點卻沒分享任何線, 或
  • 造成 non-manifold edge 的點



lamina face : 兩個以上的面分享共同的點和線



如何用 mel 程式來偵測non-manifold問題.

non-manifold vertex:
{
string $selected[]=`ls -sl`;
string $nmv[] = `polyInfo -nmv $selected`;
if(size($nmv)>0)
{
select -r $nmv;
warning("polygon has non-manifold vertices");
}
};


non-manifold edges :
{
string $selected[]=`ls -sl`;
string $nme[] = `polyInfo -nme $selected`;
if(size($nme)>0)
{
select -r $nme;
warning("polygon has non-manifold edges");
}
};


lamina faces:
{
string $selected[]=`ls -sl`;
string $lf[] = `polyInfo -lf $selected`;
if(size($lf)>0)
{
select -r $lf;
warning("polygon has lamina faces");
}
};


Maya 的 cleanup 功能 (Mesh->Cleanup...) 可以自動幫你移除掉 non-manifold / lamina faces ,可是出來的結果可能不是你預期的,所以還是建議手動把這些問題解決.

2009年4月26日 星期日

MakeHuman : 人物生產器






如果你像我ㄧ樣,連一個基本人物模型都做不出來的人,看到這套軟體應該會很高興吧.它叫做 "MakeHuman", 一個 免費(open source) 軟體. 用一些預訂參數 (性別,年齡,體重等) 以及手動調整,就可以做出一個形狀不錯的模型.

MakeHuman 介面


但你可能會擔心:用這種軟體生出來的模型可以用嘛?佈線會不會很糟呢?這是合理的憂慮,因為很多類似的軟體可以生出很好看的模型,可是因為佈線太糟了,最後還是廢掉. 可是MakeHumant產生出的模型佈線還不錯,拿來做動畫應該不會有太大的問題.


MakeHuman 輸出的 3d 模型


軟體介面感覺上還蠻簡單直覺的. 幾乎所有功能都可以用滑鼠來操作. 模型調整介面分成大(macrodetail), 中(detail), 小(microdetail) 三個部份.



適用年齡,體重設定來改變人物體型




你也可以手動細調模型的形狀


除了快速建模,你也可以直接用 pixie, aqsis, 或 POVRay 來 render, 只是要先裝好那些算圖軟體就是了. 未來版本據說也會支援擺 pose,輸出各種3D格式功能.目前軟體只能輸出 obj / bvh 格式.輸出的方法是在主要介面裡(不是在 export 介面)按下 'e' . obj / bvh 檔將會在 跟 makehuman.exe 檔的同樣目錄裡出現.

MakeHuman 官方網頁 : http://www.makehuman.org/blog/index.php

2009年4月24日 星期五

python : 偵測一個點是在某個模型內或外

有一位cgtalk 的網友寫了一個 python function, 使用 maya python API 來偵測一個點是在模型裡面或外面 (point inside object) . 這程式還沒經過加速改善,所以處理大量data可能會有點慢,可是一般來說應該還蠻好用的.

import maya.OpenMaya as OM
from math import fmod

def pyRayIntersect(mesh, point, direction=(0.0, 1.0, 0.0)):

  OM.MGlobal.selectByName(mesh,OM.MGlobal.kReplaceList)
  sList = OM.MSelectionList()
  #Assign current selection to the selection list object
  OM.MGlobal.getActiveSelectionList(sList)

  item = OM.MDagPath()
  sList.getDagPath(0, item)
  item.extendToShape()

  fnMesh = OM.MFnMesh(item)
  raySource = OM.MFloatPoint(point[0], point[1], point[2], 1.0)
  rayDir = OM.MFloatVector(direction[0], direction[1], direction[2])
  faceIds = None
  triIds = None
  idsSorted = False
  testBothDirections = False
  worldSpace = OM.MSpace.kWorld
  maxParam = 999999
  accelParams = None
  sortHits = True
  hitPoints = OM.MFloatPointArray()
  #hitRayParams = OM.MScriptUtil().asFloatPtr()
  hitRayParams = OM.MFloatArray()
  hitFaces = OM.MIntArray()
  hitTris = None
  hitBarys1 = None
  hitBarys2 = None
  tolerance = 0.0001
  hit = fnMesh.allIntersections(raySource, rayDir, faceIds, triIds, idsSorted, worldSpace, maxParam, testBothDirections, accelParams, sortHits, hitPoints, hitRayParams, hitFaces, hitTris, hitBarys1, hitBarys2, tolerance)

  result = int(fmod(len(hitFaces), 2))

  #clear selection as may cause problem if the function is called multiple times in succession
  #OM.MGlobal.clearSelectionList()
  return result


測試程式:

from pymel.core import *



def testIntersect():
sel = ls(sl=1)
container = sel[0]
checkInsideObj = sel[1]
allVtx = ls(str(checkInsideObj)+'.vtx[*]',fl=1)
allIn = []
start = timerX()
for eachVtx in allVtx:
location = pointPosition(eachVtx,w=1)
test = pyRayIntersect(container,location,(0,1,0))
if(test):
allIn.append(eachVtx)
elapsedTime = timerX(startTime = start)
print "time :",elapsedTime
select(allIn,replace=1)



2009年4月22日 星期三

Transfer maps: 轉移貼圖(texture)功能




Maya 的 transfer maps 可以把一個模型的貼圖 (或細節,或occlusion)轉到另外一個模型上. 模型彼此貼的越緊,轉出來的貼圖就會越準確.

範例:

左邊是Maya的標準 poly sphere, 右邊是 smooth 過後的 poly cube. 你可以注意到這兩個模型不管是面數,線型,和 UV 都不一樣 (但是大小跟位子是差不多的),所 pSphere1 的貼圖如果直接貼到 pCube1 上,效果就會很不一樣. 現在我們來把 pSphere1 的貼圖轉到 pCube1 上吧.





->執行 Rendering->Lighting/Shading->Transfer Maps[]





設定簡易說明:

*Target Mesh : 要接收新貼圖的模型(pCube1). 點選你要用的模型,然後按 add selected.
*Source Mesh : 原本已經有貼圖的模型 (pSphere1) . 點選你要用的模型,然後按 add selected.
*Output Map : 想要轉過去的貼圖類別.
  • 轉模型細節 : normal 或 displace
  • 轉貼圖顏色: diffuse 或 shaded
  • 轉透明度 : alpha
  • 轉occlusion : Ambient
我們現在只想用單存顏色,所以按下diffuse.
*Diffuse Color map & File format : 貼圖路徑 和格式
*Map width & height : 貼圖大小
*Transfer in : World space (兩個模型都在同一個位子上)
*Sampling quality :數值越大效果就越好,但會算越久
*Filter size : 轉出來的貼圖要比較 模糊(blur) 或 銳利 (sharp). 數值越大就會越 blur
*Filter Type : Gaussian (相對下最好的演算法)
*Fill texture seams : 轉出來的貼圖在 UV 邊緣上要多算幾個 pixel (避免render出來有接縫). 通常 4 到 8 個 pixel 就夠了.

->按下 bake 或 bake and close.




算出來的結果. pCube1 這個模型有了很類似 pSphere 的貼圖 !

2009年4月21日 星期二

Maya import obj : 點順序

對有些軟體或工具來說,一個模型的 點順序 (vertex order) 是很重要的. 例如 Copy Mesh Attributes. 兩個模型雖然點數面線數都一摩一樣,但如果點的 順序不一樣的話 copy mesh attributes 這功能就會失敗或轉錯. Zbrush 也是這樣 .很多使用者抱怨 用maya改完 UV 後把模型重新 import 到 Zbrush ,如果你再把 subdivision 調上去,整個模型就會爆炸. 這也是是因為 vertex order 已經改變了.
在 Maya import obj 的設定裡有一個很重要的選項叫做 "Create multiple objects". 如果這選項被打勾了,Maya就會試著把模型分成好幾個 group, 也會改變到 vertex order.所以說如果你在意 點順序 的話 (例如要把模型再送到 zbrush) 那就不要打勾 這 "Create multiple objects" 選項. (聽說maya 2009 SP1 已經把這問題解決,但我還沒試過).


Maya8.5 import obj 介面


Maya2008 import obj 介面

2009年4月20日 星期一

檢查 模型是否封閉

以下的 mel 程式可以幫你把模型所有的邊線 (border edge / border loop) 選起來, 讓你檢查模型是否有你不想要的 border edge (例如兩個點(vertex) 沒接好之類的問題 ).




{
polySelectConstraint -mode 3 -type 0x8000 -where 1;
string $selectedEdge[] = `ls -sl`;
polySelectConstraint -disable;

if(size($selectedEdge)>0)
for($eachEdge in $selectedEdge)
warning("border Edge: " + $eachEdge+"\n");
else
print "no border\n";
}

2009年4月19日 星期日

Smart Bake : 減少 bake simulation 的key frame 數量

之前我有寫過如何使用 simplify curve 來減少 key frame 的 數量. 如果你覺得這招有點麻煩,這裡有個好消息: 我發現 Maya 2009 的 bake simulation 有個新功能叫做 smart bake. 它可以自動幫你只產生"有用"的keyframe, 減少 key frame 數量.

主要參數: Fidelity Keys Tolerance -> 數值越小,出來的 animation curve就會越準,可是key 數量也會越多.




用之前的範例 來做 bake simulation 的結果. 上面是沒有使用 smart bake, 下面是有使用 smart bake, 並且把 Fidelity Keys Tolerance 設成 1.0% .

2009年4月18日 星期六

Maya Booleans 成功訣竅

Maya Booleans 可以說是很不穩定的一個功能.不管是 union, difference, 或 intersection,執行完之後整個模型常常都會消失,或是出現不是你想要的結果.




那要如何讓 Booleans可以成功執行呢? 以下有幾個步驟可以參考:

1. 把洞補起來,尤其是形狀複雜的洞.



2. 檢查 normal 方向是否正確.



4.Edge/Face的密度如果差太多,試試看把face較少的模型 smooth 一兩下.



3. 如果模型的 scale 太小,試試看把 scale 用大一點.



4. freeze transformation



5. 把 history 殺掉



執行完這些步驟之後boolean 的成功率就會提高不少.

2009年4月17日 星期五

import 之後如何移除物件的 namespace

當你把某個maya檔 import 到另外一個maya檔裡, 而且 import 選項裡有把 "use namespaces" 打勾 ( maya本身是建議你把它打勾,為了避免物件名稱衝突而造成的問題), import 完之後你就會發現物件名稱前面多了一個字串 再加一個冒號 (或多個).這東西叫做"namespace".




如過你覺得這些字串太長了,你不需要,或production 規定名稱不能有namespace, 那以下的 mel 程式可以把 這些 namespace 去掉.

{
 string $allNodes[] = `ls -l`;

string $allNamespaceNodes[];

for($each in $allNodes)
{
      if(`gmatch $each "*:*"` && (`nodeType $each` != "reference") && (!`referenceQuery -isNodeReferenced $each`))
         $allNamespaceNodes[size($allNamespaceNodes)] = $each;
 
}

int $nodeLevel[];

int $maxLevel=-1;
int $index = 0;
for($each in $allNamespaceNodes)
{
     string $tokens[];
     int $numToken =tokenize($each,"|",$tokens);
     $nodeLevel[$index] = $numToken;
     if($numToken > $maxLevel)
         $maxLevel = $numToken;
     $index+=1;
}

 print("nodes to be renamed: "+size($allNamespaceNodes)+"\n");

int $index = $maxLevel;
while($index>=1)
{
     int $index2=0;
     for($each in $allNamespaceNodes)
     {
         if($nodeLevel[$index2] == $index)
         {
             if((`nodeType $each` != "reference") && (!`referenceQuery -isNodeReferenced $each`))
             {
                 string $tokens[];
                 int $numToken = tokenize($each,":",$tokens);
                 string $shortName = $tokens[$numToken-1];
             
                 int $index=1;
                 string $newName = $shortName;
                 while(`objExists $newName`)
                 {
                     $newName = $shortName+$index;
                     $index+=1;
                 }
                 print ($each+" -> ");
                 string $result;
                 string $command = "rename "+$each+" "+$newName;
                 int $test = catch( $result = eval($command));
                 print ($result+"\n");
             }
         }
     
         $index2+=1;
     }
     $index-=1;
}
}

nb : 這個程式只把 import 物件的namespace 去掉, reference 物件 的 namespace 還是會保留.


執行完之 這些 namespace 就消失了.


-> 如何把以上的mel 程式變成一個shelf 按鈕.

2009年4月16日 星期四

Prescale UV : 調整UV <-> 模型相對 比率

Prescale UV 是 Maya 2008 extension 2 新增功能. 它的用途是來調整模型與 UV shell 的相對比率. UV 比率不正確會造成上貼圖的困難度增加(除非你是故意的)


臉部 與 嘴巴 UV 大小 比率差太多.

Prescale UV 這功能是 " 隱藏" 在 UV texture editor 的 Polygons->Layout[] 或 Menu 的 Edit UVs->Layout[] 裡頭.




->Layout objects : Single or Multiple Objects (non-overlapping)
這選項可以讓你針對一個或多個物件做 prescale & layout

->Prescale : World
用模型真正的 scale 來做調整UV

->Rotate : None / 90 degrees / Free
調整UV時要不要把 UV Shell 做 rotation (為了得到最佳 layout).


執行完之後模型與UV比率就會比較正確.


上完一張基本貼圖,你會發現嘴部與臉部的 pattern 是比較均勻的 (相對來說,prescale 之前的嘴部 pattern 太大了).

2009年4月15日 星期三

模型 normal 被鎖著

如果你發現模型的 shading 看起來怪怪的, 可是 face normal 方向卻是正確的.. 那有可能是模型normal 被鎖著了.

正面看模型好像凹進去,但側面看卻好像凸出來. face normal 方向沒問題.


要解決這問題不難. 你只需要把模型選起來,然後執行 Normals -> Unlock Normals 或是 Normals->Set to Face . 模型的 shading 應該就會恢復正常.



2009年4月13日 星期一

當機之後 暫存檔要到拿找

如果Maya當機之後就跳掉沒什麼訊息的話,那就沒救了. 可是如果出現這種視窗:



表示你還有機會救回那個檔案. 那要到拿找呢? 預設資料夾是在:

Windows XP : C:\Documents and Settings\[帳號]\Local Settings\Temp
linux : /usr/tmp


或你可以在 Maya 下此指令來得知暫存檔是在哪:

getenv "TMPDIR";

暫存檔有日期時間,看哪個是最接近你當機時間那就是它了.

2009年4月12日 星期日

小技巧: 用舊的Maya打開較新版本的檔案

Maya 的預設是不讓你打開較新版本檔案的. 例如說你要用 Maya8.5 打開 2008的檔案, Maya會吐出"Unknown Maya file version:2008 . line 0: Error reading file" 這些訊息,然後就放棄了. 你需要到 File->Open Scene[] 選項裡把 Ignore Version 勾起來, 然後按下 Apply. 改完設定再試一次, Maya 雖然還是會吐出一些錯誤訊息,但它會繼續試著把檔案開起來.

2009年4月11日 星期六

簡化動畫曲線 ( animation curves )

當你把某個物件的動畫 bake 之後 (edit->keys->bake simulation), 你會發現動畫的每一個 frame 都會有 key. 如果這是你的final animation (雖然在 production 時幾乎沒有所謂的"final") 那就沒什麼問題. 如果你之後還需要改變動畫, 你就會發現你的 animation curve 都是塞滿 key, 要對它做修改的話好像乾脆重做都比較快 :sad:.

沒關係,Maya的 graph editor 裡就是有個功能專用來處理這種事. 這功能叫做 Curves->Simplify curve. 它可以把"不必要"的 key 刪掉,只留下真正對一個curve 有"貢獻"的keys.神奇吧!

話不多說,我們就來用看看!

-> 首先在maya裡產生一顆球與一個平面.



-> 把球變成一個 active rigid body (選取球然後執行 Soft/Rigid Bodies -> Create Active Rigid Body)

-> 把平面變成一個 passive rigid body (選取平面然後執行 Soft/Rigid Bodies -> Create Passive Rigid Body)

-> 加 gravity 在球身上(選取球然後執行 Fields->Gravity)

執行到這裡,你把animation 往前跑的話 球就會在平面上彈跳.我們現在要把球彈跳的動畫bake 成 keyframe.

-> 選取球的 translate channels, 然後執行 Edit->Keys->Bake Simulation []



-> maya 把動畫bake 完之後,打開 graph editor. 在 translateY 的 animation curve 你會發現每一個 frame 都有 key的. 我們現在要做的是減少這些 key 的數量並且可以維持 animation curve 的形狀.



-> 執行 Curves->Simplify Curve[]


simply curve 的演算法有兩種 :classic & Dense data. 建議使用 Dense data,因為 Dense data 比較適合對密集 keyframe 狀況 做簡化.
time tolerance : 數值越高,出來的key數量就越少,形狀差異越大.

-> 按下 apply 或 simplify



出來的結果, key 數量果然減少了,而且球的動畫根原來的相較之下差異並不大.之後要修動畫的時候,這種 animation curve 就好修多了.