Blender 源码学习 --- Modifier
Published
Contents
reference: * http://wiki.blender.org/index.php/User:Enjalot/Creating_a_custom_modifier * http://wiki.blender.org/index.php/User:Apinzonf/Dev:Doc/Tutorial_Modifier
Blender Modifier 的结构有点小复杂, 需要修改的部分有点多 需要修改的部分:
properties_data_modifier.py
: Modifier 的 UI 界面, 接口是 SCALINGDNA_modifier_types.h
: 这里有两个东西需要修改- 在这里添加
ModifierType
枚举类 - 声明和 UI 交互的数据结构
- 在这里添加
RNA_access.h
: 添加 StructRNA 的声明, 而定义是自动生成的rna_modifier.c
: 这里有三处需要修改- 这里添加的是 添加Modifier下拉列表UI 的值, 同时指向 1 和 2.a
- 修改
rna_Modifier_refine
, 这里相当于定义了从 2.a 到 3 的链接 - 在
RNA_def_modifier
中创建StructRNA
, 然后由系统自动生成定义, 和 3 链接
- 创建 Modifier 所需的文件
MOD_xxx.c
, 这个文件包含所有算法, 以及事件处理, 修改 cmakelists 加入编译列表 - 在
MOD_modifiertypes.h
中声明 modifier 所需要的类型, 将会在 5 中定义 - 在
MOD_util.c
创建INIT_TYPE
, 相当于从 2.a 到 6 的链接
这是一个简易的关系图:
具体代码解析:
首先是编写 UI, 我们在
properties_data_modifier.py
添加这么行代码:class DATA_PT_modifiers(ModifierButtonsPanel, Panel): ... def SCALING(self, layout, ob, md): layout.prop(md, "scaleui") ...
SCALING
这个函数是有意义的, 在第 4.a 步会出现, 同时这里的md
就是我们在第 4.c 步创建的RNA_ScalingModifier
DNA_modifier_types.h
: 修改两处在 ModifierType 枚举类中创建
eModifierType_Scaling
, 这是 blender 最顶层能够访问到的元素typedef enum ModifierType { eModifierType_None = 0, ... ... eModifierType_Wireframe = 48, eModifierType_Scaling = 49, // 这里的编号是需要连续 NUM_MODIFIER_TYPES } ModifierType;
创建
struct ScalingModifierData
, 这个 struct 会在两处用到, 一个是生成RNA_ScalingModifier
, 第二个是在MOD_scaling.c
中用到typedef struct ScalingModifierData { ModifierData modifier; float scale; int pad; // blender 为了保证兼容性的 8 byte 对齐 } ScalingModifierData;
RNA_access.h
: 声明RNA_ScalingModifier
, 实际定义由在 4.c 步骤生成extern StructRNA RNA_ScalingModifier;
rna_modifier.c
, 修改三处在这里可以喊道各种被分类好了的 Modifier, 找到对应的位置插入以下代码:
EnumPropertyItem modifier_type_items[] = { ... {0, "", 0, N_("Deform"), ""}, ... {eModifierType_Scaling, "SCALING", ICON_MAN_SCALE, "Scaling the mesh", ""}, ... };
这一步同时让系统知道
eModifierType_Scaling
对应了 python 中的哪个函数来绘制 UI在函数体
rna_Modifier_refine
中添加对应代码:static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) { ... switch (md->type) { ... case eModifierType_Scaling: return &RNA_ScalingModifier; ... }
这里让系统得知
eModifierType_Scaling
对应的 RNA定义 RNA
static void rna_def_modifier_scaling(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; srna = RNA_def_struct(brna, "ScalingModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Scaling Modifier", "Scaling effect modifier"); RNA_def_struct_sdna(srna, "ScalingModifierData"); RNA_def_struct_ui_icon(srna, ICON_MAN_SCALE); /* scaleui: name for "properties_data_modifier.py"*/ prop = RNA_def_property(srna, "scaleui", PROP_FLOAT, PROP_NONE); /*scale: name for "DNA_modifier_types.h"*/ RNA_def_property_float_sdna(prop, NULL, "scale"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_range(prop, -100, 100, 1, 3); RNA_def_property_ui_text(prop, "Scale", "Scale factor"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); } ...... void RNA_def_modifier(BlenderRNA *brna) { ... rna_def_modifier_remesh(brna); rna_def_modifier_skin(brna); rna_def_modifier_scaling(brna); }
创建对应文件, 修改对应文件夹下的 cmakelists
set(SRC ... intern/MOD_scaling.c ... )
MOD_modifiertypes.h
: 添加ModifierTypeInfo
的声明extern ModifierTypeInfo modifierType_Scaling;
MOD_util.c
: 让 blender 能够通过eModifierType_Scaling
获取ModifierTypeInfo
#define INIT_TYPE(typeName) (types[eModifierType_##typeName] = &modifierType_##typeName) ... INIT_TYPE(Scaling); #undef INIT_TYPE
MOD_util.c
核心代码部分, 关于ModifierTypeInfo
的定义可以在BKE_modifier.h
中看到非常详细的定义/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. * All rights reserved. * * Contributor(s): Your name * * ***** END GPL LICENSE BLOCK ***** * */ /** \file blender/modifiers/intern/MOD_scaling.c * \ingroup modifiers */ #include "DNA_meshdata_types.h" #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_string.h" #include "MEM_guardedalloc.h" #include "BKE_cdderivedmesh.h" #include "BKE_particle.h" #include "BKE_deform.h" #include "MOD_modifiertypes.h" #include "MOD_util.h" static void initData(ModifierData *md) { ScalingModifierData *smd = (ScalingModifierData *) md; smd->scale = 1.0f; } static void copyData(ModifierData *md, ModifierData *target) { ScalingModifierData *smd = (ScalingModifierData *) md; ScalingModifierData *tsmd = (ScalingModifierData *) target; tsmd->scale = smd->scale; } static int isDisabled(ModifierData *md, int UNUSED(useRenderParams)) { ScalingModifierData *smd = (ScalingModifierData *) md; /* disable if modifier is 1.0 for scale*/ if (smd->scale == 1.0f) return 1; return 0; } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) { ScalingModifierData *smd = (ScalingModifierData *)md; CustomDataMask dataMask = 0; return dataMask; } static void ScalingModifier_do( ScalingModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { int i; float scale; scale = smd->scale; for (i = 0; i < numVerts; i++) { vertexCos[i][0] = vertexCos[i][0] * scale; vertexCos[i][1] = vertexCos[i][1] * scale; vertexCos[i][2] = vertexCos[i][2] * scale; } } static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag)) { DerivedMesh *dm = get_dm(ob, NULL, derivedData, NULL, 0); ScalingModifier_do((ScalingModifierData *)md, ob, dm, vertexCos, numVerts); if (dm != derivedData) dm->release(dm); } static void deformVertsEM( ModifierData *md, Object *ob, struct BMEditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, 0); ScalingModifier_do((ScalingModifierData *)md, ob, dm, vertexCos, numVerts); if (dm != derivedData) dm->release(dm); } ModifierTypeInfo modifierType_Scaling = { /* name */ "Scaling", /* structName */ "ScalingModifierData", /* structSize */ sizeof(ScalingModifierData), /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* applyModifier */ NULL, /* applyModifierEM */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, };
乱
RNA_access.h
: 各种 StructRNA 声明的地方BKE_modifier.h
: 关于ModifierTypeInfo
的定义
blog comments powered by Disqus