Schema、API Schema与MFn
大部分知識都是相通的,Maya和USD在設計上有很多相似之處,USD的Schema粗看很難理解,但實際上與Maya的MFn有著異曲同工之處。這篇文章會簡單介紹一下這兩個知識點,做個對比,了解下它們在各自環境下的使用套路,長長姿勢,幫助看官們融會貫通,聞一知十。
廢話不多說,正文開始。
首先我們來看看USD中的Schema:
USD defines aschemaas an object whose purpose is to author and retrieve structured data from someUsdObject. Most schemas found in the core are "prim schemas", which are further refined intoIsA SchemasandAPI Schemas, for which the USD distribution providestools for code generationto create your own schemas. Schemas are lightweight objects we create to wrap a UsdObject, as and when needed, to robustly interrogate and author scene description.
USD定義Schema的目的是編寫、檢索一些UsdObject的結構化數據。USD內核中大部分能找到的Schema大多數都是Prim類型的Schema,這些Schema以委托的方式封裝了UsdObject,并提供了相應的函數來訪問UsdObject。這些Schema可以進一步細分為IsASchema和API Schema,對此,USD的軟件發行版也提供了生成代碼的工具來創建自己的Schema。
Schema是輕量級的對象,我們創建它來封裝UsdObject,并在我們需要的時候,能夠穩定的詢問和編寫場景描述。
Schema的簡易繼承關系如圖:
UsdGeomSphere就是一種Schema,提供了一套與內含數據相關的函數集,比如GetRadiusAttr()可以獲取球體半徑。由于繼承Usdtyped,它是可以定義自身身份類型的。Schema不僅提供了操作內部數據的API,還提供了與Stage交互的功能,記錄其自身在Stage中的層級和合成方式,以實現資產與資產之間的嵌套組合,實際上Schema就是層的概念,它包含了原始幾何體數據,在場景層級中以層的方式組成有向循環圖。
An API schema is a primSchemathat does not represent an object's type-identity, but simply serves as an interface orAPIfor authoring and extracting a set of related data.
Choose to create an API Schema when you have a group of related properties, metadata, and possibly associated behaviors that may need to be applied tomultiple different types of prims. For example, if your pipeline has a set of three attributes that get authored onto everygprim, and you want to have a robust schema for authoring and extracting those attributes, you could create an API schema for them.
Why not instead subclass thetypedUsdGeomGprim schema and add the attributes there? Because you would then need to redefine all of the schema classes that derive from Gprim, thus preventing you from taking advantage of built-in DCC support for the UsdGeom GPrim-derived classes. API schemas provide for "mix in" data organization.
API schemas can be generated using theUSD schema generation tools, but they can also be created manually.
API Schema是Prim類型的Schema,但無法表示對象的類型身份,只能用作編寫和提取一組相關數據的接口或API。舉個例子,UsdModelAPI就是一個API Schema,它有一套函數來操作模型,比如GetAssetName()可以獲取模型的名稱,GetAssetVersion()可以獲取模型的版本名稱。而這些函數是與被訪問對象的具體類型無關的,無論它是sphere還是cube,只要它是模型,就支持UsdModelAPI的訪問。
如果你有一組相關屬性、元數據、可能相互聯系的行為,需要添加到多個不同類型Prim對象上,請選擇創建API Schema。比如,如果在你的流程中,每個UsdGeomGprim實例上的都創建了一套三個屬性構成的組,你想有一個穩定的方式來編寫或提取這組屬性,你就可以為他們創建一個API Schema。
為什么不創建UsdGeomGprim的子類,把這套屬性添加到子類里呢?因為如果這樣,你就需要重新定義所有Gprim的子類的API Schema,看下圖:
如果你只是創建了UsdGeomGprim的子類,那只有這個子類會得到相應的API支持,UsdGeomGprim下游的其他子類是不受支持的。
顯然這會阻礙你從DCC對UsdGeom的原生支持中受益。
你可以使用USD schema generation tools來生成新的API Schema,也可以手動創建它們。
API Schema的簡易繼承關系如圖:
UsdModelAPI就是一種API Schema,跳過Usdtyped,直接繼承自UsdSchemaBase,這就意味著UsdModelAPI是無法表達自身類型的。
我們再來看看MFn:
Any class with this prefix is a function set used to operate on MObjects of a particular type.
Objects and function sets are always used together. They are separate which easily establishes ownership—objects are always owned by Maya, and function sets are always owned by you.
任意以MFn做前綴的類都是用來操作特定類型MObject的函數集。
MObject和函數集(MFn)總是一起使用的,它們的擁有權是不同的,MObject一直被Maya持有,函數集(MFn)則一直被用戶持用。
對Schema、API Schema及MFn稍加對比不難發現,這三者的設計目的都是用來操縱軟件內部數據對象。
下面再對Schema、API Schema及MFn的異同從這幾個方面做一個總結:
實現方式:Schema、API Schema、MFn都是通過delegate(委托)的方式實現,通過將數據對象實例傳遞給這三個工廠類,來達到對象組合的作用,這種復用方式往往也稱為黑箱復用(black-box reuse)。這種方式由于只要工廠類和數據類遵守接口約定,運行時刻數據類也能動態替換,因此,Schema、API Schema、MFn三個類在各自環境里對其它對象的依賴更少,具備更高的靈活性。這也是大型軟件開發中的常見套路。
擁有權:Schema、API Schema對象的擁有權歸屬Stage所有,由Stage分配和釋放,舉個例子:
sphere = stage.DefinePrim('/hello/world', 'Sphere')
這是一個典型的委托形式,新創建的sphere對象由stage對象持有,而stage是可以被用戶訪問編輯的,所以Schema、API Schema、MFn三者的擁有權都歸屬用戶。
作用對象:Schema、API Schema的作用對象是UsdPrim,UsdPrim是USD中的基本元素。內部結構如圖:
顯然UsdPrim是USD內部對象的一個handle,Schema、API Schema操作的實際上就是USD內部的數據對象。而MFn操作的MObject當然就是Maya中的數據對象啦,在作用對象上Schema、API Schema、MFn也是異曲同工。
調用方式:我們來看一個Schema的使用例子:
spherePrim = UsdGeom.Sphere.Define(stage, '/hello/world')
這行代碼執行后會在stage的'/hello/world'路徑上創建一個球體對象,該球體對象由spherePrim持有,相當于將sphere委托給spherePrim。
我們再來看一個MFn的使用例子:
MFnNurbsCurve curveFn; MObject curve = curveFn.create( ... ); MFnNurbsSurface surface( curve );
第一行定義一個名為curveFn的MFn實例,第二行通過curveFn的create方法創建一個名為curve的MObject,顯然這是一個用MFn創建數據對象的做法。而第三行用構造函數的方式創建一個新的surface對象,同時把curve傳遞給surface,這就是一個標準的委托方式。
可見在調用方式上三者也非常近似。
自定義:自定義指的是開發新類,擴展功能。Schema的開發方式與MFn還是有很大不同的,USD提供了代碼生成工具,你只需要按照如下例子編寫一個schema.usda文件:
class "SimplePrim" (
    doc = """An example of an untyped schema prim. Note that it does not specify a typeName"""
    inherits = </Typed>
    customData = {
        string className = "Simple"
    }
)  
{
    int intAttr = 0 (
        doc = "An integer attribute with fallback value of 0."
    )
    rel target (
        doc = """A relationship called target that could point to another prim or a property"""
    )
}
然后再執行
usdGenSchema schema.usda
即可運行USD的代碼生成工具usdGenSchema生成SimplePrim類的源碼了,SimplePrim就是一個自定義的Schema類。
API Schema的自定義方式和Schema幾乎相同,在這里就跳過了。
我們再來看看MFn的自定義方式。要寫一個MFn就沒那么容易了,Maya的底層非常靈活且復雜,還沒有提供代碼生成器,你也不能直接編寫MFn類,必須先寫一個MPxCommand,再通過MFnPlugin把這個命令注冊到Maya中,開發者需要對Maya底層架構有足夠的了解才能寫MFn,這是非常繁瑣專業的工作。具體例子可以參考:helloCmd
由此可見,雖然在開發靈活性上MFn要優于USD,要比開發效率和容易程度,還是USD的Schema勝出。
精力有限,Schema、API Schema及MFn的對比就到這里吧,希望這篇文章能幫助到對Maya開發、USD開發有興趣的小伙伴們。
總結
以上是生活随笔為你收集整理的Schema、API Schema与MFn的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 加速度传感器检测物体倾角的原理
- 下一篇: 缓慢的http拒绝服务攻击 tomcat
