tornavis/source/blender/blenkernel/BKE_modifier.hh

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

616 lines
22 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
*/
#include "BLI_compiler_attrs.h"
#include "BLI_function_ref.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_span.hh"
#include "DNA_modifier_types.h" /* Needed for all enum type definitions. */
#include "DNA_customdata_types.h"
namespace blender::bke {
struct GeometrySet;
}
struct ARegionType;
struct bArmature;
struct BMEditMesh;
2020-09-30 03:51:13 +02:00
struct BlendDataReader;
struct BlendWriter;
struct CustomData_MeshMasks;
struct DepsNodeHandle;
struct Depsgraph;
struct ID;
struct ListBase;
struct Main;
struct Mesh;
struct ModifierData;
struct Object;
struct Scene;
struct StructRNA;
struct IDCacheKey;
enum class ModifierTypeType {
/* Should not be used, only for None modifier type */
None,
2020-06-17 06:00:09 +02:00
/**
* Modifier only does deformation, implies that modifier
* type should have a valid deform_verts function. OnlyDeform
* style modifiers implicitly accept either mesh or CV
* input but should still declare flags appropriately.
*/
OnlyDeform,
2020-06-17 06:00:09 +02:00
/** Modifier adds geometry. */
Constructive,
/* Modifier can add and remove geometry. */
Nonconstructive,
2020-06-17 06:00:09 +02:00
/**
* Both deform_verts & applyModifier are valid calls
* used for particles modifier that doesn't actually modify the object
* unless it's a mesh and can be exploded -> curve can also emit particles
*/
DeformOrConstruct,
2020-06-17 06:00:09 +02:00
/**
* Like Nonconstructive, but does not affect the geometry
* of the object, rather some of its CustomData layers.
* E.g. UVProject and WeightVG modifiers. */
NonGeometrical,
};
enum ModifierTypeFlag {
eModifierTypeFlag_AcceptsMesh = (1 << 0),
eModifierTypeFlag_AcceptsCVs = (1 << 1),
/**
* Modifiers that enable this flag can have the modifiers "On Cage" option toggled,
* see: #eModifierMode_OnCage, where the output of the modifier can be selected directly.
* In some cases the cage geometry use read to tool code as well (loop-cut & knife are examples).
*
* When set, geometry from the resulting mesh can be mapped back to the original indices
* via #CD_ORIGINDEX.
*
* While many modifiers using this flag preserve the order of geometry arrays,
* this isn't always the case, this flag doesn't imply #ModifierTypeType::OnlyDeform.
* Geometry from the original mesh may be removed from the resulting mesh or new geometry
* may be added (where the #CD_ORIGINDEX value will be #ORIGINDEX_NONE).
*
* Modifiers that create entirely new geometry from the input should not enable this flag
* because none of the geometry will be selectable when "On Cage" is enabled.
*/
eModifierTypeFlag_SupportsMapping = (1 << 2),
eModifierTypeFlag_SupportsEditmode = (1 << 3),
2020-06-17 06:00:09 +02:00
/**
* 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.
*/
eModifierTypeFlag_EnableInEditmode = (1 << 4),
2020-06-17 06:00:09 +02:00
/**
* For modifiers that require original data and so cannot
* be placed after any non-deforming modifier.
*/
eModifierTypeFlag_RequiresOriginalData = (1 << 5),
2020-06-17 06:00:09 +02:00
/**
* For modifiers that support point-cache,
2020-06-17 06:00:09 +02:00
* so we can check to see if it has files we need to deal with.
*/
eModifierTypeFlag_UsesPointCache = (1 << 6),
2020-06-17 06:00:09 +02:00
/** For physics modifiers, max one per type */
eModifierTypeFlag_Single = (1 << 7),
2020-06-17 06:00:09 +02:00
/** Some modifier can't be added manually by user */
eModifierTypeFlag_NoUserAdd = (1 << 8),
eModifierTypeFlag_AcceptsVertexCosOnly = (1 << 10),
/** Accepts #BMesh input (without conversion). */
eModifierTypeFlag_AcceptsBMesh = (1 << 11),
/** Accepts #GreasePencil data input. */
eModifierTypeFlag_AcceptsGreasePencil = (1 << 12),
};
ENUM_OPERATORS(ModifierTypeFlag, eModifierTypeFlag_AcceptsGreasePencil)
using IDWalkFunc = void (*)(void *user_data, Object *ob, ID **idpoin, int cb_flag);
using TexWalkFunc = void (*)(void *user_data, Object *ob, ModifierData *md, const char *propname);
enum ModifierApplyFlag {
2019-04-18 07:21:26 +02:00
/** Render time. */
MOD_APPLY_RENDER = 1 << 0,
/** Result of evaluation will be cached, so modifier might
2022-05-03 07:11:27 +02:00
* want to cache data for quick updates (used by subdivision-surface) */
2019-04-18 07:21:26 +02:00
MOD_APPLY_USECACHE = 1 << 1,
/** Modifier evaluated for undeformed texture coordinates */
MOD_APPLY_ORCO = 1 << 2,
/** Ignore scene simplification flag and use subdivisions
* level set in multires modifier. */
MOD_APPLY_IGNORE_SIMPLIFY = 1 << 3,
/** The effect of this modifier will be applied to the base mesh
* The modifier itself will be removed from the modifier stack.
* This flag can be checked to ignore rendering display data to the mesh.
* See `OBJECT_OT_modifier_apply` operator. */
MOD_APPLY_TO_BASE_MESH = 1 << 4,
};
2022-10-06 03:51:05 +02:00
ENUM_OPERATORS(ModifierApplyFlag, MOD_APPLY_TO_BASE_MESH);
struct ModifierUpdateDepsgraphContext {
Scene *scene;
Object *object;
DepsNodeHandle *node;
};
/* Contains the information for deformXXX and applyXXX functions below that
* doesn't change between consecutive modifiers. */
struct ModifierEvalContext {
Depsgraph *depsgraph;
Object *object;
ModifierApplyFlag flag;
};
struct ModifierTypeInfo {
/* A unique identifier for this modifier. Used to generate the panel id type name.
* See #BKE_modifier_type_panel_id. */
char idname[64];
/* The user visible name for this modifier */
char name[64];
/* The DNA struct name for the modifier data type, used to
* write the DNA data out.
*/
char struct_name[64];
/* The size of the modifier data type, used by allocation. */
int struct_size;
/* StructRNA of this modifier. This is typically something like RNA_*Modifier. */
StructRNA *srna;
ModifierTypeType type;
ModifierTypeFlag flags;
/* Icon of the modifier. Usually something like ICON_MOD_*. */
int icon;
/********************* Non-optional functions *********************/
2020-06-17 06:00:09 +02:00
/**
* Copy instance data for this modifier type. Should copy all user
* level settings to the target modifier.
*
2024-01-15 18:44:04 +01:00
* \param flag: Copying options (see BKE_lib_id.hh's LIB_ID_COPY_... flags for more).
*/
void (*copy_data)(const ModifierData *md, ModifierData *target, int flag);
/********************* Deform modifier functions *********************/
2020-06-17 06:00:09 +02:00
/**
* Apply a deformation to the positions in the \a positions array. If the \a mesh argument is
* non-null, if will contain proper (not wrapped) mesh data. The \a positions array may or may
* not be the same as the mesh's position attribute.
*/
void (*deform_verts)(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions);
2020-06-17 06:00:09 +02:00
/**
* Like deform_matrices_EM but called from object mode (for supporting modifiers in sculpt mode).
2020-06-17 06:00:09 +02:00
*/
void (*deform_matrices)(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions,
blender::MutableSpan<blender::float3x3> matrices);
2020-06-17 06:00:09 +02:00
/**
* Like deform_verts but called during edit-mode if supported. The \a mesh argument might be a
* wrapper around edit BMesh data.
*/
void (*deform_verts_EM)(ModifierData *md,
const ModifierEvalContext *ctx,
BMEditMesh *em,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions);
2020-07-01 05:12:24 +02:00
/* Set deform matrix per vertex for crazy-space correction */
void (*deform_matrices_EM)(ModifierData *md,
const ModifierEvalContext *ctx,
BMEditMesh *em,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions,
blender::MutableSpan<blender::float3x3> matrices);
/********************* Non-deform modifier functions *********************/
2020-06-17 06:00:09 +02:00
/**
* For non-deform types: apply the modifier and return a mesh data-block.
*
* The mesh argument should always be non-NULL; the modifier should use the
2020-06-05 06:34:00 +02:00
* passed in mesh data-block rather than object->data, as it contains the mesh
* with modifier applied up to this point.
*
* The modifier may modify and return the mesh argument, but must not free it
* and must ensure any referenced data layers are converted to non-referenced
* before modification.
*/
Mesh *(*modify_mesh)(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh);
/**
* The modifier has to change the geometry set in-place. The geometry set can contain zero or
* more geometry components. This callback can be used by modifiers that don't work on any
* specific type of geometry (e.g. mesh).
*/
void (*modify_geometry_set)(ModifierData *md,
const ModifierEvalContext *ctx,
2023-11-14 09:30:40 +01:00
blender::bke::GeometrySet *geometry_set);
/********************* Optional functions *********************/
2020-06-17 06:00:09 +02:00
/**
* Initialize new instance data for this modifier type, this function
* should set modifier variables to their default values.
2018-06-17 17:05:51 +02:00
*
* This function is optional.
*/
void (*init_data)(ModifierData *md);
2020-06-17 06:00:09 +02:00
/**
* Should add to passed \a r_cddata_masks the data types that this
* modifier needs. If (mask & (1 << (layer type))) != 0, this modifier
* needs that custom data layer. It can change required layers
* 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, it is assumed that no extra data is needed.
*
* This function is optional.
*/
void (*required_data_mask)(ModifierData *md, CustomData_MeshMasks *r_cddata_masks);
2020-06-17 06:00:09 +02:00
/**
* Free internal modifier data variables, this function should
* not free the md variable itself.
*
* This function is responsible for freeing the runtime data as well.
*
* This function is optional.
*/
void (*free_data)(ModifierData *md);
2020-06-17 06:00:09 +02:00
/**
* Return a boolean value indicating if this modifier is able to be
* calculated based on the modifier data. This is *not* regarding the
* md->flag, that is tested by the system, this is just if the data
* validates (for example, a lattice will return false if the lattice
* object is not defined).
*
* This function is optional (assumes never disabled if not present).
*/
bool (*is_disabled)(const Scene *scene, ModifierData *md, bool use_render_params);
2020-06-17 06:00:09 +02:00
/**
* Add the appropriate relations to the dependency graph.
Depsgraph: New dependency graph integration commit This commit integrates the work done so far on the new dependency graph system, where goal was to replace legacy depsgraph with the new one, supporting loads of neat features like: - More granular dependency relation nature, which solves issues with fake cycles in the dependencies. - Move towards all-animatable, by better integration of drivers into the system. - Lay down some basis for upcoming copy-on-write, overrides and so on. The new system is living side-by-side with the previous one and disabled by default, so nothing will become suddenly broken. The way to enable new depsgraph is to pass `--new-depsgraph` command line argument. It's a bit early to consider the system production-ready, there are some TODOs and issues were discovered during the merge period, they'll be addressed ASAP. But it's important to merge, because it's the only way to attract artists to really start testing this system. There are number of assorted documents related on the design of the new system: * http://wiki.blender.org/index.php/User:Aligorith/GSoC2013_Depsgraph#Design_Documents * http://wiki.blender.org/index.php/User:Nazg-gul/DependencyGraph There are also some user-related information online: * http://code.blender.org/2015/02/blender-dependency-graph-branch-for-users/ * http://code.blender.org/2015/03/more-dependency-graph-tricks/ Kudos to everyone who was involved into the project: - Joshua "Aligorith" Leung -- design specification, initial code - Lukas "lukas_t" Toenne -- integrating code into blender, with further fixes - Sergey "Sergey" "Sharybin" -- some mocking around, trying to wrap up the project and so - Bassam "slikdigit" Kurdali -- stressing the new system, reporting all the issues and recording/writing documentation. - Everyone else who i forgot to mention here :)
2015-05-12 12:05:57 +02:00
*
* This function is optional.
*/
void (*update_depsgraph)(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx);
2020-06-17 06:00:09 +02:00
/**
* Should return true if the modifier needs to be recalculated on time
* changes.
*
* This function is optional (assumes false if not present).
*/
bool (*depends_on_time)(Scene *scene, ModifierData *md);
2020-06-17 06:00:09 +02:00
/**
* True when a deform modifier uses normals, the required_data_mask
* can't be used here because that refers to a normal layer whereas
* in this case we need to know if the deform modifier uses normals.
2018-06-17 17:05:51 +02:00
*
* this is needed because applying 2 deform modifiers will give the
* second modifier bogus normals.
2020-06-17 06:00:09 +02:00
*/
bool (*depends_on_normals)(ModifierData *md);
2020-06-17 06:00:09 +02:00
/**
* Should call the given walk function with a pointer to each ID
2019-06-12 01:04:10 +02:00
* pointer (i.e. each data-block pointer) that the modifier data
* stores. This is used for linking on file load and for
2019-06-12 01:04:10 +02:00
* unlinking data-blocks or forwarding data-block references.
*
* This function is optional.
- shuffled editmesh derived function name/function - added ModifierTypeInfo.freeData function - added modifier_{new,free] utility function - added ccgSubSurf_getUseAgeCounts to query info - removed subsurf modifier faking (ME_SUBSURF flag is no longer valid). subsurf modifier gets converted on file load although there is obscure linked mesh situation where this can go wrong, will fix shortly. this also means that some places in the code that test/copy subsurf settings are broken for the time being. - shuffled modifier calculation to be simpler. note that all modifiers are currently disabled in editmode (including subsurf). don't worry, will return shortly. - bug fix, build modifier didn't randomize meshes with only verts - cleaned up subsurf_ccg and adapted for future editmode modifier work - added editmesh.derived{Cage,Final}, not used yet - added SubsurfModifierData.{mCache,emCache}, will be used to cache subsurf instead of caching in derivedmesh itself - removed old subsurf buttons - added do_modifiers_buttons to handle modifier events - removed count_object counting of modifier (subsurfed) objects... this would be nice to add back at some point but requires care. probably requires rewrite of counting system. New feature: Incremental Subsurf in Object Mode The previous release introduce incremental subsurf calculation during editmode but it was not turned on during object mode. In general it does not make sense to have it always enabled during object mode because it requires caching a fair amount of information about the mesh which is a waste of memory unless the mesh is often recalculated. However, for mesh's that have subsurfed armatures for example, or that have other modifiers so that the mesh is essentially changing on every frame, it makes a lot of sense to keep the subsurf'd object around and that is what the new incremental subsurf modifier toggle is for. The intent is that the user will enable this option for (a) a mesh that is currently under active editing or (b) a mesh that is heavily updated in the scene, such as a character. I will try to write more about this feature for release, because it has advantages and disadvantages that are not immediately obvious (the first user reaction will be to turn it on for ever object, which is probably not correct).
2005-07-21 22:30:33 +02:00
*/
void (*foreach_ID_link)(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data);
2020-06-17 06:00:09 +02:00
/**
* Should call the given walk function for each texture that the
* modifier data stores. This is used for finding all textures in
* the context for the UI.
*
* This function is optional. If it is not present, it will be
* assumed the modifier has no textures.
*/
void (*foreach_tex_link)(ModifierData *md, Object *ob, TexWalkFunc walk, void *user_data);
2020-06-17 06:00:09 +02:00
/**
* Free given run-time data.
*
* This data is coming from a modifier of the corresponding type, but actual
* modifier data is not known here.
*
* Notes:
* - The data itself is to be de-allocated as well.
2019-06-12 01:04:10 +02:00
* - This callback is allowed to receive NULL pointer as a data, so it's
* more like "ensure the data is freed".
*/
void (*free_runtime_data)(void *runtime_data);
2020-06-17 06:00:09 +02:00
/** Register the panel types for the modifier's UI. */
void (*panel_register)(ARegionType *region_type);
2020-06-17 06:00:09 +02:00
/**
* Is called when the modifier is written to a file. The modifier data struct itself is written
* already.
*
* This method should write any additional arrays and referenced structs that should be
* stored in the file.
*/
void (*blend_write)(BlendWriter *writer, const ID *id_owner, const ModifierData *md);
2020-06-17 06:00:09 +02:00
/**
* Is called when the modifier is read from a file.
*
* It can be used to update pointers to arrays and other structs. Furthermore, fields that have
* not been written (e.g. runtime data) can be reset.
*/
void (*blend_read)(BlendDataReader *reader, ModifierData *md);
/**
* Iterate over all cache pointers of given modifier. Also see #IDTypeInfo::foreach_cache.
*/
void (*foreach_cache)(
Object *object,
ModifierData *md,
blender::FunctionRef<void(const IDCacheKey &cache_key, void **cache_p, uint flags)> fn);
};
/* Used to set a modifier's panel type. */
#define MODIFIER_TYPE_PANEL_PREFIX "MOD_PT_"
2021-02-05 06:23:34 +01:00
/* Initialize modifier's global data (type info and some common global storage). */
void BKE_modifier_init();
const ModifierTypeInfo *BKE_modifier_get_info(ModifierType type);
/* For modifier UI panels. */
/**
* Get the idname of the modifier type's panel, which was defined in the #panel_register callback.
*/
void BKE_modifier_type_panel_id(ModifierType type, char *r_idname);
void BKE_modifier_panel_expand(ModifierData *md);
/* Modifier utility calls, do call through type pointer and return
* default values if pointer is optional.
*/
ModifierData *BKE_modifier_new(int type);
void BKE_modifier_free_ex(ModifierData *md, int flag);
void BKE_modifier_free(ModifierData *md);
/**
* Use instead of `BLI_remlink` when the object's active modifier should change.
*/
void BKE_modifier_remove_from_list(Object *ob, ModifierData *md);
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md);
ModifierData *BKE_modifier_copy_ex(const ModifierData *md, int flag);
/**
* Callback's can use this to avoid copying every member.
*/
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag);
void BKE_modifier_copydata(const ModifierData *md, ModifierData *target);
void BKE_modifier_copydata_ex(const ModifierData *md, ModifierData *target, int flag);
bool BKE_modifier_depends_ontime(Scene *scene, ModifierData *md);
bool BKE_modifier_supports_mapping(ModifierData *md);
bool BKE_modifier_supports_cage(Scene *scene, ModifierData *md);
bool BKE_modifier_couldbe_cage(Scene *scene, ModifierData *md);
bool BKE_modifier_is_correctable_deformed(ModifierData *md);
bool BKE_modifier_is_same_topology(ModifierData *md);
bool BKE_modifier_is_non_geometrical(ModifierData *md);
/**
* Check whether is enabled.
*
* \param scene: Current scene, may be NULL,
* in which case `is_disabled` callback of the modifier is never called.
*/
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode);
/**
* Check whether given modifier is not local (i.e. from linked data) when the object is a library
* override.
*
* \param md: May be NULL, in which case we consider it as a non-local modifier case.
*/
bool BKE_modifier_is_nonlocal_in_liboverride(const Object *ob, const ModifierData *md);
/* Set modifier execution error.
* The message will be shown in the interface and will be logged as an error to the console. */
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format, ...)
ATTR_PRINTF_FORMAT(3, 4);
/* Set modifier execution warning, which does not prevent the modifier from being applied but which
* might need an attention. The message will only be shown in the interface, but will not appear in
* the logs. */
void BKE_modifier_set_warning(const Object *ob, ModifierData *md, const char *format, ...)
ATTR_PRINTF_FORMAT(3, 4);
void BKE_modifiers_foreach_ID_link(Object *ob, IDWalkFunc walk, void *user_data);
void BKE_modifiers_foreach_tex_link(Object *ob, TexWalkFunc walk, void *user_data);
ModifierData *BKE_modifiers_findby_type(const Object *ob, ModifierType type);
ModifierData *BKE_modifiers_findby_name(const Object *ob, const char *name);
Modifiers: add unique modifier identifiers This adds a new `ModifierData.persistent_uid` integer property with the following properties: * It's unique within the object. * Match between the original and evaluated object. * Stable across Blender sessions. * Stable across renames and reorderings of modifiers. Potential use-cases: * Everywhere where we currently use the name as identifier. For example, `ModifierComputeContext` and `ModifierViewerPathElem`. * Can be used as part of a key in `IDCacheKey` to support caches that stay in-tact across undo steps. * Can be stored in the `SpaceNode` to identify the modifier whose geometry node tree is currently pinned (this could use the name currently, but that hasn't been implemented yet). This new identifier has some overlap with `ModifierData.session_uid`, but there are some differences: * `session_uid` is unique within the entire Blender session (except for duplicates between the original and evaluated data blocks). * `session_uid` is not stable across Blender sessions. Especially due to the first difference, it's not immediately obvious that the new `persistent_uid` can fulfill all use-cases of the existing `session_uid`. Nevertheless, this seems likely and will be cleaned up separately. Unfortunately, there is not a single place where modifiers are added to objects currently. Therefore, there are quite a few places that need to ensure valid identifiers. I tried to catch all the places, but it's hard to be sure. Therefore, I added an assert in `object_copy_data` that checks if all identifiers are valid. This way, we should be notified relatively quickly if issues are caused by invalid identifiers. Pull Request: https://projects.blender.org/blender/blender/pulls/117347
2024-02-06 17:10:40 +01:00
ModifierData *BKE_modifiers_findby_persistent_uid(const Object *ob, int persistent_uid);
void BKE_modifiers_clear_errors(Object *ob);
Modifiers: add unique modifier identifiers This adds a new `ModifierData.persistent_uid` integer property with the following properties: * It's unique within the object. * Match between the original and evaluated object. * Stable across Blender sessions. * Stable across renames and reorderings of modifiers. Potential use-cases: * Everywhere where we currently use the name as identifier. For example, `ModifierComputeContext` and `ModifierViewerPathElem`. * Can be used as part of a key in `IDCacheKey` to support caches that stay in-tact across undo steps. * Can be stored in the `SpaceNode` to identify the modifier whose geometry node tree is currently pinned (this could use the name currently, but that hasn't been implemented yet). This new identifier has some overlap with `ModifierData.session_uid`, but there are some differences: * `session_uid` is unique within the entire Blender session (except for duplicates between the original and evaluated data blocks). * `session_uid` is not stable across Blender sessions. Especially due to the first difference, it's not immediately obvious that the new `persistent_uid` can fulfill all use-cases of the existing `session_uid`. Nevertheless, this seems likely and will be cleaned up separately. Unfortunately, there is not a single place where modifiers are added to objects currently. Therefore, there are quite a few places that need to ensure valid identifiers. I tried to catch all the places, but it's hard to be sure. Therefore, I added an assert in `object_copy_data` that checks if all identifiers are valid. This way, we should be notified relatively quickly if issues are caused by invalid identifiers. Pull Request: https://projects.blender.org/blender/blender/pulls/117347
2024-02-06 17:10:40 +01:00
/**
* Updates `md.persistent_uid` so that it is a valid identifier (>=1) and is unique in the object.
*/
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md);
/**
* Returns true when all the modifier identifiers are positive and unique. This should generally be
* true and should only be used by asserts.
*/
bool BKE_modifiers_persistent_uids_are_valid(const Object &object);
/**
* used for buttons, to find out if the 'draw deformed in edit-mode option is there.
*
* Also used in transform_conversion.c, to detect crazy-space (2nd arg then is NULL).
* Also used for some mesh tools to give warnings.
*/
int BKE_modifiers_get_cage_index(const Scene *scene,
Object *ob,
2020-05-08 11:02:03 +02:00
int *r_lastPossibleCageIndex,
bool is_virtual);
/**
* Takes an object and returns its first selected armature, else just its armature.
* This should work for multiple armatures per object.
*/
Object *BKE_modifiers_is_deformed_by_armature(Object *ob);
Object *BKE_modifiers_is_deformed_by_meshdeform(Object *ob);
/**
* Takes an object and returns its first selected lattice, else just its lattice.
* This should work for multiple lattices per object.
*/
Object *BKE_modifiers_is_deformed_by_lattice(Object *ob);
/**
* Takes an object and returns its first selected curve, else just its curve.
* This should work for multiple curves per object.
*/
Object *BKE_modifiers_is_deformed_by_curve(Object *ob);
bool BKE_modifiers_uses_multires(Object *ob);
bool BKE_modifiers_uses_armature(Object *ob, bArmature *arm);
bool BKE_modifiers_is_correctable_deformed(const Scene *scene, Object *ob);
void BKE_modifier_free_temporary_data(ModifierData *md);
struct CDMaskLink {
CDMaskLink *next;
CustomData_MeshMasks mask;
};
2020-06-17 06:00:09 +02:00
/**
* Calculates and returns a linked list of CustomData_MeshMasks and modified
* final datamask, indicating the data required by each modifier in the stack
* pointed to by md for correct evaluation, assuming the data indicated by
* final_datamask is required at the end of the stack.
*/
CDMaskLink *BKE_modifier_calc_data_masks(const Scene *scene,
ModifierData *md,
CustomData_MeshMasks *final_datamask,
int required_mode);
struct VirtualModifierData {
ArmatureModifierData amd;
CurveModifierData cmd;
LatticeModifierData lmd;
ShapeKeyModifierData smd;
};
/**
* This is to include things that are not modifiers in the evaluation of the modifier stack,
* for example parenting to an armature.
*/
ModifierData *BKE_modifiers_get_virtual_modifierlist(const Object *ob, VirtualModifierData *data);
/**
* Ensure modifier correctness when changing `ob->data`.
*/
void BKE_modifiers_test_object(Object *ob);
/**
* Here for #do_versions.
*/
void BKE_modifier_mdef_compact_influences(ModifierData *md);
/**
* Initializes `path` with either the blend file or temporary directory.
*/
void BKE_modifier_path_init(char *path, int path_maxncpy, const char *name);
const char *BKE_modifier_path_relbase(Main *bmain, Object *ob);
const char *BKE_modifier_path_relbase_from_global(Object *ob);
/* Accessors of original/evaluated modifiers. */
/**
* For a given modifier data, get corresponding original one.
* If the modifier data is already original, return it as-is.
*/
ModifierData *BKE_modifier_get_original(const Object *object, ModifierData *md);
ModifierData *BKE_modifier_get_evaluated(Depsgraph *depsgraph, Object *object, ModifierData *md);
/* wrappers for modifier callbacks that ensure valid normals */
Mesh *BKE_modifier_modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh);
void BKE_modifier_deform_verts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions);
void BKE_modifier_deform_vertsEM(ModifierData *md,
const ModifierEvalContext *ctx,
BMEditMesh *em,
Mesh *mesh,
blender::MutableSpan<blender::float3> positions);
/**
* Get evaluated mesh for other evaluated object, which is used as an operand for the modifier,
* e.g. second operand for boolean modifier.
* Note that modifiers in stack always get fully evaluated ID pointers,
* never original ones. Makes things simpler.
*/
Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval);
void BKE_modifier_blend_write(BlendWriter *writer, const ID *id_owner, ListBase *modbase);
void BKE_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb, Object *ob);
Modifiers: measure execution time and provide Python access The goal is to give technical artists the ability to optimize modifier usage and/or geometry node groups for performance. In the long term, it would be useful if Blender could provide its own UI to display profiling information to users. However, right now, there are too many open design questions making it infeasible to tackle this in the short term. This commit uses a simpler approach: Instead of adding new ui for profiling data, it exposes the execution-time of modifiers in the Python API. This allows technical artists to access the information and to build their own UI to display the relevant information. In the long term this will hopefully also help us to integrate a native ui for this in Blender by observing how users use this information. Note: The execution time of a modifier highly depends on what other things the CPU is doing at the same time. For example, in many more complex files, many objects and therefore modifiers are evaluated at the same time by multiple threads which makes the measurement much less reliable. For best results, make sure that only one object is evaluated at a time (e.g. by changing it in isolation) and that no other process on the system keeps the CPU busy. As shown below, the execution time has to be accessed on the evaluated object, not the original object. ```lang=python import bpy depsgraph = bpy.context.view_layer.depsgraph ob = bpy.context.active_object ob_eval = ob.evaluated_get(depsgraph) modifier_eval = ob_eval.modifiers[0] print(modifier_eval.execution_time, "s") ``` Differential Revision: https://developer.blender.org/D17185
2023-02-06 15:39:59 +01:00
namespace blender::bke {
/**
* A convenience class that can be used to set `ModifierData::execution_time` based on the lifetime
* of this class.
*/
class ScopedModifierTimer {
private:
ModifierData &md_;
double start_time_;
public:
ScopedModifierTimer(ModifierData &md);
~ScopedModifierTimer();
};
} // namespace blender::bke