Published

16 August 2014

Tags

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 的结构有点小复杂, 需要修改的部分有点多 需要修改的部分:

  1. properties_data_modifier.py: Modifier 的 UI 界面, 接口是 SCALING
  2. DNA_modifier_types.h: 这里有两个东西需要修改
    1. 在这里添加 ModifierType 枚举类
    2. 声明和 UI 交互的数据结构
  3. RNA_access.h: 添加 StructRNA 的声明, 而定义是自动生成的
  4. rna_modifier.c: 这里有三处需要修改
    1. 这里添加的是 添加Modifier下拉列表UI 的值, 同时指向 1 和 2.a
    2. 修改rna_Modifier_refine, 这里相当于定义了从 2.a 到 3 的链接
    3. RNA_def_modifier 中创建 StructRNA, 然后由系统自动生成定义, 和 3 链接
  5. 创建 Modifier 所需的文件 MOD_xxx.c, 这个文件包含所有算法, 以及事件处理, 修改 cmakelists 加入编译列表
  6. MOD_modifiertypes.h 中声明 modifier 所需要的类型, 将会在 5 中定义
  7. MOD_util.c 创建 INIT_TYPE, 相当于从 2.a 到 6 的链接

这是一个简易的关系图:

具体代码解析:

  1. 首先是编写 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

  2. DNA_modifier_types.h: 修改两处
    1. 在 ModifierType 枚举类中创建 eModifierType_Scaling, 这是 blender 最顶层能够访问到的元素

      typedef enum ModifierType {
          eModifierType_None = 0,
          ...
          ...
          eModifierType_Wireframe         = 48,
          eModifierType_Scaling           = 49, // 这里的编号是需要连续
          NUM_MODIFIER_TYPES
      } ModifierType;
    2. 创建 struct ScalingModifierData, 这个 struct 会在两处用到, 一个是生成 RNA_ScalingModifier, 第二个是在 MOD_scaling.c 中用到

      typedef struct ScalingModifierData {
          ModifierData modifier;
          float scale;
          int pad; // blender 为了保证兼容性的 8 byte 对齐
      } ScalingModifierData;
  3. RNA_access.h: 声明 RNA_ScalingModifier, 实际定义由在 4.c 步骤生成

    extern StructRNA RNA_ScalingModifier;
  4. rna_modifier.c, 修改三处

    1. 在这里可以喊道各种被分类好了的 Modifier, 找到对应的位置插入以下代码:

      EnumPropertyItem modifier_type_items[] = {
          ...
          {0, "", 0, N_("Deform"), ""},
          ...
          {eModifierType_Scaling, "SCALING", ICON_MAN_SCALE, "Scaling the mesh", ""},
          ...
      };

      这一步同时让系统知道 eModifierType_Scaling 对应了 python 中的哪个函数来绘制 UI

    2. 在函数体 rna_Modifier_refine 中添加对应代码:

      static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
      {
          ...
          switch (md->type) {
              ...
              case eModifierType_Scaling:
                  return &RNA_ScalingModifier;
          ...
      }

      这里让系统得知 eModifierType_Scaling 对应的 RNA

    3. 定义 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);
      }
  5. 创建对应文件, 修改对应文件夹下的 cmakelists

    set(SRC
        ...
        intern/MOD_scaling.c
        ...
    )
  6. MOD_modifiertypes.h: 添加 ModifierTypeInfo 的声明

    extern ModifierTypeInfo modifierType_Scaling;
  7. MOD_util.c: 让 blender 能够通过 eModifierType_Scaling 获取 ModifierTypeInfo

    #define INIT_TYPE(typeName) (types[eModifierType_##typeName] = &modifierType_##typeName)
    ...
        INIT_TYPE(Scaling);
    #undef INIT_TYPE
  8. 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,
    };

patch 文件

  • RNA_access.h: 各种 StructRNA 声明的地方
  • BKE_modifier.h: 关于 ModifierTypeInfo 的定义


blog comments powered by Disqus