From BlenderWiki

Jump to: navigation, search

[edit] Overview

[edit] ModifierTypeInfo

The modifier stack accesses modifiers through a standard interface. The interface for each modifier is stored as a set of callback function pointers in a ModifierTypeInfo structure (defined in BKE_modifier.h). There is a static array of these structures (one for each modifier type) accessible through the modifierType_getInfo function defined in modifier.c.

[edit] ModifierData

The data for a specific instance of a certain modifier type is stored in a <type>ModifierData structure (e.g. MirrorModifierData for the Mirror modifier), defined in DNA_modifier_types.h. Each <type>ModifierData structure must include, as its first field, a ModifierData structure which contains a type identifier. This type identifier is passed to the modifierType_getInfo function to retrieve a ModifierTypeInfo structure describing the modifier type. Since the ModifierData structure is the first field, any <type>ModifierData pointer can be cast to a ModifierData pointer and used to directly retrieve the type identifier.

[edit] Required vs. Optional functions

Some callback functions in ModifierTypeInfo are required, others are optional (these should be set to NULL if not implemented). Additionally, modifiers can be classified as either deforming or non-deforming, which affects which callback functions they are required to implement.

[edit] Adding a modifier type

To add a modifier type, the following things must be done (where <type> is the one-word name of the modifier):

  • Add an eModifierType_<type> entry at the end of the ModifierType enum in DNA_modifier_types.h (just before NUM_MODIFIER_TYPES - the position is important to make sure all the other type values stay the same)
  • Add a <type>ModifierData structure definition to DNA_modifier_types.h (following the example of the existing structures and the guidelines in BlenderDev/DNAStructs)
  • Add function definitions to modifier.c. The current convention is to name them <type>Modifier_<functionName>, where <type> is spelt starting with a lowercase letter (e.g. curveModifier_deformVerts).
  • Add a section to the modifierType_getInfo function in modifier.c initialising the ModifierTypeInfo structure for the new modifier (using the INIT_TYPE macro and following the example of the existing sections)
  • Add else if(md->type==eModifierType_<type>) sections to the draw_modifier function in buttons_editing.c, following the example of the existing sections. There are two places to add else if(...) sections; one determines the height of the modifier panel, and the other draws the modifier panel.

[edit] Required functions

[edit] All Modifiers

[edit] copyData

void copyData(ModifierData *md, ModifierData *target)
Copy instance data for this modifier type. Should copy all user level settings to the target modifier.

[edit] Deforming modifiers

[edit] deformVerts

void deformVerts(ModifierData *md, struct Object *ob,
                 struct DerivedMesh *derivedData, float (*vertexCos)[3],
                 int numVerts)
Should apply the deformation to the given vertex array.
  • If the deformer requires information from the object it can obtain it from the derivedData argument if non-NULL, and otherwise the ob argument. The derivedData argument should not be changed.

[edit] deformVertsEM

void deformVertsEM(ModifierData *md, struct Object *ob,
                   struct EditMesh *editData, struct DerivedMesh *derivedData,
                   float (*vertexCos)[3], int numVerts)
Like deformVerts but called during editmode (for modifiers which support editmode).

[edit] Non-deforming modifiers

[edit] applyModifier

DerivedMesh *applyModifier(ModifierData *md, struct Object *ob,
                           struct DerivedMesh *derivedData,
                           int useRenderParams, int isFinalCalc)
Should apply the modifier and return a DerivedMesh object (type is dependent on object type).
  • The derivedData argument will always be non-NULL; the modifier should read the mesh data from derivedData instead of the actual object data.
  • The useRenderParams argument indicates if the modifier is being applied in the service of the renderer (which may alter quality settings).
  • The isFinalCalc parameter indicates if the modifier is being calculated for a final result or for something temporary (like orcos). This is a hack at the moment, it is meant so subsurf can know if it is safe to reuse its internal cache.
  • The modifier may reuse the derivedData argument (i.e. return it in modified form), but must not release it.

[edit] applyModifierEM

DerivedMesh *applyModifierEM(ModifierData *md, struct Object *ob,
                             struct EditMesh *editData, struct DerivedMesh *derivedData)
