blender入門及案例(Blender修改器開發入門)
2023-04-14 19:07:57 1
在Blender中,修改器(Modifier)是動態應用於網格的程序幾何效果,可實現靈活的非破壞性工作流程。這是為 Blender 2.80 添加新修改器的編程指南。
自定義修改器不能用 python 編寫,因此本指南將展示 Blender 的 C 代碼的哪些部分必須修改。
1、Blender源碼構建由於我們要修改 Blender 的核心,首先需要從原始碼構建 Blender。這個過程在 Blender 的 Wiki: Building Blender中有詳細記錄。我將假設你遵循了有關目錄名稱的這些說明。
在實際開始修改代碼之前,建議創建一個分支以將我們的更改與上遊開發隔離。例如讓我們稱之為pizza-modifier:
/../blender-git/blender $ git checkout -b pizza-modifier
在這篇文章中,我們將添加一個「Pizza」修改器。我不知道它可以做什麼,但至少我們肯定不會被源庫中其他出現的「pizza」這個詞弄糊塗。
2、Pizza修改器概述那麼,我們需要改變什麼?為什麼我們需要更改這麼多文件?顯然,我們至少必須對修改器本身的行為進行編碼。但我們還必須確保它在 UI 中列出,可以通過 Python API 訪問,並且它的參數保存在Blender文件中。最後一點是使用 Blender 架構核心的 DNA/RNA 機制實現的。
我們的大部分更改位於/../blender-git/blender/source/blender/modifiers/目錄。
3、Blender核心修改器為Blender創建修改器意味著定義一個ModifierTypeInfo類型的全局變量。然後我們將它註冊到全局修改器列表中。為了匹配編碼風格並與現有宏很好地配合,此變量必須被命名為modifierType_Pizza,其中「Pizza」是你的實際修改器名稱的首字母大寫形式。
3.1 修改器類型信息修改器類型信息變量通常在/../blender-git/blender/source/blender/modifiers/intern 文件夾中MOD_pizza.c文件中定義, 因此,創建此文件並將其添加到要在父目錄CMakeLists.txt 中的構建列表中,連同以 intern/MOD_開頭的所有其他行。
至少,你的MOD_pizza.c文件應當包含:
#include "BKE_modifier.h"ModifierTypeInfo modifierType_Pizza = { /* name */ "Pizza", /* StructName */ "PizzaModifierData", /* structSize */ sizeof(PizzaModifierData), /* type */ eModifierTypeType_None, /* flags */ 0, /* copyData */ NULL, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* applyModifier */ NULL, /* initData */ NULL, /* requiredDataMask */ NULL, /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL,};
結構ModifierTypeInfo定義在source/blender/blenkernel/BKE_modifier.h 文件中,在我寫這篇文章時的第 139 行,即使用 Blender 2.80 RC時。不同欄位的含義在這個頭文件中有很好的解釋,所以你一定要看看。
我將專注於一些基本欄位,而將其他領域留給你探索,因為根據你的修改器要實現的任務,並不一定需要所有這些欄位。
3.2 類型和標誌要設置的第一個欄位(在名稱之後)是修改器的類型,type 欄位。 這是在BKE_modifier.h的開頭定義的枚舉類型,因此再次查看選項以找到最適合你的修改器的匹配項。如果不確定,可以嘗試查看MOD_something.c 文件中具有類似行為的現有修改器。
另一個重要欄位是flags 。 同樣是一個在BKE_modifier.h中定義的枚舉。很可能你會用eModifierTypeFlag_AcceptsMesh來告訴 Blender 你的修改器可以處理網格數據。可以使用邏輯或運算符( |) 設置多個標誌。
3.3 應用修改器修改器的核心是applyModifier 函數中實現的功能。在定義修改器類型信息變量之前,定義一個函數,如:
#include "DNA_mesh_types.h"static Mesh *pizza_applyModifier(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct Mesh *mesh){ return mesh;}
並將applyModifier欄位設置為pizza_applyModifier ,或者你為上述函數提供的任何名稱。此功能將是修改器進行所有處理的地方。這完全取決於你自己,返回的網格可以是使用source/blender/blenkernel/BKE_mesh.h中的函數創建的新網格,請參見附錄中的示例。
3.4 其他欄位對於某些欄位,可以使用定義在BKE_modifier.h 中的工具方法。例如,可以設置copyData為modifier_copyData_generic 。
4、DNA和RNAModifierTypeInfo 中有兩個非常重要的欄位我還沒有提到:structName和structSize。它們指向的PizzaModifierData結構將成為我們修改器的DNA。
DNA 是.blend文件保存在磁碟上的內容。它必須包含所有保存的參數。按照生物學的比喻,每個 DNA 都與一個 RNA 結構相關聯。這個僅在運行時使用,用於編輯、傳輸、撤消、重做等與修改器相關的數據。
4.1 DNABlender 中使用的所有 DNA 結構都在source/blender/makesdna/目錄中定義。修改器定義在DNA_modifier_types.h 文件中。
首先要修改的是:添加eModifierType_Pizza到ModifierType文件開頭的枚舉中,就放在NUM_MODIFIER_TYPES 前面。 這個枚舉不能重新排序,因為枚舉值是保存在混合文件中的,所以它會破壞向後兼容性。這也是明確說明枚舉值的原因。
在文件末尾,我們為修改器添加 DNA 結構。它的第一個欄位必須是 type ModifierData。它是一種繼承機制,可以將指向結構的指針用作更通用的ModifierData*。
typedef struct PizzaModifierData { ModifierData modifier; int num_olives; int _pad0;} PizzaModifierData;
在這個例子中,我們的修改器有一個整型參數num_olives。
另一個要求是填充結構以使其整體大小為 8 字節的倍數。如果不是自然情況,請添加額外的_pad 前綴的欄位以達到 8 的倍數。
請注意,整個文件是在構建 Blender 之前通過執行特殊程序makesdna處理的,因此這裡不能使用花哨的東西或預處理器宏。
注意:由於我們在修改器類型信息中指向的是 DNA 結構,因此必須將DNA_modifier_types.h 其包含在MOD_pizza.c文件中。
4.2 RNARNA 機制位於source/blender/makesrna/ 目錄中。與 DNA 類似,intern中的文件在Blender構建之前由一個名為makesrna 的定製程序處理, 這使我們免於執行一些關於 DNA/RNA 轉換的非常重複的任務。
修改器的 RNA 定義在 makesrna/intern/rna_modifier.c 文件中。除非你用 DNA 製作高級的東西,否則你將主要需要編寫一個類似於所有其他已經存在的簡單函數 rna_def_modifier_pizza ,把這個函數添到 void RNA_def_modifier(BlenderRNA *brna) 之前:
static void rna_def_modifier_pizza(BlenderRNA *brna){ StructRNA *srna; PropertyRNA *prop; // Define the RNA and bind it to the PizzaModifierData DNA struct srna = RNA_def_struct(brna, "PizzaModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Pizza Modifier", ""); RNA_def_struct_sdna(srna, "PizzaModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_ARRAY); // There will be such a block for each data field of PizzaModifierData prop = RNA_def_property(srna, "num_olives", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, 100); RNA_def_property_ui_range(prop, 0, 100, 1, -1); RNA_def_property_ui_text(prop, "Olives", "The number of olives on the pizza"); RNA_def_property_update(prop, 0, "rna_Modifier_update");}
注意:您可以為您的 RNA 選擇自定義圖標,而不是ICON_MOD_ARRAY我在此處選擇的圖標。
在 RNA_def_modifier的最後,添加對我們剛剛定義的rna_def_modifier_pizza(brna)函數的調用。
4.3 修改器類型枚舉由於修改了ModifierType枚舉的 DNA,我們還需要編輯它的 RNA。為此,請在相應rna_modifier.c部分的開頭為rna_enum_object_modifier_type_items添加一個條目。節標題是{0, "", 0, N_("Modify"), ""}類型的行。它們與添加新修改器時顯示在 UI 中的下拉菜單直接相關。第二個參數是用於繪製 UI 的 Python 函數的名稱,見下文。
我們還必須編輯要在/* Default */之前添加的rna_Modifier_refine 函數:
case eModifierType_Pizza: return &RNA_PizzaModifier;
注意:變量RNA_PizzaModifier不需要我們自己定義,它會由makesrna生成。
因此,我們完成了與 DNA/RNA 相關的更改。你可能對修改器參數有一些更高級的需求。如果是這樣,請隨意查看其他修改器如何處理特殊情況,它們都定義在同一個文件中。
注意:有關 RNA 的更多詳細信息,可以查看此存檔。
5、用戶界面修改器的用戶界面在 Python 腳本中定義:release/scripts/startup/bl_ui/properties_data_modifier.py.
向DATA_PT_modifiers類添加繪圖方法def PIZZA(self, layout, ob, md):,類似於其他修改器已經存在的功能。函數的名稱必須與上面rna_enum_object_modifier_type_items( rna_modifier.c)中定義的條目匹配。例如:
# in class DATA_PT_modifiersdef PIZZA(self, layout, ob, md): layout.prop(md, "num_olives")
注意:構建時,請確保將此 python 文件複製到2.80/scripts/startup/bl_ui目錄中。可能需要手動複製它。
6、最後的步驟我們的修改器有一個核心,通過 DNA 存儲在Blender文件中並通過 RNA 傳輸,但我們仍然需要在其他地方註冊它。
6.1 修改器表修改器的類型信息需要在全局修改器表中註冊。這是通過在modifier_type_init原型之前的source/blender/modifiers/MOD_modifiertypes.h末尾添加以下行來完成的:
extern ModifierTypeInfo modifierType_Pizza;
在source/blender/modifiers/intern/MOD_util.c 中,#undef INIT_TYPE 之前:
INIT_TYPE(Pizza);
6.2 大綱大綱是 UI 空間,可以列出有關當前打開的Blender文件的所有技術細節。因此它必須知道所有的修改器,包括我們新的 Pizza 修飾符。在 source/blender/editors/space_outliner/outliner_draw.c 中編輯tree_element_get_icon函數以添加適當的case eModifierType_Pizza 。 不過,我不知道為什麼它不能從 RNA 中獲取這條信息。
7、結論現在,你的修改器有了第一個骨架。從現在開始,你將能夠通過閱讀BKE_modifier.h 的注釋或其他修飾符的實現來學到很多東西。
原文連結:http://www.bimant.com/blog/custom-blender-modifier/
,