Like applyModifier but called during editmode (for modifiers which support editmode).
  • The DerivedMesh that is returned must support the operations that are expected from editmode objects. The same qualifications regarding derivedData apply as for applyModifier.

[edit] Optional functions

[edit] All Modifiers

[edit] initData

void initData(ModifierData *md)
Initialize new instance data for this modifier type. This function should set modifier variables to their default values.

[edit] freeData

void freeData(ModifierData *md)
Should free internal modifier data variables. This function should not free the md variable itself.

[edit] requiredDataMask

CustomDataMask requiredDataMask(struct ModifierData *md)
Should return a CustomDataMask indicating what data this modifier needs. If (mask & (1 << (layer type))) != 0, this modifier needs that custom data layer. This function's return value can change depending on the modifier's settings.
  • Note that this means extra data (e.g. vertex groups) - it is assumed that all modifiers need mesh data and deform modifiers need vertex coordinates.
  • If this function is not present or it returns 0, it is assumed that no extra data is needed.

[edit] isDisabled

int isDisabled(ModifierData *md)
Should return a boolean value indicating if this modifier is able to be calculated based on the modifier data. This is *not* regarding md->flag (that is tested by the system); this just tests if the data validates (for example, a lattice will return false if the lattice object is not defined). If this function is not present, the modifier is assumed to never be disabled.

[edit] updateDepgraph

void updateDepgraph(ModifierData *md, struct DagForest *forest,
                    struct Object *ob, struct DagNode *obNode)
Should add the appropriate relations to the dependancy graph depending on the modifier data. These relations are used by Blender to determine when the modifier stack needs to be re-evaluated.

[edit] dependsOnTime

int dependsOnTime(ModifierData *md)
Should return true if the modifier needs to be recalculated on time changes. This function is assumed to return false if not present.

[edit] foreachObjectLink

void foreachObjectLink(ModifierData *md, struct Object *ob,
                       ObjectWalkFunc walk, void *userData)
Should call the given walk function with a pointer to each Object pointer that the modifier data stores. This is used for unlinking objects or forwarding object references, and for linking on file load if foreachIDLink is not present.
  • If a modifier stores Object pointers, it should probably implement this function.

[edit] foreachIDLink

void foreachIDLink(ModifierData *md, struct Object *ob,
                   IDWalkFunc walk, void *userData)
Should call the given walk function with a pointer to each ID pointer (i.e. each datablock pointer) that the modifier data stores. This is used for linking on file load and for unlinking datablocks or forwarding datablock references.
  • If this function is not present and foreachObjectLink is, foreachObjectLink will be used.
  • If a modifier stores datablock pointers (including Object pointers), it should probably implement this function.

[edit] Enumerations

[edit] ModifierTypeType

[edit] eModifierTypeType_None

Should not be used, only for None modifier type

[edit] eModifierTypeType_OnlyDeform

Modifier only does deformation, implies that modifier type should have a valid deformVerts function. OnlyDeform style modifiers implicitly accept either mesh or CV input but should still declare flags appropriately.

[edit] eModifierTypeType_Constructive

[edit] eModifierTypeType_Nonconstructive

[edit] ModifierTypeFlag

[edit] eModifierTypeFlag_AcceptsMesh

[edit] eModifierTypeFlag_AcceptsCVs

[edit] eModifierTypeFlag_SupportsMapping

[edit] eModifierTypeFlag_SupportsEditmode

[edit] eModifierTypeFlag_EnableInEditmode

For modifiers that support editmode this determines if the modifier should be enabled by default in editmode. This should only be used by modifiers that are relatively speedy and also generally used in editmode, otherwise let the user enable it by hand.

[edit] eModifierTypeFlag_RequiresOriginalData

For modifiers that require original data and so cannot be placed after any non-deformative modifier.


[edit] Data types

[edit] ObjectWalkFunc

typedef void (*ObjectWalkFunc)(void *userData, Object *ob, Object **obpoin)
A pointer to a function to be called on each object pointer in the modifier data; passed to forEachObjectLink

[edit] IDWalkFunc

typedef void (*IDWalkFunc)(void *userData, Object *ob, ID **idpoin)
A pointer to a function to be called on each ID pointer in the modifier data; passed to forEachIDLink