diff options
Diffstat (limited to 'source/blender/blenkernel')
153 files changed, 3475 insertions, 3026 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 7d553b68185..684296381eb 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -329,7 +329,7 @@ void DM_copy_vert_data(struct DerivedMesh *source, int dest_index, int count); -/*sets up mpolys for a DM based on face iterators in source*/ +/* Sets up mpolys for a DM based on face iterators in source. */ void DM_DupPolys(DerivedMesh *source, DerivedMesh *target); void DM_ensure_normals(DerivedMesh *dm); diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 3d81fcba37d..9f69c5e3976 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -108,7 +108,7 @@ void action_group_colors_sync(struct bActionGroup *grp, const struct bActionGrou /* Add a new action group with the given name to the action */ struct bActionGroup *action_groups_add_new(struct bAction *act, const char name[]); -/* Add given channel into (active) group */ +/* Add given channel into (active) group */ void action_groups_add_channel(struct bAction *act, struct bActionGroup *agrp, struct FCurve *fcurve); diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index d43332ae1ac..030560015a9 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -242,7 +242,7 @@ bool BKE_animsys_rna_path_resolve(struct PointerRNA *ptr, bool BKE_animsys_read_from_rna_path(struct PathResolvedRNA *anim_rna, float *r_value); bool BKE_animsys_write_to_rna_path(struct PathResolvedRNA *anim_rna, const float value); -/* Evaluation loop for evaluating animation data */ +/* Evaluation loop for evaluating animation data. */ void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, const struct AnimationEvalContext *anim_eval_context, diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 112b8bf3ad4..86aa18e5739 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -49,24 +49,30 @@ typedef struct EditBone { struct EditBone *next, *prev; /** User-Defined Properties on this Bone */ struct IDProperty *prop; - /** Editbones have a one-way link (i.e. children refer + /** + * Editbones have a one-way link (i.e. children refer * to parents. This is converted to a two-way link for - * normal bones when leaving editmode. */ + * normal bones when leaving editmode. + */ struct EditBone *parent; /** (64 == MAXBONENAME) */ char name[64]; - /** Roll along axis. We'll ultimately use the axis/angle method + /** + * Roll along axis. We'll ultimately use the axis/angle method * for determining the transformation matrix of the bone. The axis * is tail-head while roll provides the angle. Refer to Graphics - * Gems 1 p. 466 (section IX.6) if it's not already in here somewhere*/ + * Gems 1 p. 466 (section IX.6) if it's not already in here somewhere. + */ float roll; /** Orientation and length is implicit during editing */ float head[3]; float tail[3]; - /** All joints are considered to have zero rotation with respect to + /** + * All joints are considered to have zero rotation with respect to * their parents. Therefore any rotations specified during the - * animation are automatically relative to the bones' rest positions*/ + * animation are automatically relative to the bones' rest positions. + */ int flag; int layer; char inherit_scale_mode; @@ -145,7 +151,7 @@ typedef struct PoseTree { struct bArmature *BKE_armature_add(struct Main *bmain, const char *name); struct bArmature *BKE_armature_from_object(struct Object *ob); -int BKE_armature_bonelist_count(struct ListBase *lb); +int BKE_armature_bonelist_count(const struct ListBase *lb); void BKE_armature_bonelist_free(struct ListBase *lb, const bool do_id_user); void BKE_armature_editbonelist_free(struct ListBase *lb, const bool do_id_user); diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 30a595dba8e..6a1f1feb14f 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -38,12 +38,16 @@ struct ID; struct ReportList; /* Attribute.domain */ +/** + * \warning: Careful when changing existing items. Arrays may be initialized from this (e.g. + * #DATASET_layout_hierarchy). + */ typedef enum AttributeDomain { ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */ ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */ ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */ - ATTR_DOMAIN_CORNER = 2, /* Mesh Corner */ - ATTR_DOMAIN_FACE = 3, /* Mesh Face */ + ATTR_DOMAIN_FACE = 2, /* Mesh Face */ + ATTR_DOMAIN_CORNER = 3, /* Mesh Corner */ ATTR_DOMAIN_CURVE = 4, /* Hair Curve */ ATTR_DOMAIN_NUM diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh index ba683362e69..2ce41e95b65 100644 --- a/source/blender/blenkernel/BKE_attribute_math.hh +++ b/source/blender/blenkernel/BKE_attribute_math.hh @@ -306,7 +306,7 @@ template<> struct DefaultMixerStruct<float3> { }; template<> struct DefaultMixerStruct<ColorGeometry4f> { /* Use a special mixer for colors. ColorGeometry4f can't be added/multiplied, because this is not - * something one should usually do with colors. */ + * something one should usually do with colors. */ using type = ColorGeometryMixer; }; template<> struct DefaultMixerStruct<int> { diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 1767077fa45..d5baeb08ccc 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 4 +#define BLENDER_FILE_SUBVERSION 7 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index 429e294a337..3e0a343a766 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -25,6 +25,7 @@ extern "C" { struct BlendFileData; struct BlendFileReadParams; +struct BlendFileReadReport; struct ID; struct Main; struct MemFile; @@ -35,7 +36,7 @@ struct bContext; void BKE_blendfile_read_setup_ex(struct bContext *C, struct BlendFileData *bfd, const struct BlendFileReadParams *params, - struct ReportList *reports, + struct BlendFileReadReport *reports, /* Extra args. */ const bool startup_update_defaults, const char *startup_app_template); @@ -43,11 +44,11 @@ void BKE_blendfile_read_setup_ex(struct bContext *C, void BKE_blendfile_read_setup(struct bContext *C, struct BlendFileData *bfd, const struct BlendFileReadParams *params, - struct ReportList *reports); + struct BlendFileReadReport *reports); struct BlendFileData *BKE_blendfile_read(const char *filepath, const struct BlendFileReadParams *params, - struct ReportList *reports); + struct BlendFileReadReport *reports); struct BlendFileData *BKE_blendfile_read_from_memory(const void *filebuf, int filelength, diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 78908908343..8be2fcbdb83 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -218,7 +218,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data, ThreadMutex *mesh_eval_mutex); BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, - struct Mesh *mesh, + const struct Mesh *mesh, const BVHCacheType bvh_cache_type, const int tree_type); diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 04fcdd6ed6f..a0e3d5dc142 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -103,11 +103,11 @@ typedef struct Cloth { * The definition of a cloth vertex. */ typedef struct ClothVertex { - int flags; /* General flags per vertex. */ - float v[3]; /* The velocity of the point. */ + int flags; /* General flags per vertex. */ + float v[3]; /* The velocity of the point. */ float xconst[3]; /* constrained position */ float x[3]; /* The current position of this vertex. */ - float xold[3]; /* The previous position of this vertex.*/ + float xold[3]; /* The previous position of this vertex. */ float tx[3]; /* temporary position */ float txold[3]; /* temporary old position */ float tv[3]; /* temporary "velocity", mostly used as tv = tx-txold */ @@ -194,7 +194,7 @@ typedef struct ClothSpring { } \ ((void)0) -/* Spring types as defined in the paper.*/ +/* Spring types as defined in the paper. */ typedef enum { CLOTH_SPRING_TYPE_STRUCTURAL = (1 << 1), CLOTH_SPRING_TYPE_SHEAR = (1 << 2), diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index 7963d54126e..f47cdf32ca0 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -164,7 +164,8 @@ bool BKE_collection_move(struct Main *bmain, bool BKE_collection_cycle_find(struct Collection *new_ancestor, struct Collection *collection); bool BKE_collection_cycles_fix(struct Main *bmain, struct Collection *collection); -bool BKE_collection_has_collection(struct Collection *parent, struct Collection *collection); +bool BKE_collection_has_collection(const struct Collection *parent, + const struct Collection *collection); void BKE_collection_parent_relations_rebuild(struct Collection *collection); void BKE_main_collections_parent_relations_rebuild(struct Main *bmain); diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index ff1bca896b1..2c21b7355d6 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -63,7 +63,7 @@ typedef struct CollPair { float time; /* collision time, from 0 up to 1 */ /* mesh-mesh collision */ -#ifdef WITH_ELTOPO /*either ap* or bp* can be set, but not both*/ +#ifdef WITH_ELTOPO /* Either ap* or bp* can be set, but not both. */ float bary[3]; int ap1, ap2, ap3, collp, bp1, bp2, bp3; int collface; diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index afad1e26159..575df93a9fc 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -59,7 +59,7 @@ typedef struct bConstraintOb { /** space matrix for custom object space */ float space_obj_world_matrix[4][4]; - /** type of owner */ + /** type of owner. */ short type; /** rotation order for constraint owner (as defined in eEulerRotationOrders in BLI_math.h) */ short rotOrder; diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 2687a5ea16c..c7c5f59cab2 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -121,6 +121,7 @@ void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsig void BKE_curve_smooth_flag_set(struct Curve *cu, const bool use_smooth); ListBase *BKE_curve_nurbs_get(struct Curve *cu); +const ListBase *BKE_curve_nurbs_get_for_read(const struct Curve *cu); int BKE_curve_nurb_vert_index_get(const struct Nurb *nu, const void *vert); void BKE_curve_nurb_active_set(struct Curve *cu, const struct Nurb *nu); @@ -153,9 +154,10 @@ void BKE_curve_editNurb_keyIndex_delCV(struct GHash *keyindex, const void *cv); void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex); void BKE_curve_editNurb_free(struct Curve *cu); struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu); +const struct ListBase *BKE_curve_editNurbs_get_for_read(const struct Curve *cu); void BKE_curve_bevelList_free(struct ListBase *bev); -void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render); +void BKE_curve_bevelList_make(struct Object *ob, const struct ListBase *nurbs, bool for_render); ListBase BKE_curve_bevel_make(const struct Curve *curve); void BKE_curve_forward_diff_bezier( diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index ed319948160..c4db8ee925e 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -41,7 +41,7 @@ struct CustomData_MeshMasks; struct ID; typedef uint64_t CustomDataMask; -/*a data type large enough to hold 1 element from any customdata layer type*/ +/* A data type large enough to hold 1 element from any custom-data layer type. */ typedef struct { unsigned char data[64]; } CDBlockBytes; @@ -109,9 +109,9 @@ bool CustomData_bmesh_has_free(const struct CustomData *data); */ bool CustomData_has_referenced(const struct CustomData *data); -/* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to +/* Copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to * another, while not overwriting anything else (e.g. flags). probably only - * implemented for mloopuv/mloopcol, for now.*/ + * implemented for mloopuv/mloopcol, for now. */ void CustomData_data_copy_value(int type, const void *source, void *dest); /* Same as above, but doing advanced mixing. @@ -121,7 +121,7 @@ void CustomData_data_mix_value( /* compares if data1 is equal to data2. type is a valid CustomData type * enum (e.g. CD_MLOOPUV). the layer type's equal function is used to compare - * the data, if it exists, otherwise memcmp is used.*/ + * the data, if it exists, otherwise memcmp is used. */ bool CustomData_data_equals(int type, const void *data1, const void *data2); void CustomData_data_initminmax(int type, void *min, void *max); void CustomData_data_dominmax(int type, const void *data, void *min, void *max); @@ -158,7 +158,7 @@ void CustomData_realloc(struct CustomData *data, int totelem); /* bmesh version of CustomData_merge; merges the layouts of source and dest, * then goes through the mesh and makes sure all the customdata blocks are - * consistent with the new layout.*/ + * consistent with the new layout. */ bool CustomData_bmesh_merge(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, @@ -186,7 +186,7 @@ void CustomData_free_temporary(struct CustomData *data, int totelem); */ void *CustomData_add_layer( struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem); -/*same as above but accepts a name */ +/* Same as above but accepts a name. */ void *CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, @@ -233,6 +233,9 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, const int totelem); bool CustomData_is_referenced_layer(struct CustomData *data, int type); +/* Duplicate all the layers with flag NOFREE, and remove the flag from duplicated layers. */ +void CustomData_duplicate_referenced_layers(CustomData *data, int totelem); + /* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is * zero for the layer type, so only layer types specified by the mask * will be copied @@ -443,7 +446,7 @@ void CustomData_validate_layer_name(const struct CustomData *data, * only after this test passes, layer->data should be assigned */ bool CustomData_verify_versions(struct CustomData *data, int index); -/*BMesh specific customdata stuff*/ +/* BMesh specific custom-data stuff. */ void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *ldata, int totloop); void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *ldata, int total); void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *ldata); @@ -536,7 +539,7 @@ enum { CDT_MIX_ADD = 17, CDT_MIX_SUB = 18, CDT_MIX_MUL = 19, - /* etc. etc. */ + /* Etc. */ }; typedef struct CustomDataTransferLayerMap { diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index a2d9bbcd011..0f37ba6c4ce 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -32,11 +32,11 @@ extern "C" { /** #DispList.type */ enum { - /** A closed polygon (that can be filled). */ + /** A closed polygon (that can be filled). */ DL_POLY = 0, - /** An open polygon. */ + /** An open polygon. */ DL_SEGM = 1, - /** A grid surface that respects #DL_CYCL_U & #DL_CYCL_V. */ + /** A grid surface that respects #DL_CYCL_U & #DL_CYCL_V. */ DL_SURF = 2, /** Triangles. */ DL_INDEX3 = 4, @@ -87,13 +87,11 @@ bool BKE_displist_has_faces(const struct ListBase *lb); void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, - const bool for_render, - const bool for_orco); + const bool for_render); void BKE_displist_make_curveTypes_forRender(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, struct ListBase *dispbase, - const bool for_orco, struct Mesh **r_final); void BKE_displist_make_mball(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_displist_make_mball_forRender(struct Depsgraph *depsgraph, diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 075a9bc0eac..e31a0a16408 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -53,12 +53,12 @@ struct Scene; typedef struct BMEditMesh { struct BMesh *bm; - /*this is for undoing failed operations*/ + /* This is for undoing failed operations. */ struct BMEditMesh *emcopy; int emcopyusers; /* we store tessellations as triplets of three loops, - * which each define a triangle.*/ + * which each define a triangle. */ struct BMLoop *(*looptris)[3]; int tottri; @@ -67,14 +67,14 @@ typedef struct BMEditMesh { /** Cached cage bounding box for selection. */ struct BoundBox *bb_cage; - /*derivedmesh stuff*/ + /** Evaluated mesh data-mask. */ CustomData_MeshMasks lastDataMask; - /*selection mode*/ + /* Selection mode. */ short selectmode; short mat_nr; - /*temp variables for x-mirror editing*/ + /* Temp variables for x-mirror editing. */ int mirror_cdlayer; /* -1 is invalid */ /** diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 231a4563630..3a964ddb1aa 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -179,7 +179,7 @@ unsigned int BKE_sim_debug_data_hash(int i); unsigned int BKE_sim_debug_data_hash_combine(unsigned int kx, unsigned int ky); /* _VA_SIM_DEBUG_HASH#(i, ...): combined hash value of multiple integers */ -/* internal helpers*/ +/* Internal helpers. */ #define _VA_SIM_DEBUG_HASH1(a) (BKE_sim_debug_data_hash(a)) #define _VA_SIM_DEBUG_HASH2(a, b) \ (BKE_sim_debug_data_hash_combine(BKE_sim_debug_data_hash(a), _VA_SIM_DEBUG_HASH1(b))) diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 589d1839dd4..f494c2e30cc 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -180,7 +180,7 @@ int BKE_fcm_envelope_find_index(struct FCM_EnvelopeData *array, * but should become userpref */ #define BEZT_BINARYSEARCH_THRESH 0.01f /* was 0.00001, but giving errors */ -/* -------- Data Management -------- */ +/* -------- Data Management -------- */ struct FCurve *BKE_fcurve_create(void); void BKE_fcurve_free(struct FCurve *fcu); struct FCurve *BKE_fcurve_copy(const struct FCurve *fcu); @@ -227,9 +227,9 @@ struct FCurve *BKE_fcurve_find_by_rna_context_ui(struct bContext *C, /* Binary search algorithm for finding where to 'insert' BezTriple with given frame number. * Returns the index to insert at (data already at that index will be offset if replace is 0) */ -int BKE_fcurve_bezt_binarysearch_index(struct BezTriple array[], - float frame, - int arraylen, +int BKE_fcurve_bezt_binarysearch_index(const struct BezTriple array[], + const float frame, + const int arraylen, bool *r_replace); /* fcurve_cache.c */ @@ -302,7 +302,7 @@ bool BKE_fcurve_bezt_subdivide_handles(struct BezTriple *bezt, struct BezTriple *next, float *r_pdelta); -/* -------- Curve Sanity -------- */ +/* -------- Curve Sanity -------- */ void calchandles_fcurve(struct FCurve *fcu); void calchandles_fcurve_ex(struct FCurve *fcu, eBezTriple_Flag handle_sel_flag); @@ -312,7 +312,7 @@ bool test_time_fcurve(struct FCurve *fcu); void BKE_fcurve_correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2]); -/* -------- Evaluation -------- */ +/* -------- Evaluation -------- */ /* evaluate fcurve */ float evaluate_fcurve(struct FCurve *fcu, float evaltime); @@ -329,7 +329,7 @@ float calculate_fcurve(struct PathResolvedRNA *anim_rna, /* ************* F-Curve Samples API ******************** */ -/* -------- Defines -------- */ +/* -------- Defines -------- */ /* Basic signature for F-Curve sample-creation function * - fcu: the F-Curve being operated on @@ -337,12 +337,12 @@ float calculate_fcurve(struct PathResolvedRNA *anim_rna, */ typedef float (*FcuSampleFunc)(struct FCurve *fcu, void *data, float evaltime); -/* ----- Sampling Callbacks ------ */ +/* ----- Sampling Callbacks ------ */ /* Basic sampling callback which acts as a wrapper for evaluate_fcurve() */ float fcurve_samplingcb_evalcurve(struct FCurve *fcu, void *data, float evaltime); -/* -------- Main Methods -------- */ +/* -------- Main Methods -------- */ /* Main API function for creating a set of sampled curve data, given some callback function * used to retrieve the values to store. diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index b23ccbe25ff..522d3843bb2 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -66,8 +66,8 @@ typedef struct EditFont { } EditFont; -bool BKE_vfont_is_builtin(struct VFont *vfont); -void BKE_vfont_builtin_register(void *mem, int size); +bool BKE_vfont_is_builtin(const struct VFont *vfont); +void BKE_vfont_builtin_register(const void *mem, int size); void BKE_vfont_free_data(struct VFont *vfont); struct VFont *BKE_vfont_builtin_get(void); diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index b2342a5fd96..82c9a31dfce 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -280,8 +280,6 @@ struct GeometrySet { void compute_boundbox_without_instances(blender::float3 *r_min, blender::float3 *r_max) const; friend std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set); - friend bool operator==(const GeometrySet &a, const GeometrySet &b); - uint64_t hash() const; void clear(); diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 74f2bf7c6ad..69c950a86dc 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -149,7 +149,7 @@ enum { G_DEBUG_DEPSGRAPH_TIME | G_DEBUG_DEPSGRAPH_UUID), G_DEBUG_SIMDATA = (1 << 15), /* sim debug data display */ G_DEBUG_GPU = (1 << 16), /* gpu debug */ - G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...)*/ + G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...). */ G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 18), /* force gpu workarounds bypassing detections. */ G_DEBUG_XR = (1 << 19), /* XR/OpenXR messages */ G_DEBUG_XR_TIME = (1 << 20), /* XR/OpenXR timing messages */ diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index d0a1f102a43..657e66729e1 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -214,6 +214,10 @@ void BKE_gpencil_layer_mask_remove_ref(struct bGPdata *gpd, const char *name); struct bGPDlayer_Mask *BKE_gpencil_layer_mask_named_get(struct bGPDlayer *gpl, const char *name); void BKE_gpencil_layer_mask_sort(struct bGPdata *gpd, struct bGPDlayer *gpl); void BKE_gpencil_layer_mask_sort_all(struct bGPdata *gpd); +void BKE_gpencil_layer_mask_copy(const struct bGPDlayer *gpl_src, struct bGPDlayer *gpl_dst); +void BKE_gpencil_layer_mask_cleanup(struct bGPdata *gpd, struct bGPDlayer *gpl); +void BKE_gpencil_layer_mask_cleanup_all_layers(struct bGPdata *gpd); + void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames); struct bGPDlayer *BKE_gpencil_layer_get_by_name(struct bGPdata *gpd, diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index 8fc3ce133a0..c1ccae7a437 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -90,7 +90,7 @@ typedef struct GPencilPointCoordinates { float pressure; } GPencilPointCoordinates; -int BKE_gpencil_stroke_point_count(struct bGPdata *gpd); +int BKE_gpencil_stroke_point_count(const struct bGPdata *gpd); void BKE_gpencil_point_coords_get(struct bGPdata *gpd, GPencilPointCoordinates *elem_data); void BKE_gpencil_point_coords_apply(struct bGPdata *gpd, const GPencilPointCoordinates *elem_data); void BKE_gpencil_point_coords_apply_with_mat4(struct bGPdata *gpd, diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index bcf35bf1197..a5cb6489194 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -67,7 +67,7 @@ void IDP_AppendArray(struct IDProperty *prop, struct IDProperty *item); void IDP_ResizeIDPArray(struct IDProperty *prop, int len); /* ----------- Numeric Array Type ----------- */ -/*this function works for strings too!*/ +/* This function works for strings too! */ void IDP_ResizeArray(struct IDProperty *prop, int newlen); void IDP_FreeArray(struct IDProperty *prop); diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h index 4578f1c3ca5..28171b2b363 100644 --- a/source/blender/blenkernel/BKE_idtype.h +++ b/source/blender/blenkernel/BKE_idtype.h @@ -82,8 +82,8 @@ typedef void (*IDTypeMakeLocalFunction)(struct Main *bmain, struct ID *id, const typedef void (*IDTypeForeachIDFunction)(struct ID *id, struct LibraryForeachIDData *data); typedef enum eIDTypeInfoCacheCallbackFlags { - /** Indicates to the callback that that cache may be stored in the .blend file, so its pointer - * should not be cleared at read-time. */ + /** Indicates to the callback that cache may be stored in the .blend file, + * so its pointer should not be cleared at read-time. */ IDTYPE_CACHE_CB_FLAGS_PERSISTENT = 1 << 0, } eIDTypeInfoCacheCallbackFlags; typedef void (*IDTypeForeachCacheFunctionCallback)(struct ID *id, diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index c969ce07d74..58b8d19abaa 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -76,7 +76,7 @@ void BKE_keyblock_update_from_lattice(struct Lattice *lt, struct KeyBlock *kb); void BKE_keyblock_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb); void BKE_keyblock_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt); -int BKE_keyblock_curve_element_count(struct ListBase *nurb); +int BKE_keyblock_curve_element_count(const struct ListBase *nurb); void BKE_keyblock_curve_data_transform(const struct ListBase *nurb, const float mat[4][4], const void *src, diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 240d6cb18ec..404f344919c 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -92,7 +92,7 @@ bool BKE_layer_collection_activate(struct ViewLayer *view_layer, struct LayerCol struct LayerCollection *BKE_layer_collection_activate_parent(struct ViewLayer *view_layer, struct LayerCollection *lc); -int BKE_layer_collection_count(struct ViewLayer *view_layer); +int BKE_layer_collection_count(const struct ViewLayer *view_layer); struct LayerCollection *BKE_layer_collection_from_index(struct ViewLayer *view_layer, const int index); @@ -107,8 +107,8 @@ void BKE_layer_collection_local_sync_all(const struct Main *bmain); void BKE_main_collection_sync_remap(const struct Main *bmain); struct LayerCollection *BKE_layer_collection_first_from_scene_collection( - struct ViewLayer *view_layer, const struct Collection *collection); -bool BKE_view_layer_has_collection(struct ViewLayer *view_layer, + const struct ViewLayer *view_layer, const struct Collection *collection); +bool BKE_view_layer_has_collection(const struct ViewLayer *view_layer, const struct Collection *collection); bool BKE_scene_has_object(struct Scene *scene, struct Object *ob); @@ -367,7 +367,7 @@ void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *iter); struct ObjectsInViewLayerParams { uint no_dup_data : 1; - bool (*filter_fn)(struct Object *ob, void *user_data); + bool (*filter_fn)(const struct Object *ob, void *user_data); void *filter_userdata; }; @@ -388,7 +388,7 @@ struct ObjectsInModeParams { int object_mode; uint no_dup_data : 1; - bool (*filter_fn)(struct Object *ob, void *user_data); + bool (*filter_fn)(const struct Object *ob, void *user_data); void *filter_userdata; }; @@ -412,8 +412,8 @@ struct Object **BKE_view_layer_array_from_objects_in_mode_params( BKE_view_layer_array_from_bases_in_mode_params( \ view_layer, v3d, r_len, &(const struct ObjectsInModeParams)__VA_ARGS__) -bool BKE_view_layer_filter_edit_mesh_has_uvs(struct Object *ob, void *user_data); -bool BKE_view_layer_filter_edit_mesh_has_edges(struct Object *ob, void *user_data); +bool BKE_view_layer_filter_edit_mesh_has_uvs(const struct Object *ob, void *user_data); +bool BKE_view_layer_filter_edit_mesh_has_edges(const struct Object *ob, void *user_data); /* Utility macros that wrap common args (add more as needed). */ diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index e16507bf3cc..fac5dc8c010 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -315,6 +315,9 @@ void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id); #define IS_TAGGED(_id) ((_id) && (((ID *)_id)->tag & LIB_TAG_DOIT)) +/* lib_id_eval.c */ +void BKE_id_eval_properties_copy(struct ID *id_cow, struct ID *id); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index 4dc99e64cf2..27076d908e7 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -43,6 +43,7 @@ extern "C" { #endif struct Collection; +struct BlendFileReadReport; struct ID; struct IDOverrideLibrary; struct IDOverrideLibraryProperty; @@ -90,14 +91,16 @@ bool BKE_lib_override_library_resync(struct Main *bmain, struct Collection *override_resync_residual_storage, const bool do_hierarchy_enforce, const bool do_post_process, - struct ReportList *reports); + struct BlendFileReadReport *reports); void BKE_lib_override_library_main_resync(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, - struct ReportList *reports); + struct BlendFileReadReport *reports); void BKE_lib_override_library_delete(struct Main *bmain, struct ID *id_root); +void BKE_lib_override_library_make_local(struct ID *id); + struct IDOverrideLibraryProperty *BKE_lib_override_library_property_find( struct IDOverrideLibrary *override, const char *rna_path); struct IDOverrideLibraryProperty *BKE_lib_override_library_property_get( diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 8ddfb0c8eb2..8d76a025e87 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -128,7 +128,8 @@ struct Mesh *BKE_mesh_copy_for_eval(struct Mesh *source, bool reference); /* These functions construct a new Mesh, * contrary to BKE_mesh_from_nurbs which modifies ob itself. */ struct Mesh *BKE_mesh_new_nomain_from_curve(struct Object *ob); -struct Mesh *BKE_mesh_new_nomain_from_curve_displist(struct Object *ob, struct ListBase *dispbase); +struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob, + const struct ListBase *dispbase); bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me); bool BKE_mesh_clear_facemap_customdata(struct Mesh *me); @@ -151,7 +152,7 @@ int BKE_mesh_nurbs_to_mdata(struct Object *ob, struct MPoly **r_allpoly, int *r_totloop, int *r_totpoly); -int BKE_mesh_nurbs_displist_to_mdata(struct Object *ob, +int BKE_mesh_nurbs_displist_to_mdata(const struct Object *ob, const struct ListBase *dispbase, struct MVert **r_allvert, int *r_totvert, @@ -298,7 +299,7 @@ void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop, struct MLoopTri *mlooptri, const float (*poly_normals)[3]); -/* *** mesh_evaluate.c *** */ +/* *** mesh_normals.c *** */ void BKE_mesh_calc_normals_mapping_simple(struct Mesh *me); void BKE_mesh_calc_normals_mapping(struct MVert *mverts, @@ -493,6 +494,8 @@ void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh, void BKE_mesh_set_custom_normals(struct Mesh *mesh, float (*r_custom_loopnors)[3]); void BKE_mesh_set_custom_normals_from_vertices(struct Mesh *mesh, float (*r_custom_vertnors)[3]); +/* *** mesh_evaluate.c *** */ + void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly, const struct MLoop *loopstart, const struct MVert *mvarray, diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h index d9b6ab3813e..02f8af6443c 100644 --- a/source/blender/blenkernel/BKE_mesh_remap.h +++ b/source/blender/blenkernel/BKE_mesh_remap.h @@ -36,7 +36,7 @@ typedef struct MeshPairRemapItem { int sources_num; int *indices_src; /* NULL if no source found. */ float *weights_src; /* NULL if no source found, else, always normalized! */ - /* UNUSED (at the moment)*/ + /* UNUSED (at the moment). */ // float hit_dist; /* FLT_MAX if irrelevant or no source found. */ int island; /* For loops only. */ } MeshPairRemapItem; diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h index 67c87e96aff..3efbef94081 100644 --- a/source/blender/blenkernel/BKE_mesh_runtime.h +++ b/source/blender/blenkernel/BKE_mesh_runtime.h @@ -45,7 +45,7 @@ void BKE_mesh_runtime_reset(struct Mesh *mesh); void BKE_mesh_runtime_reset_on_copy(struct Mesh *mesh, const int flag); int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh); void BKE_mesh_runtime_looptri_recalc(struct Mesh *mesh); -const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(struct Mesh *mesh); +const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh); bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh); bool BKE_mesh_runtime_clear_edit_data(struct Mesh *mesh); bool BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh); diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index fce25abba7f..11bfc4b2b3a 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -220,7 +220,7 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3] /* Versioning. */ /* Convert displacement which is stored for simply-subdivided mesh to a Catmull-Clark - * subdivided mesh. */ + * subdivided mesh. */ void multires_do_versions_simple_to_catmull_clark(struct Object *object, struct MultiresModifierData *mmd); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index a0f6be6b3e9..3562a3e8d63 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1439,6 +1439,11 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_SEPARATE_COMPONENTS 1059 #define GEO_NODE_CURVE_SUBDIVIDE 1060 #define GEO_NODE_RAYCAST 1061 +#define GEO_NODE_CURVE_PRIMITIVE_STAR 1062 +#define GEO_NODE_CURVE_PRIMITIVE_SPIRAL 1063 +#define GEO_NODE_CURVE_PRIMITIVE_QUADRATIC_BEZIER 1064 +#define GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT 1065 +#define GEO_NODE_CURVE_PRIMITIVE_CIRCLE 1066 /** \} */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index b0b1657c162..cd66f026828 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -243,7 +243,7 @@ void BKE_object_dimensions_set(struct Object *ob, const float value[3], int axis void BKE_object_empty_draw_type_set(struct Object *ob, const int value); void BKE_object_boundbox_flag(struct Object *ob, int flag, const bool set); -void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval); +void BKE_object_boundbox_calc_from_mesh(struct Object *ob, const struct Mesh *me_eval); void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden); bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph, struct Scene *scene, @@ -382,20 +382,19 @@ void BKE_object_data_batch_cache_dirty_tag(struct ID *object_data); /* this function returns a superset of the scenes selection based on relationships */ typedef enum eObRelationTypes { - OB_REL_NONE = 0, /* just the selection as is */ - OB_REL_PARENT = (1 << 0), /* immediate parent */ - OB_REL_PARENT_RECURSIVE = (1 << 1), /* parents up to root of selection tree*/ - OB_REL_CHILDREN = (1 << 2), /* immediate children */ - OB_REL_CHILDREN_RECURSIVE = (1 << 3), /* All children */ - OB_REL_MOD_ARMATURE = (1 << 4), /* Armatures related to the selected objects */ - /* OB_REL_SCENE_CAMERA = (1 << 5), */ /* you might want the scene camera too even if unselected? - */ + OB_REL_NONE = 0, /* Just the selection as is. */ + OB_REL_PARENT = (1 << 0), /* Immediate parent. */ + OB_REL_PARENT_RECURSIVE = (1 << 1), /* Parents up to root of selection tree. */ + OB_REL_CHILDREN = (1 << 2), /* Immediate children. */ + OB_REL_CHILDREN_RECURSIVE = (1 << 3), /* All children. */ + OB_REL_MOD_ARMATURE = (1 << 4), /* Armatures related to the selected objects. */ + // OB_REL_SCENE_CAMERA = (1 << 5), /* You might want the scene camera too even if unselected? */ } eObRelationTypes; typedef enum eObjectSet { - OB_SET_SELECTED, /* Selected Objects */ - OB_SET_VISIBLE, /* Visible Objects */ - OB_SET_ALL, /* All Objects */ + OB_SET_SELECTED, /* Selected Objects. */ + OB_SET_VISIBLE, /* Visible Objects. */ + OB_SET_ALL, /* All Objects. */ } eObjectSet; struct LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer, diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 3913ede9049..e5b547d2557 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -78,7 +78,7 @@ struct Scene; for (p = 0; p < psys->totpart; p++) \ if ((pa = psys->particles + p)->state.time > 0.0f) -/* fast but sure way to get the modifier*/ +/* Fast but sure way to get the modifier. */ #define PARTICLE_PSMD \ ParticleSystemModifierData *psmd = sim->psmd ? sim->psmd : psys_get_modifier(sim->ob, sim->psys) @@ -190,7 +190,7 @@ typedef struct ParticleCollisionElement { /* pointers to original data */ float *x[3], *v[3]; - /* values interpolated from original data*/ + /* Values interpolated from original data. */ float x0[3], x1[3], x2[3], p[3]; /* results for found intersection point */ diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 0fa44067b16..97e5698d6f9 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -474,7 +474,7 @@ bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node); // void BKE_pbvh_node_BB_reset(PBVHNode *node); // void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]); -bool pbvh_has_mask(PBVH *pbvh); +bool pbvh_has_mask(const PBVH *pbvh); void pbvh_show_mask_set(PBVH *pbvh, bool show_mask); bool pbvh_has_face_sets(PBVH *pbvh); diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 085851ba5e6..fed155626ed 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -62,7 +62,7 @@ struct wmWindow; struct wmWindowManager; /* spacetype has everything stored to get an editor working, it gets initialized via - * ED_spacetypes_init() in editors/space_api/spacetypes.c */ + * #ED_spacetypes_init() in `editors/space_api/spacetypes.c` */ /* an editor in Blender is a combined ScrArea + SpaceType + SpaceData */ #define BKE_ST_MAXNAME 64 @@ -206,7 +206,7 @@ typedef struct ARegionType { * performed. * * This callback is not called on indirect changes of the current viewport (which could happen - * when the `v2d->tot is changed and `cur` is adopted accordingly). */ + * when the `v2d->tot is changed and `cur` is adopted accordingly). */ void (*on_view2d_changed)(const struct bContext *C, struct ARegion *region); /* custom drawing callbacks */ diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h index 7e3783a3ee9..8d1fe709355 100644 --- a/source/blender/blenkernel/BKE_shader_fx.h +++ b/source/blender/blenkernel/BKE_shader_fx.h @@ -172,7 +172,7 @@ void BKE_shaderfx_copydata_ex(struct ShaderFxData *fx, void BKE_shaderfx_copy(struct ListBase *dst, const struct ListBase *src); void BKE_shaderfx_foreach_ID_link(struct Object *ob, ShaderFxIDWalkFunc walk, void *userData); -bool BKE_shaderfx_has_gpencil(struct Object *ob); +bool BKE_shaderfx_has_gpencil(const struct Object *ob); void BKE_shaderfx_blend_write(struct BlendWriter *writer, struct ListBase *fxbase); void BKE_shaderfx_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb); diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh index 24b5a78e598..1aac2e311e3 100644 --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@ -32,6 +32,7 @@ #include "BKE_attribute_math.hh" struct Curve; +struct ListBase; class Spline; using SplinePtr = std::unique_ptr<Spline>; @@ -328,7 +329,8 @@ class BezierSpline final : public Spline { }; InterpolationData interpolation_data_from_index_factor(const float index_factor) const; - virtual blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const; + virtual blender::fn::GVArrayPtr interpolate_to_evaluated( + const blender::fn::GVArray &src) const override; void evaluate_segment(const int index, const int next_index, @@ -545,4 +547,6 @@ struct CurveEval { void assert_valid_point_attributes() const; }; -std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &curve); +std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &curve, + const ListBase &nurbs_list); +std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve); diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index 07bbeafb1ae..3816a822279 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -25,7 +25,7 @@ /* struct DerivedMesh is used directly */ #include "BKE_DerivedMesh.h" -/* Thread sync primitives used directly. */ +/* Thread sync primitives used directly. */ #include "BLI_threads.h" #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index c60d5c7bfec..c7120c60020 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -48,7 +48,7 @@ char *txt_to_buf(struct Text *text, int *r_buf_strlen); void txt_clean_text(struct Text *text); void txt_order_cursors(struct Text *text, const bool reverse); int txt_find_string(struct Text *text, const char *findstr, int wrap, int match_case); -bool txt_has_sel(struct Text *text); +bool txt_has_sel(const struct Text *text); int txt_get_span(struct TextLine *from, struct TextLine *to); void txt_move_up(struct Text *text, const bool sel); void txt_move_down(struct Text *text, const bool sel); @@ -85,13 +85,13 @@ bool txt_uncomment(struct Text *text); void txt_move_lines(struct Text *text, const int direction); void txt_duplicate_line(struct Text *text); int txt_setcurr_tab_spaces(struct Text *text, int space); -bool txt_cursor_is_line_start(struct Text *text); -bool txt_cursor_is_line_end(struct Text *text); +bool txt_cursor_is_line_start(const struct Text *text); +bool txt_cursor_is_line_end(const struct Text *text); int txt_calc_tab_left(struct TextLine *tl, int ch); int txt_calc_tab_right(struct TextLine *tl, int ch); -/* utility functions, could be moved somewhere more generic but are python/text related */ +/* Utility functions, could be moved somewhere more generic but are python/text related. */ int text_check_bracket(const char ch); bool text_check_delim(const char ch); bool text_check_digit(const char ch); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index c2544c06514..47145a7d6bd 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -161,7 +161,7 @@ struct MovieTrackingMarker *BKE_tracking_marker_get_exact(struct MovieTrackingTr struct MovieTrackingMarker *BKE_tracking_marker_ensure(struct MovieTrackingTrack *track, int framenr); -/* Get marker position, possibly interpolating interpolating gap between keyframed/tracked markers. +/* Get marker position, possibly interpolating gap between key-framed/tracked markers. * * The result marker frame number is set to the requested frame number. Its flags are 0 if the * marker is interpolated, and is set to original marker flag if there were no interpolation diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h index 620496864f5..efac5d9097f 100644 --- a/source/blender/blenkernel/BKE_undo_system.h +++ b/source/blender/blenkernel/BKE_undo_system.h @@ -178,7 +178,7 @@ UndoStack *BKE_undosys_stack_create(void); void BKE_undosys_stack_destroy(UndoStack *ustack); void BKE_undosys_stack_clear(UndoStack *ustack); void BKE_undosys_stack_clear_active(UndoStack *ustack); -bool BKE_undosys_stack_has_undo(UndoStack *ustack, const char *name); +bool BKE_undosys_stack_has_undo(const UndoStack *ustack, const char *name); void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain); void BKE_undosys_stack_init_from_context(UndoStack *ustack, struct bContext *C); UndoStep *BKE_undosys_stack_active_with_type(UndoStack *ustack, const UndoType *ut); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 0f36887b234..7a057d8fc1b 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -93,7 +93,7 @@ set(SRC intern/boids.c intern/bpath.c intern/brush.c - intern/bvhutils.c + intern/bvhutils.cc intern/cachefile.c intern/callbacks.c intern/camera.c @@ -165,6 +165,7 @@ set(SRC intern/layer_utils.c intern/lib_id.c intern/lib_id_delete.c + intern/lib_id_eval.c intern/lib_override.c intern/lib_query.c intern/lib_remap.c @@ -189,6 +190,7 @@ set(SRC intern/mesh_mapping.c intern/mesh_merge.c intern/mesh_mirror.c + intern/mesh_normals.c intern/mesh_remap.c intern/mesh_remesh_voxel.c intern/mesh_runtime.c diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 6caed3936d4..bc49c086532 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -960,7 +960,7 @@ static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md, mesh_output = mesh_component.release(); } - /* Return an empty mesh instead of null. */ + /* Return an empty mesh instead of null. */ if (mesh_output == nullptr) { mesh_output = BKE_mesh_new_nomain(0, 0, 0, 0, 0); BKE_mesh_copy_parameters_for_eval(mesh_output, input_mesh); @@ -973,7 +973,7 @@ static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md, static void mesh_calc_modifiers(struct Depsgraph *depsgraph, Scene *scene, Object *ob, - int useDeform, + const bool use_deform, const bool need_mapping, const CustomData_MeshMasks *dataMask, const int index, @@ -1068,7 +1068,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, BKE_modifiers_clear_errors(ob); /* Apply all leading deform modifiers. */ - if (useDeform) { + if (use_deform) { for (; md; md = md->next, md_datamask = md_datamask->next) { const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); @@ -1076,10 +1076,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, continue; } - if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) { - continue; - } - if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) { if (!deformed_verts) { deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); @@ -1128,7 +1124,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, continue; } - if (mti->type == eModifierTypeType_OnlyDeform && !useDeform) { + if (mti->type == eModifierTypeType_OnlyDeform && !use_deform) { continue; } @@ -1173,10 +1169,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, continue; } - if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) { - continue; - } - /* Add orco mesh as layer if needed by this modifier. */ if (mesh_final && mesh_orco && mti->requiredDataMask) { CustomData_MeshMasks mask = {0}; @@ -1937,7 +1929,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph, mesh_calc_modifiers(depsgraph, scene, ob, - 1, + true, need_mapping, dataMask, -1, @@ -2162,7 +2154,7 @@ Mesh *mesh_create_eval_final(Depsgraph *depsgraph, Mesh *final; mesh_calc_modifiers( - depsgraph, scene, ob, 1, false, dataMask, -1, false, false, nullptr, &final, nullptr); + depsgraph, scene, ob, true, false, dataMask, -1, false, false, nullptr, &final, nullptr); return final; } @@ -2176,7 +2168,7 @@ Mesh *mesh_create_eval_final_index_render(Depsgraph *depsgraph, Mesh *final; mesh_calc_modifiers( - depsgraph, scene, ob, 1, false, dataMask, index, false, false, nullptr, &final, nullptr); + depsgraph, scene, ob, true, false, dataMask, index, false, false, nullptr, &final, nullptr); return final; } @@ -2189,7 +2181,7 @@ Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph, Mesh *final; mesh_calc_modifiers( - depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final, nullptr); + depsgraph, scene, ob, false, false, dataMask, -1, false, false, nullptr, &final, nullptr); return final; } @@ -2202,7 +2194,7 @@ Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph, Mesh *final; mesh_calc_modifiers( - depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final, nullptr); + depsgraph, scene, ob, false, false, dataMask, -1, false, false, nullptr, &final, nullptr); return final; } diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 71d242e9c79..fdf3558abed 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -370,7 +370,7 @@ void set_active_action_group(bAction *act, bActionGroup *agrp, short select) /* Sync colors used for action/bone group with theme settings */ void action_group_colors_sync(bActionGroup *grp, const bActionGroup *ref_grp) { - /* only do color copying if using a custom color (i.e. not default color) */ + /* Only do color copying if using a custom color (i.e. not default color). */ if (grp->customCol) { if (grp->customCol > 0) { /* copy theme colors on-to group's custom color in case user tries to edit color */ @@ -486,8 +486,7 @@ void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve) /* If grp is NULL, that means we fell through, and this F-Curve should be added as the new * first since group is (effectively) the first group. Thus, the existing first F-Curve becomes - * the second in the chain, etc. etc. - */ + * the second in the chain, etc. */ if (grp == NULL) { BLI_insertlinkbefore(&act->curves, act->curves.first, fcurve); } @@ -1856,7 +1855,7 @@ void BKE_pose_blend_write(BlendWriter *writer, bPose *pose, bArmature *arm) /* Write channels */ LISTBASE_FOREACH (bPoseChannel *, chan, &pose->chanbase) { /* Write ID Properties -- and copy this comment EXACTLY for easy finding - * of library blocks that implement this.*/ + * of library blocks that implement this. */ if (chan->prop) { IDP_BlendWrite(writer, chan->prop); } diff --git a/source/blender/blenkernel/intern/action_mirror.c b/source/blender/blenkernel/intern/action_mirror.c index c975d2bfb9c..69e0091444b 100644 --- a/source/blender/blenkernel/intern/action_mirror.c +++ b/source/blender/blenkernel/intern/action_mirror.c @@ -343,7 +343,7 @@ static void action_flip_pchan(Object *ob_arm, } \ ((void)0) - /* Write the values back the the F-curves. */ + /* Write the values back the F-curves. */ WRITE_ARRAY_FLT(loc); WRITE_ARRAY_FLT(eul); WRITE_ARRAY_FLT(quat); diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 44b760aefc8..2f71dda17f2 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -946,7 +946,7 @@ static bool nlastrips_path_rename_fix(ID *owner_id, is_changed |= fcurves_path_rename_fix( owner_id, prefix, oldName, newName, oldKey, newKey, &strip->act->curves, verify_paths); } - /* Ignore own F-Curves, since those are local. */ + /* Ignore own F-Curves, since those are local. */ /* Check sub-strips (if meta-strips). */ is_changed |= nlastrips_path_rename_fix( owner_id, prefix, oldName, newName, oldKey, newKey, &strip->strips, verify_paths); @@ -1422,7 +1422,7 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id, * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]> * i.e. pose.bones["Bone"] */ -/* TODO: use BKE_animdata_main_cb for looping over all data */ +/* TODO: use BKE_animdata_main_cb for looping over all data. */ void BKE_animdata_fix_paths_rename_all_ex(Main *bmain, ID *ref_id, const char *prefix, diff --git a/source/blender/blenkernel/intern/anim_path.c b/source/blender/blenkernel/intern/anim_path.c index af2b386a30a..e2c2708101b 100644 --- a/source/blender/blenkernel/intern/anim_path.c +++ b/source/blender/blenkernel/intern/anim_path.c @@ -327,7 +327,7 @@ bool BKE_where_on_path(const Object *ob, } const Nurb *nu = nurbs->first; - /* make sure that first and last frame are included in the vectors here */ + /* Make sure that first and last frame are included in the vectors here. */ if (ELEM(nu->type, CU_POLY, CU_BEZIER, CU_NURBS)) { key_curve_position_weights(frac, w, KEY_LINEAR); } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index e347306e0ae..08a3f3fcf4f 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -852,7 +852,7 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, /* loop over strips, checking if they fall within the range */ for (strip = strips->first; strip; strip = strip->next) { - /* check if current time occurs within this strip */ + /* Check if current time occurs within this strip. */ if (IN_RANGE_INCL(ctime, strip->start, strip->end) || (strip->flag & NLASTRIP_FLAG_NO_TIME_MAP)) { /* this strip is active, so try to use it */ @@ -1564,7 +1564,7 @@ static bool nla_blend_get_inverted_strip_value(const int blendmode, } } -/** \returns true if solution exists and output is written to. */ +/** \returns true if solution exists and output is written to. */ static bool nla_combine_get_inverted_strip_value(const int mix_mode, float base_value, const float lower_value, @@ -2017,7 +2017,7 @@ static void nlaeval_fmodifiers_join_stacks(ListBase *result, ListBase *list1, Li { FModifier *fcm1, *fcm2; - /* if list1 is invalid... */ + /* if list1 is invalid... */ if (ELEM(NULL, list1, list1->first)) { if (list2 && list2->first) { result->first = list2->first; diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index bcfd34ab42f..579f671e2b0 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -200,7 +200,7 @@ bool BKE_appdir_folder_documents(char *dir) return true; } - /* Ghost couldn't give us a documents path, let's try if we can find it ourselves.*/ + /* Ghost couldn't give us a documents path, let's try if we can find it ourselves. */ const char *home_path = BKE_appdir_folder_home(); if (!home_path || !BLI_is_dir(home_path)) { diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index a57e1d6b2dd..d0604f4bfda 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -198,7 +198,7 @@ static void write_bone(BlendWriter *writer, Bone *bone) BLO_write_struct(writer, Bone, bone); /* Write ID Properties -- and copy this comment EXACTLY for easy finding - * of library blocks that implement this.*/ + * of library blocks that implement this. */ if (bone->prop) { IDP_BlendWrite(writer, bone->prop); } @@ -358,7 +358,7 @@ bArmature *BKE_armature_from_object(Object *ob) return NULL; } -int BKE_armature_bonelist_count(ListBase *lb) +int BKE_armature_bonelist_count(const ListBase *lb) { int i = 0; LISTBASE_FOREACH (Bone *, bone, lb) { @@ -1627,7 +1627,7 @@ void BKE_armature_mat_world_to_pose(Object *ob, const float inmat[4][4], float o return; } - /* get inverse of (armature) object's matrix */ + /* Get inverse of (armature) object's matrix. */ invert_m4_m4(obmat, ob->obmat); /* multiply given matrix by object's-inverse to find pose-space matrix */ @@ -2063,9 +2063,11 @@ void BKE_armature_mat_pose_to_delta(float delta_mat[4][4], * Used for Objects and Pose Channels, since both can have multiple rotation representations. * \{ */ -/* Called from RNA when rotation mode changes +/** + * Called from RNA when rotation mode changes * - the result should be that the rotations given in the provided pointers have had conversions - * applied (as appropriate), such that the rotation of the element hasn't 'visually' changed */ + * applied (as appropriate), such that the rotation of the element hasn't 'visually' changed. + */ void BKE_rotMode_change_values( float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode) { @@ -2333,7 +2335,7 @@ void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, const bool /* yoffs(b-1) + root(b) + bonemat(b) */ BKE_bone_offset_matrix_get(bone, offs_bone); - /* Compose the matrix for this bone */ + /* Compose the matrix for this bone. */ mul_m4_m4m4(bone->arm_mat, bone_parent->arm_mat, offs_bone); } else { diff --git a/source/blender/blenkernel/intern/armature_test.cc b/source/blender/blenkernel/intern/armature_test.cc index 366bbe3e37c..589337d9d01 100644 --- a/source/blender/blenkernel/intern/armature_test.cc +++ b/source/blender/blenkernel/intern/armature_test.cc @@ -121,7 +121,7 @@ TEST(vec_roll_to_mat3_normalized, Rotationmatrix) /* TODO: This test will pass after fixing T82455) */ /* If normalized_vector is close to -Y and * it has X and Z values above a threshold, - * apply the special case. */ + * apply the special case. */ { const float expected_roll_mat[3][3] = {{0.000000f, -9.99999975e-06f, 1.000000f}, {9.99999975e-06f, -0.999999881f, 9.99999975e-06f}, diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 4504f10967c..0f8956a1a91 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -837,7 +837,7 @@ void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph, Scene *scene, Object *ob BIK_init_tree(depsgraph, scene, object, ctime); /* construct the Spline IK trees * - this is not integrated as an IK plugin, since it should be able - * to function in conjunction with standard IK. */ + * to function in conjunction with standard IK. */ BKE_pose_splineik_init_tree(scene, object, ctime); } diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 8bbb3014dac..aa0af294bc3 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -1197,7 +1197,7 @@ static blender::bke::OutputAttribute create_output_attribute( cpp_type->size() * domain_size, cpp_type->alignment(), __func__); if (ignore_old_values) { /* This does nothing for trivially constructible types, but is necessary for correctness. */ - cpp_type->construct_default_n(data, domain); + cpp_type->default_construct_n(data, domain); } else { /* Fill the temporary array with values from the existing attribute. */ diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c index dfd49a347ca..9c9f898afef 100644 --- a/source/blender/blenkernel/intern/blender_copybuffer.c +++ b/source/blender/blenkernel/intern/blender_copybuffer.c @@ -87,7 +87,8 @@ bool BKE_copybuffer_read(Main *bmain_dst, ReportList *reports, const uint64_t id_types_mask) { - BlendHandle *bh = BLO_blendhandle_from_file(libname, reports); + BlendFileReadReport bf_reports = {.reports = reports}; + BlendHandle *bh = BLO_blendhandle_from_file(libname, &bf_reports); if (bh == NULL) { /* Error reports will have been made by BLO_blendhandle_from_file(). */ return false; @@ -133,7 +134,8 @@ int BKE_copybuffer_paste(bContext *C, BlendHandle *bh; const int id_tag_extra = 0; - bh = BLO_blendhandle_from_file(libname, reports); + BlendFileReadReport bf_reports = {.reports = reports}; + bh = BLO_blendhandle_from_file(libname, &bf_reports); if (bh == NULL) { /* error reports will have been made by BLO_blendhandle_from_file() */ diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c index ba41786c7fd..411ece21599 100644 --- a/source/blender/blenkernel/intern/blender_undo.c +++ b/source/blender/blenkernel/intern/blender_undo.c @@ -78,9 +78,10 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu, if (UNDO_DISK) { const struct BlendFileReadParams params = {0}; - struct BlendFileData *bfd = BKE_blendfile_read(mfu->filename, ¶ms, NULL); + BlendFileReadReport bf_reports = {.reports = NULL}; + struct BlendFileData *bfd = BKE_blendfile_read(mfu->filename, ¶ms, &bf_reports); if (bfd != NULL) { - BKE_blendfile_read_setup(C, bfd, ¶ms, NULL); + BKE_blendfile_read_setup(C, bfd, ¶ms, &bf_reports); success = true; } } @@ -93,7 +94,7 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu, struct BlendFileData *bfd = BKE_blendfile_read_from_memfile( bmain, &mfu->memfile, ¶ms, NULL); if (bfd != NULL) { - BKE_blendfile_read_setup(C, bfd, ¶ms, NULL); + BKE_blendfile_read_setup(C, bfd, ¶ms, &(BlendFileReadReport){NULL}); success = true; } } diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index e335dd4bdcd..f31d8f5ade7 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -36,6 +36,8 @@ #include "BLI_system.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "IMB_colormanagement.h" #include "BKE_addon.h" @@ -136,7 +138,7 @@ static void setup_app_userdef(BlendFileData *bfd) static void setup_app_data(bContext *C, BlendFileData *bfd, const struct BlendFileReadParams *params, - ReportList *reports) + BlendFileReadReport *reports) { Main *bmain = G_MAIN; Scene *curscene = NULL; @@ -155,7 +157,7 @@ static void setup_app_data(bContext *C, /* may happen with library files - UNDO file should never have NULL curscene (but may have a * NULL curscreen)... */ else if (ELEM(NULL, bfd->curscreen, bfd->curscene)) { - BKE_report(reports, RPT_WARNING, "Library file, loading empty scene"); + BKE_report(reports->reports, RPT_WARNING, "Library file, loading empty scene"); mode = LOAD_UI_OFF; } else if (G.fileflags & G_FILE_NO_UI) { @@ -270,7 +272,7 @@ static void setup_app_data(bContext *C, /* We need to tag this here because events may be handled immediately after. * only the current screen is important because we won't have to handle - * events from multiple screens at once.*/ + * events from multiple screens at once. */ if (curscreen) { BKE_screen_gizmo_tag_refresh(curscreen); } @@ -396,11 +398,17 @@ static void setup_app_data(bContext *C, } if (mode != LOAD_UNDO && !USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) { + reports->duration.lib_overrides_resync = PIL_check_seconds_timer(); + BKE_lib_override_library_main_resync( bmain, curscene, bfd->cur_view_layer ? bfd->cur_view_layer : BKE_view_layer_default_view(curscene), reports); + + reports->duration.lib_overrides_resync = PIL_check_seconds_timer() - + reports->duration.lib_overrides_resync; + /* We need to rebuild some of the deleted override rules (for UI feedback purpose). */ BKE_lib_override_library_main_operations_create(bmain, true); } @@ -409,7 +417,7 @@ static void setup_app_data(bContext *C, static void setup_app_blend_file_data(bContext *C, BlendFileData *bfd, const struct BlendFileReadParams *params, - ReportList *reports) + BlendFileReadReport *reports) { if ((params->skip_flags & BLO_READ_SKIP_USERDEF) == 0) { setup_app_userdef(bfd); @@ -419,12 +427,12 @@ static void setup_app_blend_file_data(bContext *C, } } -static void handle_subversion_warning(Main *main, ReportList *reports) +static void handle_subversion_warning(Main *main, BlendFileReadReport *reports) { if (main->minversionfile > BLENDER_FILE_VERSION || (main->minversionfile == BLENDER_FILE_VERSION && main->minsubversionfile > BLENDER_FILE_SUBVERSION)) { - BKE_reportf(reports, + BKE_reportf(reports->reports, RPT_ERROR, "File written by newer Blender binary (%d.%d), expect loss of data!", main->minversionfile, @@ -443,7 +451,7 @@ static void handle_subversion_warning(Main *main, ReportList *reports) void BKE_blendfile_read_setup_ex(bContext *C, BlendFileData *bfd, const struct BlendFileReadParams *params, - ReportList *reports, + BlendFileReadReport *reports, /* Extra args. */ const bool startup_update_defaults, const char *startup_app_template) @@ -460,7 +468,7 @@ void BKE_blendfile_read_setup_ex(bContext *C, void BKE_blendfile_read_setup(bContext *C, BlendFileData *bfd, const struct BlendFileReadParams *params, - ReportList *reports) + BlendFileReadReport *reports) { BKE_blendfile_read_setup_ex(C, bfd, params, reports, false, NULL); } @@ -470,7 +478,7 @@ void BKE_blendfile_read_setup(bContext *C, */ struct BlendFileData *BKE_blendfile_read(const char *filepath, const struct BlendFileReadParams *params, - ReportList *reports) + BlendFileReadReport *reports) { /* Don't print startup file loading. */ if (params->is_startup == false) { @@ -482,7 +490,7 @@ struct BlendFileData *BKE_blendfile_read(const char *filepath, handle_subversion_warning(bfd->main, reports); } else { - BKE_reports_prependf(reports, "Loading '%s' failed: ", filepath); + BKE_reports_prependf(reports->reports, "Loading '%s' failed: ", filepath); } return bfd; } @@ -559,7 +567,9 @@ UserDef *BKE_blendfile_userdef_read(const char *filepath, ReportList *reports) BlendFileData *bfd; UserDef *userdef = NULL; - bfd = BLO_read_from_file(filepath, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF, reports); + bfd = BLO_read_from_file(filepath, + BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF, + &(struct BlendFileReadReport){.reports = reports}); if (bfd) { if (bfd->user) { userdef = bfd->user; @@ -770,7 +780,8 @@ WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepat WorkspaceConfigFileData *workspace_config = NULL; if (filepath) { - bfd = BLO_read_from_file(filepath, BLO_READ_SKIP_USERDEF, reports); + bfd = BLO_read_from_file( + filepath, BLO_READ_SKIP_USERDEF, &(struct BlendFileReadReport){.reports = reports}); } else { bfd = BLO_read_from_memory(filebuf, filelength, BLO_READ_SKIP_USERDEF, reports); diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.cc index 116e6279657..3dea49d1953 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.cc @@ -21,9 +21,9 @@ * \ingroup bke */ -#include <math.h> -#include <stdio.h> -#include <string.h> +#include <cmath> +#include <cstdio> +#include <cstring> #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -46,15 +46,15 @@ /** \name BVHCache * \{ */ -typedef struct BVHCacheItem { +struct BVHCacheItem { bool is_filled; BVHTree *tree; -} BVHCacheItem; +}; -typedef struct BVHCache { +struct BVHCache { BVHCacheItem items[BVHTREE_MAX_ITEM]; ThreadMutex mutex; -} BVHCache; +}; /** * Queries a bvhcache for the cache bvhtree of the request type @@ -74,14 +74,14 @@ static bool bvhcache_find(BVHCache **bvh_cache_p, if (r_locked) { *r_locked = false; } - if (*bvh_cache_p == NULL) { + if (*bvh_cache_p == nullptr) { if (!do_lock) { /* Cache does not exist and no lock is requested. */ return false; } /* Lazy initialization of the bvh_cache using the `mesh_eval_mutex`. */ BLI_mutex_lock(mesh_eval_mutex); - if (*bvh_cache_p == NULL) { + if (*bvh_cache_p == nullptr) { *bvh_cache_p = bvhcache_init(); } BLI_mutex_unlock(mesh_eval_mutex); @@ -94,7 +94,7 @@ static bool bvhcache_find(BVHCache **bvh_cache_p, } if (do_lock) { BLI_mutex_lock(&bvh_cache->mutex); - bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, NULL, NULL); + bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, nullptr, nullptr); if (in_cache) { BLI_mutex_unlock(&bvh_cache->mutex); return in_cache; @@ -113,11 +113,11 @@ static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started) bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree) { - if (bvh_cache == NULL) { + if (bvh_cache == nullptr) { return false; } - for (BVHCacheType i = 0; i < BVHTREE_MAX_ITEM; i++) { + for (int i = 0; i < BVHTREE_MAX_ITEM; i++) { if (bvh_cache->items[i].tree == tree) { return true; } @@ -127,7 +127,7 @@ bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree) BVHCache *bvhcache_init(void) { - BVHCache *cache = MEM_callocN(sizeof(BVHCache), __func__); + BVHCache *cache = (BVHCache *)MEM_callocN(sizeof(BVHCache), __func__); BLI_mutex_init(&cache->mutex); return cache; } @@ -137,7 +137,7 @@ BVHCache *bvhcache_init(void) * as that will be done when the cache is freed. * * A call to this assumes that there was no previous cached tree of the given type - * \warning The #BVHTree can be NULL. + * \warning The #BVHTree can be nullptr. */ static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType type) { @@ -152,10 +152,10 @@ static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType typ */ void bvhcache_free(BVHCache *bvh_cache) { - for (BVHCacheType index = 0; index < BVHTREE_MAX_ITEM; index++) { + for (int index = 0; index < BVHTREE_MAX_ITEM; index++) { BVHCacheItem *item = &bvh_cache->items[index]; BLI_bvhtree_free(item->tree); - item->tree = NULL; + item->tree = nullptr; } BLI_mutex_end(&bvh_cache->mutex); MEM_freeN(bvh_cache); @@ -197,9 +197,10 @@ float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, float dist; #ifdef USE_KDOPBVH_WATERTIGHT - if (isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc, v0, v1, v2, &dist, NULL)) + if (isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc, v0, v1, v2, &dist, nullptr)) #else - if (isect_ray_tri_epsilon_v3(ray->origin, ray->direction, v0, v1, v2, &dist, NULL, FLT_EPSILON)) + if (isect_ray_tri_epsilon_v3( + ray->origin, ray->direction, v0, v1, v2, &dist, nullptr, FLT_EPSILON)) #endif { return dist; @@ -247,7 +248,7 @@ static void mesh_faces_nearest_point(void *userdata, t0 = vert[face->v1].co; t1 = vert[face->v2].co; t2 = vert[face->v3].co; - t3 = face->v4 ? vert[face->v4].co : NULL; + t3 = face->v4 ? vert[face->v4].co : nullptr; do { float nearest_tmp[3], dist_sq; @@ -264,7 +265,7 @@ static void mesh_faces_nearest_point(void *userdata, t1 = t2; t2 = t3; - t3 = NULL; + t3 = nullptr; } while (t2); } @@ -300,7 +301,7 @@ static void editmesh_looptri_nearest_point(void *userdata, const float co[3], BVHTreeNearest *nearest) { - const BVHTreeFromEditMesh *data = userdata; + const BVHTreeFromEditMesh *data = (const BVHTreeFromEditMesh *)userdata; BMEditMesh *em = data->em; const BMLoop **ltri = (const BMLoop **)em->looptris[index]; @@ -339,7 +340,7 @@ static void mesh_faces_spherecast(void *userdata, t0 = vert[face->v1].co; t1 = vert[face->v2].co; t2 = vert[face->v3].co; - t3 = face->v4 ? vert[face->v4].co : NULL; + t3 = face->v4 ? vert[face->v4].co : nullptr; do { float dist; @@ -360,7 +361,7 @@ static void mesh_faces_spherecast(void *userdata, t1 = t2; t2 = t3; - t3 = NULL; + t3 = nullptr; } while (t2); } @@ -457,7 +458,7 @@ static void mesh_edges_nearest_point(void *userdata, } } -/* Helper, does all the point-spherecast work actually. */ +/* Helper, does all the point-sphere-cast work actually. */ static void mesh_verts_spherecast_do(int index, const float v[3], const BVHTreeRay *ray, @@ -484,7 +485,7 @@ static void editmesh_verts_spherecast(void *userdata, const BVHTreeRay *ray, BVHTreeRayHit *hit) { - const BVHTreeFromEditMesh *data = userdata; + const BVHTreeFromEditMesh *data = (const BVHTreeFromEditMesh *)userdata; BMVert *eve = BM_vert_at_index(data->em->bm, index); mesh_verts_spherecast_do(index, eve->co, ray, hit); @@ -600,7 +601,7 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree(float epsilon, const BLI_bitmap *verts_mask, int verts_num_active) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (verts_mask) { BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num)); @@ -637,9 +638,9 @@ static void bvhtree_from_mesh_verts_setup_data(BVHTreeFromMesh *data, data->tree = tree; data->cached = is_cached; - /* a NULL nearest callback works fine + /* a nullptr nearest callback works fine * remember the min distance to point is the same as the min distance to BV of point */ - data->nearest_callback = NULL; + data->nearest_callback = nullptr; data->raycast_callback = mesh_verts_spherecast; data->vert = vert; @@ -658,7 +659,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { bool lock_started = false; @@ -671,7 +672,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, bvhtree_balance(tree, true); /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); bvhcache_insert(*bvh_cache_p, tree, bvh_cache_type); data->cached = true; } @@ -687,9 +688,9 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, memset(data, 0, sizeof(*data)); data->tree = tree; data->em = em; - data->nearest_callback = NULL; + data->nearest_callback = nullptr; data->raycast_callback = editmesh_verts_spherecast; - data->cached = bvh_cache_p != NULL; + data->cached = bvh_cache_p != nullptr; } return tree; @@ -699,11 +700,11 @@ BVHTree *bvhtree_from_editmesh_verts( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) { return bvhtree_from_editmesh_verts_ex( - data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL); + data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr); } /** - * Builds a bvh tree where nodes are the given vertices (note: does not copy given mverts!). + * Builds a bvh tree where nodes are the given vertices (note: does not copy given `vert`!). * \param vert_allocated: if true, vert freeing will be done when freeing data. * \param verts_mask: if not null, true elements give which vert to add to BVH tree. * \param verts_num_active: if >= 0, number of active verts to add to BVH tree @@ -724,7 +725,7 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, { bool in_cache = false; bool lock_started = false; - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } @@ -732,11 +733,11 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, if (in_cache == false) { tree = bvhtree_from_mesh_verts_create_tree( epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active); - bvhtree_balance(tree, bvh_cache_p != NULL); + bvhtree_balance(tree, bvh_cache_p != nullptr); if (bvh_cache_p) { /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); BVHCache *bvh_cache = *bvh_cache_p; bvhcache_insert(bvh_cache, tree, bvh_cache_type); in_cache = true; @@ -807,7 +808,7 @@ static BVHTree *bvhtree_from_mesh_edges_create_tree(const MVert *vert, int tree_type, int axis) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (edges_mask) { BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edge_num)); @@ -817,7 +818,7 @@ static BVHTree *bvhtree_from_mesh_edges_create_tree(const MVert *vert, } if (edges_num_active) { - /* Create a bvh-tree of the given target */ + /* Create a BVH-tree of the given target */ tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis); if (tree) { for (int i = 0; i < edge_num; i++) { @@ -871,7 +872,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { bool lock_started = false; @@ -883,7 +884,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, epsilon, tree_type, axis, em, edges_mask, edges_num_active); bvhtree_balance(tree, true); /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); bvhcache_insert(bvh_cache, tree, bvh_cache_type); data->cached = true; } @@ -899,9 +900,9 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, memset(data, 0, sizeof(*data)); data->tree = tree; data->em = em; - data->nearest_callback = NULL; /* TODO */ - data->raycast_callback = NULL; /* TODO */ - data->cached = bvh_cache_p != NULL; + data->nearest_callback = nullptr; /* TODO */ + data->raycast_callback = nullptr; /* TODO */ + data->cached = bvh_cache_p != nullptr; } return tree; @@ -911,7 +912,7 @@ BVHTree *bvhtree_from_editmesh_edges( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) { return bvhtree_from_editmesh_edges_ex( - data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL); + data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr); } /** @@ -939,7 +940,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data, { bool in_cache = false; bool lock_started = false; - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } @@ -953,7 +954,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data, BVHCache *bvh_cache = *bvh_cache_p; /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); bvhcache_insert(bvh_cache, tree, bvh_cache_type); in_cache = true; } @@ -988,7 +989,7 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon, const BLI_bitmap *faces_mask, int faces_num_active) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (faces_num) { if (faces_mask) { @@ -998,8 +999,8 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon, faces_num_active = faces_num; } - /* Create a bvh-tree of the given target */ - /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */ + /* Create a BVH-tree of the given target. */ + // printf("%s: building BVH, total=%d\n", __func__, numFaces); tree = BLI_bvhtree_new(faces_num_active, epsilon, tree_type, axis); if (tree) { if (vert && face) { @@ -1074,7 +1075,7 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data, { bool in_cache = false; bool lock_started = false; - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } @@ -1082,11 +1083,11 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data, if (in_cache == false) { tree = bvhtree_from_mesh_faces_create_tree( epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active); - bvhtree_balance(tree, bvh_cache_p != NULL); + bvhtree_balance(tree, bvh_cache_p != nullptr); if (bvh_cache_p) { /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); BVHCache *bvh_cache = *bvh_cache_p; bvhcache_insert(bvh_cache, tree, bvh_cache_type); in_cache = true; @@ -1117,7 +1118,7 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon, const BLI_bitmap *looptri_mask, int looptri_num_active) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; const int looptri_num = em->tottri; if (looptri_num) { @@ -1128,11 +1129,11 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon, looptri_num_active = looptri_num; } - /* Create a bvh-tree of the given target */ - /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */ + /* Create a BVH-tree of the given target */ + // printf("%s: building BVH, total=%d\n", __func__, numFaces); tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis); if (tree) { - const struct BMLoop *(*looptris)[3] = (void *)em->looptris; + const BMLoop *(*looptris)[3] = (const BMLoop *(*)[3])em->looptris; /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden * and/or selected. Even if the faces themselves are not selected for the snapped @@ -1143,7 +1144,7 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon, bool insert = looptri_mask ? BLI_BITMAP_TEST_BOOL(looptri_mask, i) : true; if (insert) { - /* No reason found to block hit-testing the triangle for snap, so insert it now.*/ + /* No reason found to block hit-testing the triangle for snap, so insert it now. */ float co[3][3]; copy_v3_v3(co[0], ltri[0]->v->co); copy_v3_v3(co[1], ltri[1]->v->co); @@ -1169,7 +1170,7 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon, const BLI_bitmap *looptri_mask, int looptri_num_active) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (looptri_mask) { BLI_assert(IN_RANGE_INCL(looptri_num_active, 0, looptri_num)); @@ -1179,8 +1180,8 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon, } if (looptri_num_active) { - /* Create a bvh-tree of the given target */ - /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */ + /* Create a BVH-tree of the given target */ + // printf("%s: building BVH, total=%d\n", __func__, numFaces); tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis); if (tree) { if (vert && looptri) { @@ -1247,7 +1248,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, /* BMESH specific check that we have tessfaces, * we _could_ tessellate here but rather not - campbell */ - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { bool lock_started = false; bool in_cache = bvhcache_find( @@ -1260,7 +1261,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, epsilon, tree_type, axis, em, looptri_mask, looptri_num_active); /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); bvhcache_insert(bvh_cache, tree, bvh_cache_type); } bvhcache_unlock(bvh_cache, lock_started); @@ -1276,7 +1277,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, data->nearest_callback = editmesh_looptri_nearest_point; data->raycast_callback = editmesh_looptri_spherecast; data->em = em; - data->cached = bvh_cache_p != NULL; + data->cached = bvh_cache_p != nullptr; } return tree; } @@ -1285,7 +1286,7 @@ BVHTree *bvhtree_from_editmesh_looptri( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) { return bvhtree_from_editmesh_looptri_ex( - data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL); + data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr); } /** @@ -1312,7 +1313,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, { bool in_cache = false; bool lock_started = false; - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } @@ -1329,7 +1330,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, looptri_mask, looptri_num_active); - bvhtree_balance(tree, bvh_cache_p != NULL); + bvhtree_balance(tree, bvh_cache_p != nullptr); if (bvh_cache_p) { BVHCache *bvh_cache = *bvh_cache_p; @@ -1437,19 +1438,22 @@ static BLI_bitmap *looptri_no_hidden_map_get(const MPoly *mpoly, /** * Builds or queries a bvhcache for the cache bvhtree of the request type. + * + * \note This function only fills a cache, and therefore the mesh argument can + * be considered logically const. Concurrent access is protected by a mutex. */ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, - struct Mesh *mesh, + const struct Mesh *mesh, const BVHCacheType bvh_cache_type, const int tree_type) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime.bvh_cache; ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex; - bool is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL); + const bool is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, nullptr, nullptr); - if (is_cached && tree == NULL) { + if (is_cached && tree == nullptr) { memset(data, 0, sizeof(*data)); return tree; } @@ -1458,7 +1462,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, case BVHTREE_FROM_VERTS: case BVHTREE_FROM_LOOSEVERTS: if (is_cached == false) { - BLI_bitmap *loose_verts_mask = NULL; + BLI_bitmap *loose_verts_mask = nullptr; int loose_vert_len = -1; int verts_len = mesh->totvert; @@ -1480,7 +1484,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, bvh_cache_p, mesh_eval_mutex); - if (loose_verts_mask != NULL) { + if (loose_verts_mask != nullptr) { MEM_freeN(loose_verts_mask); } } @@ -1493,7 +1497,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, case BVHTREE_FROM_EDGES: case BVHTREE_FROM_LOOSEEDGES: if (is_cached == false) { - BLI_bitmap *loose_edges_mask = NULL; + BLI_bitmap *loose_edges_mask = nullptr; int loose_edges_len = -1; int edges_len = mesh->totedge; @@ -1516,7 +1520,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, bvh_cache_p, mesh_eval_mutex); - if (loose_edges_mask != NULL) { + if (loose_edges_mask != nullptr) { MEM_freeN(loose_edges_mask); } } @@ -1538,7 +1542,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, mesh->mface, num_faces, false, - NULL, + nullptr, -1, 0.0, tree_type, @@ -1561,7 +1565,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, int looptri_len = BKE_mesh_runtime_looptri_len(mesh); int looptri_mask_active_len = -1; - BLI_bitmap *looptri_mask = NULL; + BLI_bitmap *looptri_mask = nullptr; if (bvh_cache_type == BVHTREE_FROM_LOOPTRI_NO_HIDDEN) { looptri_mask = looptri_no_hidden_map_get( mesh->mpoly, looptri_len, &looptri_mask_active_len); @@ -1584,7 +1588,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, bvh_cache_p, mesh_eval_mutex); - if (looptri_mask != NULL) { + if (looptri_mask != nullptr) { MEM_freeN(looptri_mask); } } @@ -1603,7 +1607,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, break; } - if (data->tree != NULL) { + if (data->tree != nullptr) { #ifdef DEBUG if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) { printf("tree_type %d obtained instead of %d\n", @@ -1631,15 +1635,15 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; bool is_cached = false; memset(data, 0, sizeof(*data)); if (bvh_cache_p) { - is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL); + is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, nullptr, nullptr); - if (is_cached && tree == NULL) { + if (is_cached && tree == nullptr) { return tree; } } @@ -1650,31 +1654,55 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, switch (bvh_cache_type) { case BVHTREE_FROM_EM_VERTS: if (is_cached == false) { - tree = bvhtree_from_editmesh_verts_ex( - data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex); + tree = bvhtree_from_editmesh_verts_ex(data, + em, + nullptr, + -1, + 0.0f, + tree_type, + 6, + bvh_cache_type, + bvh_cache_p, + mesh_eval_mutex); } else { - data->nearest_callback = NULL; + data->nearest_callback = nullptr; data->raycast_callback = editmesh_verts_spherecast; } break; case BVHTREE_FROM_EM_EDGES: if (is_cached == false) { - tree = bvhtree_from_editmesh_edges_ex( - data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex); + tree = bvhtree_from_editmesh_edges_ex(data, + em, + nullptr, + -1, + 0.0f, + tree_type, + 6, + bvh_cache_type, + bvh_cache_p, + mesh_eval_mutex); } else { /* Setup BVHTreeFromMesh */ - data->nearest_callback = NULL; /* TODO */ - data->raycast_callback = NULL; /* TODO */ + data->nearest_callback = nullptr; /* TODO */ + data->raycast_callback = nullptr; /* TODO */ } break; case BVHTREE_FROM_EM_LOOPTRI: if (is_cached == false) { - tree = bvhtree_from_editmesh_looptri_ex( - data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex); + tree = bvhtree_from_editmesh_looptri_ex(data, + em, + nullptr, + -1, + 0.0f, + tree_type, + 6, + bvh_cache_type, + bvh_cache_p, + mesh_eval_mutex); } else { /* Setup BVHTreeFromMesh */ @@ -1694,7 +1722,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, break; } - if (data->tree != NULL) { + if (data->tree != nullptr) { #ifdef DEBUG if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) { printf("tree_type %d obtained instead of %d\n", @@ -1763,7 +1791,7 @@ BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data, { BVHTree *tree = BLI_bvhtree_new(pointcloud->totpoint, 0.0f, tree_type, 6); if (!tree) { - return NULL; + return nullptr; } for (int i = 0; i < pointcloud->totpoint; i++) { @@ -1774,7 +1802,7 @@ BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data, data->coords = pointcloud->co; data->tree = tree; - data->nearest_callback = NULL; + data->nearest_callback = nullptr; return tree; } diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index bab9e2a5592..5172b067eba 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -615,7 +615,7 @@ static void camera_frame_fit_data_init(const Scene *scene, BKE_camera_params_init(params); BKE_camera_params_from_object(params, ob); - /* compute matrix, viewplane, .. */ + /* Compute matrix, view-plane, etc. */ if (scene) { BKE_camera_params_compute_viewplane( params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp); @@ -975,7 +975,7 @@ void BKE_camera_multiview_window_matrix(const RenderData *rd, BKE_camera_params_from_object(¶ms, camera); BKE_camera_multiview_params(rd, ¶ms, camera, viewname); - /* Compute matrix, viewplane, .. */ + /* Compute matrix, view-plane, etc. */ BKE_camera_params_compute_viewplane(¶ms, rd->xsch, rd->ysch, rd->xasp, rd->yasp); BKE_camera_params_compute_matrix(¶ms); diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index aa51ee0017e..24266dc6bea 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -79,7 +79,8 @@ static bool collection_object_remove(Main *bmain, static CollectionChild *collection_find_child(Collection *parent, Collection *collection); static CollectionParent *collection_find_parent(Collection *child, Collection *collection); -static bool collection_find_child_recursive(Collection *parent, Collection *collection); +static bool collection_find_child_recursive(const Collection *parent, + const Collection *collection); /** \} */ @@ -710,7 +711,7 @@ Collection *BKE_collection_duplicate(Main *bmain, * unless its duplication is a sub-process of another one. */ collection_new->id.tag &= ~LIB_TAG_NEW; - /* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW.*/ + /* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */ BKE_libblock_relink_to_newid(&collection_new->id); #ifndef NDEBUG @@ -1458,7 +1459,7 @@ bool BKE_collection_cycle_find(Collection *new_ancestor, Collection *collection) } /* Find possible objects in collection or its children, that would instantiate the given ancestor - * collection (that would also make a fully invalid cycle of dependencies) .*/ + * collection (that would also make a fully invalid cycle of dependencies). */ return collection_instance_find_recursive(collection, new_ancestor); } @@ -1521,9 +1522,9 @@ static CollectionChild *collection_find_child(Collection *parent, Collection *co return BLI_findptr(&parent->children, collection, offsetof(CollectionChild, collection)); } -static bool collection_find_child_recursive(Collection *parent, Collection *collection) +static bool collection_find_child_recursive(const Collection *parent, const Collection *collection) { - LISTBASE_FOREACH (CollectionChild *, child, &parent->children) { + LISTBASE_FOREACH (const CollectionChild *, child, &parent->children) { if (child->collection == collection) { return true; } @@ -1536,7 +1537,7 @@ static bool collection_find_child_recursive(Collection *parent, Collection *coll return false; } -bool BKE_collection_has_collection(Collection *parent, Collection *collection) +bool BKE_collection_has_collection(const Collection *parent, const Collection *collection) { return collection_find_child_recursive(parent, collection); } diff --git a/source/blender/blenkernel/intern/colorband.c b/source/blender/blenkernel/intern/colorband.c index 2884d7b3204..d6b318caa5e 100644 --- a/source/blender/blenkernel/intern/colorband.c +++ b/source/blender/blenkernel/intern/colorband.c @@ -490,7 +490,7 @@ bool BKE_colorband_evaluate(const ColorBand *coba, float in, float out[4]) } if (ELEM(ipotype, COLBAND_INTERP_B_SPLINE, COLBAND_INTERP_CARDINAL)) { - /* ipo from right to left: 3 2 1 0 */ + /* Interpolate from right to left: `3 2 1 0`. */ float t[4]; if (a >= coba->tot - 1) { diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index f30fcc54b23..1484021cb9d 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -638,7 +638,7 @@ static void curvemap_make_table(const CurveMapping *cumap, CurveMap *cuma) cuma->mintable = clipr->xmin; cuma->maxtable = clipr->xmax; - /* hrmf... we now rely on blender ipo beziers, these are more advanced */ + /* Rely on Blender interpolation for bezier curves, support extra functionality here as well. */ bezt = MEM_callocN(cuma->totpoint * sizeof(BezTriple), "beztarr"); for (int a = 0; a < cuma->totpoint; a++) { @@ -1280,12 +1280,12 @@ static void save_sample_line( { float yuv[3]; - /* vectorscope*/ + /* Vector-scope. */ rgb_to_yuv(rgb[0], rgb[1], rgb[2], &yuv[0], &yuv[1], &yuv[2], BLI_YUV_ITU_BT709); scopes->vecscope[idx + 0] = yuv[1]; scopes->vecscope[idx + 1] = yuv[2]; - /* waveform */ + /* Waveform. */ switch (scopes->wavefrm_mode) { case SCOPES_WAVEFRM_RGB: case SCOPES_WAVEFRM_RGB_PARADE: @@ -1497,7 +1497,7 @@ static void scopes_update_cb(void *__restrict userdata, mul_v3_fl(ycc, INV_255); minmax_v3v3_v3(min, max, ycc); } - /* increment count for histo*/ + /* Increment count for histo. */ bin_lum[get_bin_float(luma)]++; bin_r[get_bin_float(rgba[0])]++; bin_g[get_bin_float(rgba[1])]++; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 826c79c3764..fe207f81d7d 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -222,7 +222,7 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob) /* XXX This would seem to be in wrong order. However, it does not work in 'right' order - * would be nice to understand why premul is needed here instead of usual postmul? * In any case, we **do not get a delta** here (e.g. startmat & matrix having same location, - * still gives a 'delta' with non-null translation component :/ ).*/ + * still gives a 'delta' with non-null translation component :/ ). */ mul_m4_m4m4(delta, cob->matrix, imat); /* copy matrices back to source */ @@ -272,7 +272,7 @@ void BKE_constraint_mat_convertspace(Object *ob, float diff_mat[4][4]; float imat[4][4]; - /* prevent crashes in these unlikely events */ + /* Prevent crashes in these unlikely events. */ if (ob == NULL || mat == NULL) { return; } @@ -299,7 +299,10 @@ void BKE_constraint_mat_convertspace(Object *ob, mul_m4_m4m4(mat, imat, mat); /* Use pose-space as stepping stone for other spaces. */ - if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { + if (ELEM(to, + CONSTRAINT_SPACE_LOCAL, + CONSTRAINT_SPACE_PARLOCAL, + CONSTRAINT_SPACE_OWNLOCAL)) { /* Call self with slightly different values. */ BKE_constraint_mat_convertspace( ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); @@ -315,6 +318,17 @@ void BKE_constraint_mat_convertspace(Object *ob, BKE_armature_mat_pose_to_bone(pchan, mat, mat); } } + /* pose to owner local */ + else if (to == CONSTRAINT_SPACE_OWNLOCAL) { + /* pose to local */ + if (pchan->bone) { + BKE_armature_mat_pose_to_bone(pchan, mat, mat); + } + + /* local to owner local (recursive) */ + BKE_constraint_mat_convertspace( + ob, pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, to, keep_scale); + } /* pose to local with parent */ else if (to == CONSTRAINT_SPACE_PARLOCAL) { if (pchan->bone) { @@ -336,17 +350,59 @@ void BKE_constraint_mat_convertspace(Object *ob, } case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */ { + /* local to owner local */ + if (to == CONSTRAINT_SPACE_OWNLOCAL) { + if (pchan->bone) { + copy_m4_m4(diff_mat, pchan->bone->arm_mat); + + if (cob && cob->pchan && cob->pchan->bone) { + invert_m4_m4(imat, cob->pchan->bone->arm_mat); + mul_m4_m4m4(diff_mat, imat, diff_mat); + } + + zero_v3(diff_mat[3]); + invert_m4_m4(imat, diff_mat); + mul_m4_series(mat, diff_mat, mat, imat); + } + } /* local to pose - do inverse procedure that was done for pose to local */ + else { + if (pchan->bone) { + /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ + BKE_armature_mat_bone_to_pose(pchan, mat, mat); + } + + /* use pose-space as stepping stone for other spaces */ + if (ELEM(to, + CONSTRAINT_SPACE_WORLD, + CONSTRAINT_SPACE_PARLOCAL, + CONSTRAINT_SPACE_CUSTOM)) { + /* call self with slightly different values */ + BKE_constraint_mat_convertspace( + ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); + } + } + break; + } + case CONSTRAINT_SPACE_OWNLOCAL: { /* -------------- FROM OWNER LOCAL ---------- */ + /* owner local to local */ if (pchan->bone) { - /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ - BKE_armature_mat_bone_to_pose(pchan, mat, mat); + copy_m4_m4(diff_mat, pchan->bone->arm_mat); + + if (cob && cob->pchan && cob->pchan->bone) { + invert_m4_m4(imat, cob->pchan->bone->arm_mat); + mul_m4_m4m4(diff_mat, imat, diff_mat); + } + + zero_v3(diff_mat[3]); + invert_m4_m4(imat, diff_mat); + mul_m4_series(mat, imat, mat, diff_mat); } - /* use pose-space as stepping stone for other spaces */ - if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_CUSTOM)) { + if (to != CONSTRAINT_SPACE_LOCAL) { /* call self with slightly different values */ BKE_constraint_mat_convertspace( - ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); + ob, pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, to, keep_scale); } break; } @@ -358,7 +414,11 @@ void BKE_constraint_mat_convertspace(Object *ob, } /* use pose-space as stepping stone for other spaces */ - if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_CUSTOM)) { + if (ELEM(to, + CONSTRAINT_SPACE_WORLD, + CONSTRAINT_SPACE_LOCAL, + CONSTRAINT_SPACE_OWNLOCAL, + CONSTRAINT_SPACE_CUSTOM)) { /* call self with slightly different values */ BKE_constraint_mat_convertspace( ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); @@ -470,7 +530,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ /* when not in EditMode, use the 'final' evaluated mesh, depsgraph * ensures we build with CD_MDEFORMVERT layer */ - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); BMEditMesh *em = BKE_editmesh_from_object(ob); float plane[3]; float imat[3][3], tmat[3][3]; @@ -488,17 +548,17 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ float normal[3] = {0.0f, 0.0f, 0.0f}; float weightsum = 0.0f; if (me_eval) { - MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT); + const MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT); int numVerts = me_eval->totvert; /* check that dvert is a valid pointers (just in case) */ if (dvert) { - MDeformVert *dv = dvert; - MVert *mv = me_eval->mvert; /* get the average of all verts with that are in the vertex-group */ - for (int i = 0; i < numVerts; i++, dv++, mv++) { - MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup); + for (int i = 0; i < numVerts; i++) { + const MDeformVert *dv = &dvert[i]; + const MVert *mv = &me_eval->mvert[i]; + const MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup); if (dw && dw->weight > 0.0f) { float nor[3]; @@ -1476,7 +1536,10 @@ static void followpath_get_tarmat(struct Depsgraph *UNUSED(depsgraph), * to get a time factor. */ curvetime /= cu->pathlen; - if (cu->flag & CU_PATH_CLAMP) { + Nurb *nu = cu->nurb.first; + if (!(nu && nu->flagu & CU_NURB_CYCLIC) && cu->flag & CU_PATH_CLAMP) { + /* If curve is not cyclic, clamp to the begin/end points if the curve clamp option is on. + */ CLAMP(curvetime, 0.0f, 1.0f); } } @@ -1491,7 +1554,7 @@ static void followpath_get_tarmat(struct Depsgraph *UNUSED(depsgraph), dir, (data->followflag & FOLLOWPATH_FOLLOW) ? quat : NULL, &radius, - NULL)) { /* quat_pt is quat or NULL*/ + NULL)) { /* quat_pt is quat or NULL. */ float totmat[4][4]; unit_m4(totmat); @@ -2232,17 +2295,47 @@ static void translike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t bConstraintTarget *ct = targets->first; if (VALID_CONS_TARGET(ct)) { + float target_mat[4][4]; + + copy_m4_m4(target_mat, ct->matrix); + + /* Remove the shear of the target matrix if enabled. + * Use Y as the axis since it's the natural default for bones. */ + if (data->flag & TRANSLIKE_REMOVE_TARGET_SHEAR) { + orthogonalize_m4_stable(target_mat, 1, false); + } + + /* Finally, combine the matrices. */ switch (data->mix_mode) { case TRANSLIKE_MIX_REPLACE: - copy_m4_m4(cob->matrix, ct->matrix); + copy_m4_m4(cob->matrix, target_mat); + break; + + /* Simple matrix multiplication. */ + case TRANSLIKE_MIX_BEFORE_FULL: + mul_m4_m4m4(cob->matrix, target_mat, cob->matrix); break; + case TRANSLIKE_MIX_AFTER_FULL: + mul_m4_m4m4(cob->matrix, cob->matrix, target_mat); + break; + + /* Aligned Inherit Scale emulation. */ case TRANSLIKE_MIX_BEFORE: - mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix); + mul_m4_m4m4_aligned_scale(cob->matrix, target_mat, cob->matrix); break; case TRANSLIKE_MIX_AFTER: - mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix); + mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, target_mat); + break; + + /* Fully separate handling of channels. */ + case TRANSLIKE_MIX_BEFORE_SPLIT: + mul_m4_m4m4_split_channels(cob->matrix, target_mat, cob->matrix); + break; + + case TRANSLIKE_MIX_AFTER_SPLIT: + mul_m4_m4m4_split_channels(cob->matrix, cob->matrix, target_mat); break; default: @@ -2361,7 +2454,7 @@ static void pycon_new_data(void *cdata) { bPythonConstraint *data = (bPythonConstraint *)cdata; - /* everything should be set correctly by calloc, except for the prop->type constant.*/ + /* Everything should be set correctly by calloc, except for the prop->type constant. */ data->prop = MEM_callocN(sizeof(IDProperty), "PyConstraintProps"); data->prop->type = IDP_GROUP; } @@ -3523,7 +3616,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t scale[0] = 1.0; scale[2] = 1.0; break; - default: /* should not happen, but in case*/ + default: /* Should not happen, but in case. */ return; } /* switch (data->volmode) */ @@ -3536,34 +3629,34 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t damptrack_do_transform(cob->matrix, vec, TRACK_Y); break; case PLANE_X: - /* new Y aligns object target connection*/ + /* New Y aligns object target connection. */ copy_v3_v3(cob->matrix[1], vec); - /* build new Z vector */ - /* othogonal to "new Y" "old X! plane */ + /* Build new Z vector. */ + /* Orthogonal to "new Y" "old X! plane. */ cross_v3_v3v3(orth, xx, vec); normalize_v3(orth); - /* new Z*/ + /* New Z. */ copy_v3_v3(cob->matrix[2], orth); - /* we decided to keep X plane*/ + /* We decided to keep X plane. */ cross_v3_v3v3(xx, vec, orth); normalize_v3_v3(cob->matrix[0], xx); break; case PLANE_Z: - /* new Y aligns object target connection*/ + /* New Y aligns object target connection. */ copy_v3_v3(cob->matrix[1], vec); - /* build new X vector */ - /* othogonal to "new Y" "old Z! plane */ + /* Build new X vector. */ + /* Orthogonal to "new Y" "old Z! plane. */ cross_v3_v3v3(orth, zz, vec); normalize_v3(orth); - /* new X */ + /* New X. */ negate_v3_v3(cob->matrix[0], orth); - /* we decided to keep Z */ + /* We decided to keep Z. */ cross_v3_v3v3(zz, vec, orth); normalize_v3_v3(cob->matrix[2], zz); break; @@ -4678,7 +4771,7 @@ static void pivotcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta } } - /* find the pivot-point to use */ + /* Find the pivot-point to use. */ if (VALID_CONS_TARGET(ct)) { /* apply offset to target location */ add_v3_v3v3(pivot, ct->matrix[3], data->offset); @@ -5006,7 +5099,7 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co } Object *depth_object = context->depth_object; - Mesh *depth_mesh = BKE_object_get_evaluated_mesh(depth_object); + const Mesh *depth_mesh = BKE_object_get_evaluated_mesh(depth_object); if (depth_mesh == NULL) { return; } @@ -6297,7 +6390,7 @@ void BKE_constraint_blend_write(BlendWriter *writer, ListBase *conlist) } /* Write ID Properties -- and copy this comment EXACTLY for easy finding - * of library blocks that implement this.*/ + * of library blocks that implement this. */ IDP_BlendWrite(writer, data->prop); break; diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 81830f5bb61..1028790856c 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -1225,8 +1225,11 @@ enum eContextObjectMode CTX_data_mode_enum(const bContext *C) return CTX_data_mode_enum_ex(obedit, obact, obact ? obact->mode : OB_MODE_OBJECT); } -/* would prefer if we can use the enum version below over this one - Campbell */ -/* must be aligned with above enum */ +/** + * Would prefer if we can use the enum version below over this one - Campbell. + * + * \note Must be aligned with above enum. + */ static const char *data_mode_strings[] = { "mesh_edit", "curve_edit", "surface_edit", "text_edit", "armature_edit", "mball_edit", "lattice_edit", "posemode", diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 65cdb8503a4..a5538453248 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -442,6 +442,15 @@ ListBase *BKE_curve_editNurbs_get(Curve *cu) return NULL; } +const ListBase *BKE_curve_editNurbs_get_for_read(const Curve *cu) +{ + if (cu->editnurb) { + return &cu->editnurb->nurbs; + } + + return NULL; +} + short BKE_curve_type_get(const Curve *cu) { int type = cu->type; @@ -1926,7 +1935,7 @@ static int cu_isectLL(const float v1[3], static bool bevelinside(const BevList *bl1, const BevList *bl2) { /* is bl2 INSIDE bl1 ? with left-right method and "lambda's" */ - /* returns '1' if correct hole */ + /* returns '1' if correct hole. */ BevPoint *bevp, *prevbevp; float min, max, vec[3], hvec1[3], hvec2[3], lab, mu; int nr, links = 0, rechts = 0, mode; @@ -1941,7 +1950,7 @@ static bool bevelinside(const BevList *bl1, const BevList *bl2) hvec2[0] += 1000; /* test it with all edges of potential surrounding poly */ - /* count number of transitions left-right */ + /* count number of transitions left-right. */ bevp = bl1->bevpoints; nr = bl1->nr; @@ -2049,7 +2058,7 @@ static void calc_bevel_sin_cos( static void tilt_bezpart(const BezTriple *prevbezt, const BezTriple *bezt, - Nurb *nu, + const Nurb *nu, float *tilt_array, float *radius_array, float *weight_array, @@ -2133,7 +2142,7 @@ static void tilt_bezpart(const BezTriple *prevbezt, } if (weight_array) { - /* basic interpolation for now, could copy tilt interp too */ + /* Basic interpolation for now, could copy tilt interp too. */ *weight_array = prevbezt->weight + (bezt->weight - prevbezt->weight) * (3.0f * fac * fac - 2.0f * fac * fac * fac); @@ -2611,7 +2620,7 @@ static void make_bevel_list_2D(BevList *bl) } } -static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl) +static void bevlist_firstlast_direction_calc_from_bpoint(const Nurb *nu, BevList *bl) { if (nu->pntsu > 1) { BPoint *first_bp = nu->bp, *last_bp = nu->bp + (nu->pntsu - 1); @@ -2646,7 +2655,7 @@ void BKE_curve_bevelList_free(ListBase *bev) BLI_listbase_clear(bev); } -void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) +void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_render) { /* * - convert all curves to polys, with indication of resol and flags for double-vertices @@ -2684,14 +2693,14 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) 1; #endif - /* STEP 1: MAKE POLYS */ + /* STEP 1: MAKE POLYS */ BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev); if (cu->editnurb && ob->type != OB_FONT) { is_editmode = 1; } - LISTBASE_FOREACH (Nurb *, nu, nurbs) { + LISTBASE_FOREACH (const Nurb *, nu, nurbs) { if (nu->hide && is_editmode) { continue; } @@ -4361,7 +4370,7 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) else { char h_new = HD_FREE; - /* there is 1 handle not FREE: FREE it all, else make ALIGNED */ + /* There is 1 handle not FREE: FREE it all, else make ALIGNED. */ if (code == 5) { h_new = HD_ALIGN; } @@ -4932,7 +4941,7 @@ bool BKE_nurb_type_convert(Nurb *nu, int a, c, nr; if (nu->type == CU_POLY) { - if (type == CU_BEZIER) { /* to Bezier with vecthandles */ + if (type == CU_BEZIER) { /* To Bezier with vecthandles. */ nr = nu->pntsu; bezt = (BezTriple *)MEM_calloc_arrayN(nr, sizeof(BezTriple), "setsplinetype2"); nu->bezt = bezt; @@ -5078,6 +5087,15 @@ ListBase *BKE_curve_nurbs_get(Curve *cu) return &cu->nurb; } +const ListBase *BKE_curve_nurbs_get_for_read(const Curve *cu) +{ + if (cu->editnurb) { + return BKE_curve_editNurbs_get_for_read(cu); + } + + return &cu->nurb; +} + void BKE_curve_nurb_active_set(Curve *cu, const Nurb *nu) { if (nu == NULL) { @@ -5135,7 +5153,7 @@ void BKE_curve_nurb_vert_active_set(Curve *cu, const Nurb *nu, const void *vert) } } -/* Get points to active active nurb and active vert for curve */ +/* Get points to the active nurb and active vert for curve. */ bool BKE_curve_nurb_vert_active_get(Curve *cu, Nurb **r_nu, void **r_vert) { Nurb *nu = NULL; diff --git a/source/blender/blenkernel/intern/curve_bevel.c b/source/blender/blenkernel/intern/curve_bevel.c index 7f2cdfa59d3..d205d8cca46 100644 --- a/source/blender/blenkernel/intern/curve_bevel.c +++ b/source/blender/blenkernel/intern/curve_bevel.c @@ -97,7 +97,7 @@ static void curve_bevel_make_extrude_and_fill(const Curve *cu, * in a consistent direction. * * These should be small enough for stack allocations because the current limit - * for #Curve.bevresol is 32. */ + * for #Curve.bevresol is 32. */ float *quarter_coords_x = alloca(sizeof(float) * (cu->bevresol + 1)); float *quarter_coords_y = alloca(sizeof(float) * (cu->bevresol + 1)); bevel_quarter_fill(cu, quarter_coords_x, quarter_coords_y); diff --git a/source/blender/blenkernel/intern/curve_decimate.c b/source/blender/blenkernel/intern/curve_decimate.c index e4647908b58..62de7c74183 100644 --- a/source/blender/blenkernel/intern/curve_decimate.c +++ b/source/blender/blenkernel/intern/curve_decimate.c @@ -32,8 +32,8 @@ struct Knot { struct Knot *next, *prev; - uint point_index; /* index in point array */ - uint knot_index; /* index in knot array*/ + uint point_index; /* Index in point array. */ + uint knot_index; /* Index in knot array. */ float tan[2][3]; float handles[2]; diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc index 0a6e4458a35..72ee2587c8a 100644 --- a/source/blender/blenkernel/intern/curve_eval.cc +++ b/source/blender/blenkernel/intern/curve_eval.cc @@ -257,9 +257,10 @@ static SplinePtr spline_from_dna_poly(const Nurb &nurb) return spline; } -std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve) +std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve, + const ListBase &nurbs_list) { - Vector<const Nurb *> nurbs(*BKE_curve_nurbs_get(&const_cast<Curve &>(dna_curve))); + Vector<const Nurb *> nurbs(nurbs_list); std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>(); curve->resize(nurbs.size()); @@ -295,6 +296,11 @@ std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve) return curve; } +std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve) +{ + return curve_eval_from_dna_curve(dna_curve, *BKE_curve_nurbs_get_for_read(&dna_curve)); +} + /** * Check the invariants that curve control point attributes should always uphold, necessary * because attributes are stored on splines rather than in a flat array on the curve: diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index b1bb8b9715e..08d0af45e92 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -2099,7 +2099,7 @@ bool CustomData_merge(const struct CustomData *source, eCDAllocType alloctype, int totelem) { - /*const LayerTypeInfo *typeInfo;*/ + // const LayerTypeInfo *typeInfo; CustomDataLayer *layer, *newlayer; int lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0; int number = 0, maxnumber = -1; @@ -2107,7 +2107,7 @@ bool CustomData_merge(const struct CustomData *source, for (int i = 0; i < source->totlayer; i++) { layer = &source->layers[i]; - /*typeInfo = layerType_getInfo(layer->type);*/ /*UNUSED*/ + // typeInfo = layerType_getInfo(layer->type); /* UNUSED */ int type = layer->type; int flag = layer->flag; @@ -2631,7 +2631,7 @@ void *CustomData_add_layer( return NULL; } -/*same as above but accepts a name*/ +/* Same as above but accepts a name. */ void *CustomData_add_layer_named(CustomData *data, int type, eCDAllocType alloctype, @@ -2813,6 +2813,14 @@ void *CustomData_duplicate_referenced_layer_named(CustomData *data, return customData_duplicate_referenced_layer_index(data, layer_index, totelem); } +void CustomData_duplicate_referenced_layers(CustomData *data, int totelem) +{ + for (int i = 0; i < data->totlayer; i++) { + CustomDataLayer *layer = &data->layers[i]; + layer->data = customData_duplicate_referenced_layer_index(data, i, totelem); + } +} + bool CustomData_is_referenced_layer(struct CustomData *data, int type) { /* get the layer index of the first layer of type */ @@ -3559,7 +3567,7 @@ bool CustomData_bmesh_merge(const CustomData *source, if (iter_type != BM_LOOPS_OF_FACE) { BMHeader *h; BMIter iter; - /*ensure all current elements follow new customdata layout*/ + /* Ensure all current elements follow new customdata layout. */ BM_ITER_MESH (h, &iter, bm, iter_type) { void *tmp = NULL; CustomData_bmesh_copy_data(&destold, dest, h->data, &tmp); @@ -3573,7 +3581,7 @@ bool CustomData_bmesh_merge(const CustomData *source, BMIter iter; BMIter liter; - /*ensure all current elements follow new customdata layout*/ + /* Ensure all current elements follow new customdata layout. */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { void *tmp = NULL; @@ -3797,7 +3805,7 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int return POINTER_OFFSET(block, data->layers[layer_index + n].offset); } -/*gets from the layer at physical index n, note: doesn't check type.*/ +/* Gets from the layer at physical index n, note: doesn't check type. */ void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n) { if (n < 0 || n >= data->totlayer) { @@ -3879,7 +3887,7 @@ bool CustomData_has_referenced(const struct CustomData *data) } /* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to - * another, while not overwriting anything else (e.g. flags)*/ + * another, while not overwriting anything else (e.g. flags). */ void CustomData_data_copy_value(int type, const void *source, void *dest) { const LayerTypeInfo *typeInfo = layerType_getInfo(type); @@ -3897,7 +3905,7 @@ void CustomData_data_copy_value(int type, const void *source, void *dest) } /* Mixes the "value" (e.g. mloopuv uv or mloopcol colors) from one block into - * another, while not overwriting anything else (e.g. flags)*/ + * another, while not overwriting anything else (e.g. flags). */ void CustomData_data_mix_value( int type, const void *source, void *dest, const int mixmode, const float mixfactor) { diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c index 314d5f4ff82..ef86a65f47d 100644 --- a/source/blender/blenkernel/intern/customdata_file.c +++ b/source/blender/blenkernel/intern/customdata_file.c @@ -361,9 +361,9 @@ bool cdf_write_open(CDataFile *cdf, const char *filename) cdf->writef = f; - /* fill header */ + /* Fill header. */ header = &cdf->header; - /* strcpy(, "BCDF"); // terminator out of range */ + /* Copy "BCDF" (string terminator out of range). */ header->ID[0] = 'B'; header->ID[1] = 'C'; header->ID[2] = 'D'; diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 2bf58d9e764..12269cf0d51 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -1260,7 +1260,7 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph, me_dst = ob_dst->data; - /* Get source evaluated mesh.*/ + /* Get source evaluated mesh. */ BKE_object_data_transfer_dttypes_to_cdmask(data_types, &me_src_mask); me_src = mesh_get_eval_final(depsgraph, scene, ob_src, &me_src_mask); if (!me_src) { @@ -1441,7 +1441,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, } } - /* Get source evaluated mesh.*/ + /* Get source evaluated mesh. */ BKE_object_data_transfer_dttypes_to_cdmask(data_types, &me_src_mask); BKE_mesh_remap_calc_source_cddata_masks_from_map_modes( map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode, &me_src_mask); diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc index 70355f3883d..a4ffaa8b10b 100644 --- a/source/blender/blenkernel/intern/displist.cc +++ b/source/blender/blenkernel/intern/displist.cc @@ -135,7 +135,7 @@ void BKE_displist_normals_add(ListBase *lb) LISTBASE_FOREACH (DispList *, dl, lb) { if (dl->type == DL_INDEX3) { if (dl->nors == nullptr) { - dl->nors = (float *)MEM_callocN(sizeof(float[3]), "dlnors"); + dl->nors = (float *)MEM_callocN(sizeof(float[3]), __func__); if (dl->flag & DL_BACK_CURVE) { dl->nors[2] = -1.0f; @@ -147,7 +147,7 @@ void BKE_displist_normals_add(ListBase *lb) } else if (dl->type == DL_SURF) { if (dl->nors == nullptr) { - dl->nors = (float *)MEM_callocN(sizeof(float[3]) * dl->nr * dl->parts, "dlnors"); + dl->nors = (float *)MEM_callocN(sizeof(float[3]) * dl->nr * dl->parts, __func__); vdata = dl->verts; ndata = dl->nors; @@ -323,12 +323,12 @@ static void curve_to_displist(const Curve *cu, /* Check that there are more than two points so the curve doesn't loop back on itself. This * needs to be separate from `is_cyclic` because cyclic sampling can work with two points - * and resolution > 1. */ + * and resolution > 1. */ const bool use_cyclic_sample = is_cyclic && (samples_len != 2); DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__); /* Add one to the length because of 'BKE_curve_forward_diff_bezier'. */ - dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * (samples_len + 1), "dlverts"); + dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * (samples_len + 1), __func__); BLI_addtail(r_dispbase, dl); dl->parts = 1; dl->nr = samples_len; @@ -382,7 +382,7 @@ static void curve_to_displist(const Curve *cu, else if (nu->type == CU_NURBS) { const int len = (resolution * SEGMENTSU(nu)); DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__); - dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), "dlverts"); + dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__); BLI_addtail(r_dispbase, dl); dl->parts = 1; dl->nr = len; @@ -395,7 +395,7 @@ static void curve_to_displist(const Curve *cu, else if (nu->type == CU_POLY) { const int len = nu->pntsu; DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__); - dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), "dlverts"); + dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__); BLI_addtail(r_dispbase, dl); dl->parts = 1; dl->nr = len; @@ -491,7 +491,7 @@ void BKE_displist_fill(const ListBase *dispbase, const int triangles_len = BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal_proj); if (totvert != 0 && triangles_len != 0) { - DispList *dlnew = (DispList *)MEM_callocN(sizeof(DispList), "filldisplist"); + DispList *dlnew = (DispList *)MEM_callocN(sizeof(DispList), __func__); dlnew->type = DL_INDEX3; dlnew->flag = (dl_flag_accum & (DL_BACK_CURVE | DL_FRONT_CURVE)); dlnew->rt = (dl_rt_accum & CU_SMOOTH); @@ -499,8 +499,8 @@ void BKE_displist_fill(const ListBase *dispbase, dlnew->nr = totvert; dlnew->parts = triangles_len; - dlnew->index = (int *)MEM_mallocN(sizeof(int[3]) * triangles_len, "dlindex"); - dlnew->verts = (float *)MEM_mallocN(sizeof(float[3]) * totvert, "dlverts"); + dlnew->index = (int *)MEM_mallocN(sizeof(int[3]) * triangles_len, __func__); + dlnew->verts = (float *)MEM_mallocN(sizeof(float[3]) * totvert, __func__); /* vert data */ int i; @@ -630,7 +630,7 @@ static float displist_calc_taper(Depsgraph *depsgraph, (DispList *)taperobj->runtime.curve_cache->disp.first : nullptr; if (dl == nullptr) { - BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false, false); + BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false); dl = (DispList *)taperobj->runtime.curve_cache->disp.first; } if (dl) { @@ -681,8 +681,7 @@ void BKE_displist_make_mball(Depsgraph *depsgraph, Scene *scene, Object *ob) BKE_displist_free(&(ob->runtime.curve_cache->disp)); } else { - ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), - "CurveCache for MBall"); + ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), __func__); } BKE_mball_polygonize(depsgraph, scene, ob, &ob->runtime.curve_cache->disp); @@ -1068,7 +1067,7 @@ static void displist_surf_indices(DispList *dl) dl->totindex = 0; int *index = dl->index = (int *)MEM_mallocN(sizeof(int[4]) * (dl->parts + 1) * (dl->nr + 1), - "index array nurbs"); + __func__); for (int a = 0; a < dl->parts; a++) { @@ -1092,31 +1091,29 @@ static void displist_surf_indices(DispList *dl) } } -static void displist_make_surf(Depsgraph *depsgraph, - const Scene *scene, - Object *ob, - ListBase *dispbase, - Mesh **r_final, - const bool for_render, - const bool for_orco) +static void evaluate_surface_object(Depsgraph *depsgraph, + const Scene *scene, + Object *ob, + const bool for_render, + ListBase *r_dispbase, + Mesh **r_final) { - ListBase nubase = {nullptr, nullptr}; + BLI_assert(ob->type == OB_SURF); const Curve *cu = (const Curve *)ob->data; + ListBase *deformed_nurbs = &ob->runtime.curve_cache->deformed_nurbs; + if (!for_render && cu->editnurb) { - BKE_nurbList_duplicate(&nubase, BKE_curve_editNurbs_get(const_cast<Curve *>(cu))); + BKE_nurbList_duplicate(deformed_nurbs, BKE_curve_editNurbs_get_for_read(cu)); } else { - BKE_nurbList_duplicate(&nubase, &cu->nurb); + BKE_nurbList_duplicate(deformed_nurbs, &cu->nurb); } - bool force_mesh_conversion = false; - if (!for_orco) { - force_mesh_conversion = BKE_curve_calc_modifiers_pre( - depsgraph, scene, ob, &nubase, &nubase, for_render); - } + bool force_mesh_conversion = BKE_curve_calc_modifiers_pre( + depsgraph, scene, ob, deformed_nurbs, deformed_nurbs, for_render); - LISTBASE_FOREACH (Nurb *, nu, &nubase) { + LISTBASE_FOREACH (const Nurb *, nu, deformed_nurbs) { if (!(for_render || nu->hide == 0) || !BKE_nurb_check_valid_uv(nu)) { continue; } @@ -1127,10 +1124,10 @@ static void displist_make_surf(Depsgraph *depsgraph, if (nu->pntsv == 1) { const int len = SEGMENTSU(nu) * resolu; - DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), "makeDispListsurf"); - dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), "dlverts"); + DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__); + dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__); - BLI_addtail(dispbase, dl); + BLI_addtail(r_dispbase, dl); dl->parts = 1; dl->nr = len; dl->col = nu->mat_nr; @@ -1150,9 +1147,9 @@ static void displist_make_surf(Depsgraph *depsgraph, else { const int len = (nu->pntsu * resolu) * (nu->pntsv * resolv); - DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), "makeDispListsurf"); - dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), "dlverts"); - BLI_addtail(dispbase, dl); + DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__); + dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__); + BLI_addtail(r_dispbase, dl); dl->col = nu->mat_nr; dl->charidx = nu->charidx; @@ -1177,13 +1174,8 @@ static void displist_make_surf(Depsgraph *depsgraph, } } - if (!for_orco) { - BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase); - curve_calc_modifiers_post( - depsgraph, scene, ob, dispbase, for_render, force_mesh_conversion, r_final); - } - - BKE_nurbList_free(&nubase); + curve_calc_modifiers_post( + depsgraph, scene, ob, r_dispbase, for_render, force_mesh_conversion, r_final); } static void rotateBevelPiece(const Curve *cu, @@ -1252,8 +1244,8 @@ static void fillBevelCap(const Nurb *nu, const float *prev_fp, ListBase *dispbase) { - DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), "makeDispListbev2"); - dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr, "dlverts"); + DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__); + dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr, __func__); memcpy(dl->verts, prev_fp, sizeof(float[3]) * dlb->nr); dl->type = DL_POLY; @@ -1403,67 +1395,47 @@ static void calc_bevfac_mapping(const Curve *cu, } } -static void do_makeDispListCurveTypes(Depsgraph *depsgraph, - const Scene *scene, - Object *ob, - ListBase *dispbase, - const bool for_render, - const bool for_orco, - Mesh **r_final) +static void evaluate_curve_type_object(Depsgraph *depsgraph, + const Scene *scene, + Object *ob, + const bool for_render, + ListBase *r_dispbase, + Mesh **r_final) { + BLI_assert(ELEM(ob->type, OB_CURVE, OB_FONT)); const Curve *cu = (const Curve *)ob->data; - /* we do allow duplis... this is only displist on curve level */ - if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { - return; - } - - if (ob->type == OB_SURF) { - displist_make_surf(depsgraph, scene, ob, dispbase, r_final, for_render, for_orco); - return; - } - - ListBase nubase = {nullptr, nullptr}; - bool force_mesh_conversion = false; - - BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev); - - /* We only re-evaluate path if evaluation is not happening for orco. - * If the calculation happens for orco, we should never free data which - * was needed before and only not needed for orco calculation. */ - if (!for_orco) { - if (ob->runtime.curve_cache->anim_path_accum_length) { - MEM_freeN((void *)ob->runtime.curve_cache->anim_path_accum_length); - } - ob->runtime.curve_cache->anim_path_accum_length = nullptr; - } + ListBase *deformed_nurbs = &ob->runtime.curve_cache->deformed_nurbs; if (ob->type == OB_FONT) { - BKE_vfont_to_curve_nubase(ob, FO_EDIT, &nubase); + BKE_vfont_to_curve_nubase(ob, FO_EDIT, deformed_nurbs); } else { - BKE_nurbList_duplicate(&nubase, BKE_curve_nurbs_get(const_cast<Curve *>(cu))); + BKE_nurbList_duplicate(deformed_nurbs, BKE_curve_nurbs_get_for_read(cu)); } - if (!for_orco) { - force_mesh_conversion = BKE_curve_calc_modifiers_pre( - depsgraph, scene, ob, &nubase, &nubase, for_render); - } + bool force_mesh_conversion = BKE_curve_calc_modifiers_pre( + depsgraph, scene, ob, deformed_nurbs, deformed_nurbs, for_render); + + BKE_curve_bevelList_make(ob, deformed_nurbs, for_render); - BKE_curve_bevelList_make(ob, &nubase, for_render); + if ((cu->flag & CU_PATH) || + DEG_get_eval_flags_for_id(depsgraph, &ob->id) & DAG_EVAL_NEED_CURVE_PATH) { + BKE_anim_path_calc_data(ob); + } /* If curve has no bevel will return nothing */ ListBase dlbev = BKE_curve_bevel_make(cu); /* no bevel or extrude, and no width correction? */ if (BLI_listbase_is_empty(&dlbev) && cu->width == 1.0f) { - curve_to_displist(cu, &nubase, for_render, dispbase); + curve_to_displist(cu, deformed_nurbs, for_render, r_dispbase); } else { const float widfac = cu->width - 1.0f; - BevList *bl = (BevList *)ob->runtime.curve_cache->bev.first; - Nurb *nu = (Nurb *)nubase.first; + const BevList *bl = (BevList *)ob->runtime.curve_cache->bev.first; + const Nurb *nu = (Nurb *)deformed_nurbs->first; for (; bl && nu; bl = bl->next, nu = nu->next) { float *data; @@ -1475,7 +1447,7 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, if (BLI_listbase_is_empty(&dlbev)) { DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), "makeDispListbev"); dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * bl->nr, "dlverts"); - BLI_addtail(dispbase, dl); + BLI_addtail(r_dispbase, dl); if (bl->poly != -1) { dl->type = DL_POLY; @@ -1523,9 +1495,9 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, LISTBASE_FOREACH (DispList *, dlb, &dlbev) { /* for each part of the bevel use a separate displblock */ - DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), "makeDispListbev1"); - dl->verts = data = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr * steps, "dlverts"); - BLI_addtail(dispbase, dl); + DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__); + dl->verts = data = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr * steps, __func__); + BLI_addtail(r_dispbase, dl); dl->type = DL_SURF; @@ -1621,62 +1593,51 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, } if (bottom_capbase.first) { - BKE_displist_fill(&bottom_capbase, dispbase, bottom_no, false); - BKE_displist_fill(&top_capbase, dispbase, top_no, false); + BKE_displist_fill(&bottom_capbase, r_dispbase, bottom_no, false); + BKE_displist_fill(&top_capbase, r_dispbase, top_no, false); BKE_displist_free(&bottom_capbase); BKE_displist_free(&top_capbase); } } } - BKE_displist_free(&dlbev); } + BKE_displist_free(&dlbev); + if (!(cu->flag & CU_DEFORM_FILL)) { - curve_to_filledpoly(cu, dispbase); + curve_to_filledpoly(cu, r_dispbase); } - if (!for_orco) { - if ((cu->flag & CU_PATH) || - DEG_get_eval_flags_for_id(depsgraph, &ob->id) & DAG_EVAL_NEED_CURVE_PATH) { - BKE_anim_path_calc_data(ob); - } - - BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase); - curve_calc_modifiers_post( - depsgraph, scene, ob, dispbase, for_render, force_mesh_conversion, r_final); - } + curve_calc_modifiers_post( + depsgraph, scene, ob, r_dispbase, for_render, force_mesh_conversion, r_final); if (cu->flag & CU_DEFORM_FILL && !ob->runtime.data_eval) { - curve_to_filledpoly(cu, dispbase); + curve_to_filledpoly(cu, r_dispbase); } - - BKE_nurbList_free(&nubase); } void BKE_displist_make_curveTypes(Depsgraph *depsgraph, const Scene *scene, Object *ob, - const bool for_render, - const bool for_orco) + const bool for_render) { - /* The same check for duplis as in do_makeDispListCurveTypes. - * Happens when curve used for constraint/bevel was converted to mesh. - * check there is still needed for render displist and orco displists. */ - if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { - return; - } + BLI_assert(ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)); BKE_object_free_derived_caches(ob); if (!ob->runtime.curve_cache) { - ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), - "CurveCache for curve types"); + ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), __func__); } ListBase *dispbase = &(ob->runtime.curve_cache->disp); Mesh *mesh_eval = nullptr; - do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, for_render, for_orco, &mesh_eval); + if (ob->type == OB_SURF) { + evaluate_surface_object(depsgraph, scene, ob, for_render, dispbase, &mesh_eval); + } + else { + evaluate_curve_type_object(depsgraph, scene, ob, for_render, dispbase, &mesh_eval); + } if (mesh_eval != nullptr) { BKE_object_eval_assign_data(ob, &mesh_eval->id, true); @@ -1685,19 +1646,19 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph, boundbox_displist_object(ob); } -void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph, - const Scene *scene, - Object *ob, - ListBase *dispbase, - const bool for_orco, - Mesh **r_final) +void BKE_displist_make_curveTypes_forRender( + Depsgraph *depsgraph, const Scene *scene, Object *ob, ListBase *r_dispbase, Mesh **r_final) { if (ob->runtime.curve_cache == nullptr) { - ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), - "CurveCache for Curve"); + ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), __func__); } - do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, true, for_orco, r_final); + if (ob->type == OB_SURF) { + evaluate_surface_object(depsgraph, scene, ob, true, r_dispbase, r_final); + } + else { + evaluate_curve_type_object(depsgraph, scene, ob, true, r_dispbase, r_final); + } } void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3]) @@ -1730,10 +1691,10 @@ static void boundbox_displist_object(Object *ob) /* object's BB is calculated from final displist */ if (ob->runtime.bb == nullptr) { - ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), "boundbox"); + ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), __func__); } - Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval) { BKE_object_boundbox_calc_from_mesh(ob, mesh_eval); } diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 788a51257bf..2eb18a06799 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -1757,7 +1757,7 @@ void dynamicPaint_clearSurface(const Scene *scene, DynamicPaintSurface *surface) } } -/* completely (re)initializes surface (only for point cache types)*/ +/* Completely (re)initializes surface (only for point cache types). */ bool dynamicPaint_resetSurface(const Scene *scene, DynamicPaintSurface *surface) { int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface); @@ -4145,7 +4145,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex( /* mix final sample strength depending on brush settings */ if (hit_found) { - /* if "negate volume" enabled, negate all factors within volume*/ + /* If "negate volume" enabled, negate all factors within volume. */ if (brush->collision == MOD_DPAINT_COL_VOLDIST && brush->flags & MOD_DPAINT_NEGATE_VOLUME) { volume_factor = 1.0f - volume_factor; if (inner_proximity) { diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index b512309a773..49c2a2cbd89 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -222,7 +222,7 @@ void BKE_editmesh_free_derivedmesh(BMEditMesh *em) MEM_SAFE_FREE(em->bb_cage); } -/*does not free the BMEditMesh struct itself*/ +/* Does not free the #BMEditMesh struct itself. */ void BKE_editmesh_free(BMEditMesh *em) { BKE_editmesh_free_derivedmesh(em); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index e39749225ea..1b628b16802 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -163,7 +163,7 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef if (cu->flag & CU_PATH) { if (eff->ob->runtime.curve_cache == NULL || eff->ob->runtime.curve_cache->anim_path_accum_length == NULL) { - BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false, false); + BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false); } if (eff->ob->runtime.curve_cache->anim_path_accum_length) { @@ -716,7 +716,7 @@ int get_effector_data(EffectorCache *eff, } else if (eff->pd && eff->pd->shape == PFIELD_SHAPE_POINTS) { /* TODO: hair and points object support */ - Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob); if (me_eval != NULL) { copy_v3_v3(efd->loc, me_eval->mvert[*efd->index].co); normal_short_to_float_v3(efd->nor, me_eval->mvert[*efd->index].no); @@ -773,7 +773,7 @@ int get_effector_data(EffectorCache *eff, /* use center of object for distance calculus */ const Object *ob = eff->ob; - /* use z-axis as normal*/ + /* Use z-axis as normal. */ normalize_v3_v3(efd->nor, ob->obmat[2]); if (eff->pd && ELEM(eff->pd->shape, PFIELD_SHAPE_PLANE, PFIELD_SHAPE_LINE)) { @@ -830,7 +830,7 @@ static void get_effector_tot( if (eff->pd->shape == PFIELD_SHAPE_POINTS) { /* TODO: hair and points object support */ - Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob); *tot = me_eval != NULL ? me_eval->totvert : 1; if (*tot && eff->pd->forcefield == PFIELD_HARMONIC && point->index >= 0) { diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 68ed3c239ef..a670e7b9ac5 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -510,8 +510,11 @@ FCurve *BKE_fcurve_find_by_rna_context_ui(bContext *C, * with optional argument for precision required. * Returns the index to insert at (data already at that index will be offset if replace is 0) */ -static int BKE_fcurve_bezt_binarysearch_index_ex( - BezTriple array[], float frame, int arraylen, float threshold, bool *r_replace) +static int BKE_fcurve_bezt_binarysearch_index_ex(const BezTriple array[], + const float frame, + const int arraylen, + const float threshold, + bool *r_replace) { int start = 0, end = arraylen; int loopbreaker = 0, maxloop = arraylen * 2; @@ -597,9 +600,9 @@ static int BKE_fcurve_bezt_binarysearch_index_ex( /* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_fcurve) * Returns the index to insert at (data already at that index will be offset if replace is 0) */ -int BKE_fcurve_bezt_binarysearch_index(BezTriple array[], - float frame, - int arraylen, +int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[], + const float frame, + const int arraylen, bool *r_replace) { /* This is just a wrapper which uses the default threshold. */ @@ -1309,7 +1312,7 @@ void calchandles_fcurve_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag) * - Need bezier keys. * - Only bezier-interpolation has handles (for now). */ - if (ELEM(NULL, fcu, fcu->bezt) || (a < 2) /*|| ELEM(fcu->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN)*/) { + if (ELEM(NULL, fcu, fcu->bezt) || (a < 2) /*|| ELEM(fcu->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN) */) { return; } @@ -2191,9 +2194,9 @@ float evaluate_fcurve(FCurve *fcu, float evaltime) float evaluate_fcurve_only_curve(FCurve *fcu, float evaltime) { - /* Can be used to evaluate the (keyframed) fcurve only. - * Also works for driver-fcurves when the driver itself is not relevant. - * E.g. when inserting a keyframe in a driver fcurve. */ + /* Can be used to evaluate the (key-framed) f-curve only. + * Also works for driver-f-curves when the driver itself is not relevant. + * E.g. when inserting a keyframe in a driver f-curve. */ return evaluate_fcurve_ex(fcu, evaltime, 0.0); } @@ -2322,7 +2325,7 @@ void BKE_fmodifiers_blend_write(BlendWriter *writer, ListBase *fmodifiers) FMod_Python *data = fcm->data; /* Write ID Properties -- and copy this comment EXACTLY for easy finding - * of library blocks that implement this.*/ + * of library blocks that implement this. */ IDP_BlendWrite(writer, data->prop); break; diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 553575b5c7b..947417af55d 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -4395,7 +4395,7 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *v int cell[3]; float t_ray = 1.0; - /* Reset shadow value.*/ + /* Reset shadow value. */ shadow[index] = -1.0f; voxel_center[0] = (float)x; @@ -5023,7 +5023,7 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd, /* viscosity options */ tfds->viscosity_value = fds->viscosity_value; - /* diffusion options*/ + /* Diffusion options. */ tfds->surface_tension = fds->surface_tension; tfds->viscosity_base = fds->viscosity_base; tfds->viscosity_exponent = fds->viscosity_exponent; diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index 8d1e6b26d4d..b9f0b97ab46 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -875,7 +875,7 @@ static void fcm_python_new_data(void *mdata) { FMod_Python *data = (FMod_Python *)mdata; - /* everything should be set correctly by calloc, except for the prop->type constant.*/ + /* Everything should be set correctly by calloc, except for the prop->type constant. */ data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps"); data->prop->type = IDP_GROUP; } diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 92cc3c763b6..8bb2c401b03 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -216,15 +216,15 @@ void BKE_vfont_free_data(struct VFont *vfont) } } -static void *builtin_font_data = NULL; +static const void *builtin_font_data = NULL; static int builtin_font_size = 0; -bool BKE_vfont_is_builtin(struct VFont *vfont) +bool BKE_vfont_is_builtin(const struct VFont *vfont) { return STREQ(vfont->filepath, FO_BUILTIN_NAME); } -void BKE_vfont_builtin_register(void *mem, int size) +void BKE_vfont_builtin_register(const void *mem, int size) { builtin_font_data = mem; builtin_font_size = size; @@ -1271,7 +1271,7 @@ static bool vfont_to_curve(Object *ob, MEM_freeN(i_textbox_array); /* TEXT ON CURVE */ - /* Note: Only OB_CURVE objects could have a path */ + /* NOTE: Only OB_CURVE objects could have a path. */ if (cu->textoncurve && cu->textoncurve->type == OB_CURVE) { BLI_assert(cu->textoncurve->runtime.curve_cache != NULL); if (cu->textoncurve->runtime.curve_cache != NULL && @@ -1746,7 +1746,7 @@ void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, char32_t *text; CharInfo *info; - /* clean previous buffers*/ + /* Clean previous buffers. */ BKE_vfont_clipboard_free(); text = MEM_malloc_arrayN((len + 1), sizeof(*text), __func__); diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 42f3a854aec..28e46aab732 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -29,7 +29,7 @@ #include "attribute_access_intern.hh" -/* Can't include BKE_object_deform.h right now, due to an enum forward declaration. */ +/* Can't include BKE_object_deform.h right now, due to an enum forward declaration. */ extern "C" MDeformVert *BKE_object_defgroup_data_create(ID *id); using blender::fn::GVArray; diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index 3d85118deee..07b4e715ea9 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -199,20 +199,6 @@ std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set) return stream; } -/* This generally should not be used. It is necessary currently, so that GeometrySet can by used by - * the CPPType system. */ -bool operator==(const GeometrySet &UNUSED(a), const GeometrySet &UNUSED(b)) -{ - return false; -} - -/* This generally should not be used. It is necessary currently, so that GeometrySet can by used by - * the CPPType system. */ -uint64_t GeometrySet::hash() const -{ - return reinterpret_cast<uint64_t>(this); -} - /* Remove all geometry components from the geometry set. */ void GeometrySet::clear() { diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index 8cf08d05d9d..01b51d552a9 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -56,7 +56,7 @@ static void add_curve_data_as_geometry_component(const Object &object, GeometryS { BLI_assert(object.type == OB_CURVE); if (object.data != nullptr) { - std::unique_ptr<CurveEval> curve = curve_eval_from_dna_curve(*(Curve *)object.data); + std::unique_ptr<CurveEval> curve = curve_eval_from_dna_curve(*(const Curve *)object.data); CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>(); curve_component.replace(curve.release(), GeometryOwnershipType::Owned); } @@ -264,7 +264,7 @@ static bool instances_attribute_foreach_recursive(const GeometrySet &geometry_se } } - /* Now that this this geometry set is visited, increase the count and check with the limit. */ + /* Now that this geometry set is visited, increase the count and check with the limit. */ if (limit > 0 && count++ > limit) { return false; } @@ -535,7 +535,7 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups, const void *src_buffer = src_span.data(); for (const int UNUSED(i) : set_group.transforms.index_range()) { void *dst_buffer = dst_span[offset]; - cpp_type->copy_to_initialized_n(src_buffer, dst_buffer, domain_size); + cpp_type->copy_assign_n(src_buffer, dst_buffer, domain_size); offset += domain_size; } } diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index a66c3cf3573..459fc5e4c68 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -195,12 +195,12 @@ static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd) { - /* we must firstly have some grease-pencil data to link! */ + /* We must firstly have some grease-pencil data to link! */ if (gpd == NULL) { return; } - /* relink animdata */ + /* Relink anim-data. */ BLO_read_data_address(reader, &gpd->adt); BKE_animdata_blend_read_data(reader, gpd->adt); @@ -219,7 +219,7 @@ void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd) gpd->runtime.sbuffer_size = 0; gpd->runtime.tot_cp_points = 0; - /* relink palettes (old palettes deprecated, only to convert old files) */ + /* Relink palettes (old palettes deprecated, only to convert old files). */ BLO_read_list(reader, &gpd->palettes); if (gpd->palettes.first != NULL) { LISTBASE_FOREACH (bGPDpalette *, palette, &gpd->palettes) { @@ -227,14 +227,14 @@ void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd) } } - /* materials */ + /* Materials. */ BLO_read_pointer_array(reader, (void **)&gpd->mat); - /* relink layers */ + /* Relink layers. */ BLO_read_list(reader, &gpd->layers); LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* relink frames */ + /* Relink frames. */ BLO_read_list(reader, &gpl->frames); BLO_read_data_address(reader, &gpl->actframe); @@ -245,23 +245,23 @@ void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd) BLO_read_list(reader, &gpl->mask_layers); LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - /* relink strokes (and their points) */ + /* Relink strokes (and their points). */ BLO_read_list(reader, &gpf->strokes); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - /* relink stroke points array */ + /* Relink stroke points array. */ BLO_read_data_address(reader, &gps->points); - /* Relink geometry*/ + /* Relink geometry. */ BLO_read_data_address(reader, &gps->triangles); - /* relink stroke edit curve. */ + /* Relink stroke edit curve. */ BLO_read_data_address(reader, &gps->editcurve); if (gps->editcurve != NULL) { - /* relink curve point array */ + /* Relink curve point array. */ BLO_read_data_address(reader, &gps->editcurve->curve_points); } - /* relink weight data */ + /* Relink weight data. */ if (gps->dvert) { BLO_read_data_address(reader, &gps->dvert); BKE_defvert_blend_read(reader, gps->totpoints, gps->dvert); @@ -458,7 +458,7 @@ void BKE_gpencil_free_frames(bGPDlayer *gpl) void BKE_gpencil_free_layer_masks(bGPDlayer *gpl) { - /* Free masks.*/ + /* Free masks. */ bGPDlayer_Mask *mask_next = NULL; for (bGPDlayer_Mask *mask = gpl->mask_layers.first; mask; mask = mask_next) { mask_next = mask->next; @@ -482,7 +482,7 @@ void BKE_gpencil_free_layers(ListBase *list) /* free layers and their data */ BKE_gpencil_free_frames(gpl); - /* Free masks.*/ + /* Free masks. */ BKE_gpencil_free_layer_masks(gpl); BLI_freelinkN(list, gpl); @@ -1076,12 +1076,7 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src, gpl_dst->prev = gpl_dst->next = NULL; /* Copy masks. */ - BLI_listbase_clear(&gpl_dst->mask_layers); - LISTBASE_FOREACH (bGPDlayer_Mask *, mask_src, &gpl_src->mask_layers) { - bGPDlayer_Mask *mask_dst = MEM_dupallocN(mask_src); - mask_dst->prev = mask_dst->next = NULL; - BLI_addtail(&gpl_dst->mask_layers, mask_dst); - } + BKE_gpencil_layer_mask_copy(gpl_src, gpl_dst); /* copy frames */ BLI_listbase_clear(&gpl_dst->frames); @@ -1122,13 +1117,8 @@ void BKE_gpencil_layer_copy_settings(const bGPDlayer *gpl_src, bGPDlayer *gpl_ds copy_v3_v3(gpl_dst->scale, gpl_src->scale); copy_m4_m4(gpl_dst->layer_mat, gpl_src->layer_mat); copy_m4_m4(gpl_dst->layer_invmat, gpl_src->layer_invmat); - /* Use Lights flag. */ - if (gpl_src->flag & GP_LAYER_USE_LIGHTS) { - gpl_dst->flag |= GP_LAYER_USE_LIGHTS; - } - else { - gpl_dst->flag &= ~GP_LAYER_USE_LIGHTS; - } + gpl_dst->blend_mode = gpl_src->blend_mode; + gpl_dst->flag = gpl_src->flag; } /** @@ -1647,6 +1637,41 @@ void BKE_gpencil_layer_mask_sort_all(bGPdata *gpd) } } +/** + * Make a copy of a given gpencil mask layers. + */ +void BKE_gpencil_layer_mask_copy(const bGPDlayer *gpl_src, bGPDlayer *gpl_dst) +{ + BLI_listbase_clear(&gpl_dst->mask_layers); + LISTBASE_FOREACH (bGPDlayer_Mask *, mask_src, &gpl_src->mask_layers) { + bGPDlayer_Mask *mask_dst = MEM_dupallocN(mask_src); + mask_dst->prev = mask_dst->next = NULL; + BLI_addtail(&gpl_dst->mask_layers, mask_dst); + } +} + +/** + * Clean any invalid mask layer. + */ +void BKE_gpencil_layer_mask_cleanup(bGPdata *gpd, bGPDlayer *gpl) +{ + LISTBASE_FOREACH_MUTABLE (bGPDlayer_Mask *, mask, &gpl->mask_layers) { + if (BKE_gpencil_layer_named_get(gpd, mask->name) == NULL) { + BKE_gpencil_layer_mask_remove(gpl, mask); + } + } +} + +/** + * Clean any invalid mask layer for all layers. + */ +void BKE_gpencil_layer_mask_cleanup_all_layers(bGPdata *gpd) +{ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + BKE_gpencil_layer_mask_cleanup(gpd, gpl); + } +} + static int gpencil_cb_cmp_frame(void *thunk, const void *a, const void *b) { const bGPDframe *frame_a = a; diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c index 906d0fb0792..344be7bc0f5 100644 --- a/source/blender/blenkernel/intern/gpencil_curve.c +++ b/source/blender/blenkernel/intern/gpencil_curve.c @@ -242,8 +242,8 @@ static int gpencil_get_stroke_material_fromcurve( float color_fill[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* If the curve has 2 materials, the first is considered as Fill and the second as Stroke. - * If the has only one material, if the name contains _stroke, the is used - * as stroke, else as fill.*/ + * If the has only one material, if the name contains "_stroke", + * it's used as a stroke, otherwise as fill. */ if (ob_cu->totcol >= 2) { *do_stroke = true; *do_fill = true; @@ -350,7 +350,7 @@ static void gpencil_convert_spline(Main *bmain, /* Assign material index to stroke. */ gps->mat_nr = r_idx; - /* Add stroke to frame.*/ + /* Add stroke to frame. */ BLI_addtail(&gpf->strokes, gps); float *coord_array = NULL; diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 982fc2abd65..077c1a65243 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -793,6 +793,7 @@ bool BKE_gpencil_stroke_smooth(bGPDstroke *gps, int i, float inf) { bGPDspoint *pt = &gps->points[i]; float sco[3] = {0.0f}; + const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0; /* Do nothing if not enough points to smooth out */ if (gps->totpoints <= 2) { @@ -802,7 +803,7 @@ bool BKE_gpencil_stroke_smooth(bGPDstroke *gps, int i, float inf) /* Only affect endpoints by a fraction of the normal strength, * to prevent the stroke from shrinking too much */ - if (ELEM(i, 0, gps->totpoints - 1)) { + if (!is_cyclic && ELEM(i, 0, gps->totpoints - 1)) { inf *= 0.1f; } @@ -828,8 +829,22 @@ bool BKE_gpencil_stroke_smooth(bGPDstroke *gps, int i, float inf) int before = i - step; int after = i + step; - CLAMP_MIN(before, 0); - CLAMP_MAX(after, gps->totpoints - 1); + if (is_cyclic) { + if (before < 0) { + /* Sub to end point (before is already negative). */ + before = gps->totpoints + before; + CLAMP(before, 0, gps->totpoints - 1); + } + if (after > gps->totpoints - 1) { + /* Add to start point. */ + after = after - gps->totpoints; + CLAMP(after, 0, gps->totpoints - 1); + } + } + else { + CLAMP_MIN(before, 0); + CLAMP_MAX(after, gps->totpoints - 1); + } pt1 = &gps->points[before]; pt2 = &gps->points[after]; @@ -855,6 +870,7 @@ bool BKE_gpencil_stroke_smooth(bGPDstroke *gps, int i, float inf) bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float influence) { bGPDspoint *ptb = &gps->points[point_index]; + const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0; /* Do nothing if not enough points */ if ((gps->totpoints <= 2) || (point_index < 1)) { @@ -862,7 +878,7 @@ bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float } /* Only affect endpoints by a fraction of the normal influence */ float inf = influence; - if (ELEM(point_index, 0, gps->totpoints - 1)) { + if (!is_cyclic && ELEM(point_index, 0, gps->totpoints - 1)) { inf *= 0.01f; } /* Limit max influence to reduce pop effect. */ @@ -884,9 +900,22 @@ bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float int before = point_index - step; int after = point_index + step; - CLAMP_MIN(before, 0); - CLAMP_MAX(after, gps->totpoints - 1); - + if (is_cyclic) { + if (before < 0) { + /* Sub to end point (before is already negative). */ + before = gps->totpoints + before; + CLAMP(before, 0, gps->totpoints - 1); + } + if (after > gps->totpoints - 1) { + /* Add to start point. */ + after = after - gps->totpoints; + CLAMP(after, 0, gps->totpoints - 1); + } + } + else { + CLAMP_MIN(before, 0); + CLAMP_MAX(after, gps->totpoints - 1); + } pt1 = &gps->points[before]; pt2 = &gps->points[after]; @@ -919,6 +948,7 @@ bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float influence) { bGPDspoint *ptb = &gps->points[point_index]; + const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0; /* Do nothing if not enough points */ if ((gps->totpoints <= 2) || (point_index < 1)) { @@ -926,7 +956,7 @@ bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float } /* Only affect endpoints by a fraction of the normal influence */ float inf = influence; - if (ELEM(point_index, 0, gps->totpoints - 1)) { + if (!is_cyclic && ELEM(point_index, 0, gps->totpoints - 1)) { inf *= 0.01f; } /* Limit max influence to reduce pop effect. */ @@ -948,9 +978,22 @@ bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float int before = point_index - step; int after = point_index + step; - CLAMP_MIN(before, 0); - CLAMP_MAX(after, gps->totpoints - 1); - + if (is_cyclic) { + if (before < 0) { + /* Sub to end point (before is already negative). */ + before = gps->totpoints + before; + CLAMP(before, 0, gps->totpoints - 1); + } + if (after > gps->totpoints - 1) { + /* Add to start point. */ + after = after - gps->totpoints; + CLAMP(after, 0, gps->totpoints - 1); + } + } + else { + CLAMP_MIN(before, 0); + CLAMP_MAX(after, gps->totpoints - 1); + } pt1 = &gps->points[before]; pt2 = &gps->points[after]; @@ -982,6 +1025,7 @@ bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float bool BKE_gpencil_stroke_smooth_uv(bGPDstroke *gps, int point_index, float influence) { bGPDspoint *ptb = &gps->points[point_index]; + const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0; /* Do nothing if not enough points */ if (gps->totpoints <= 2) { @@ -993,9 +1037,22 @@ bool BKE_gpencil_stroke_smooth_uv(bGPDstroke *gps, int point_index, float influe int before = point_index - 1; int after = point_index + 1; - CLAMP_MIN(before, 0); - CLAMP_MAX(after, gps->totpoints - 1); - + if (is_cyclic) { + if (before < 0) { + /* Sub to end point (before is already negative). */ + before = gps->totpoints + before; + CLAMP(before, 0, gps->totpoints - 1); + } + if (after > gps->totpoints - 1) { + /* Add to start point. */ + after = after - gps->totpoints; + CLAMP(after, 0, gps->totpoints - 1); + } + } + else { + CLAMP_MIN(before, 0); + CLAMP_MAX(after, gps->totpoints - 1); + } pta = &gps->points[before]; ptc = &gps->points[after]; @@ -1993,7 +2050,7 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int MEM_SAFE_FREE(temp_points); MEM_SAFE_FREE(temp_dverts); - /* move points to smooth stroke (not simple type )*/ + /* Move points to smooth stroke (not simple type). */ if (type != GP_SUBDIV_SIMPLE) { /* duplicate points in a temp area with the new subdivide data */ temp_points = MEM_dupallocN(gps->points); @@ -2076,7 +2133,7 @@ void BKE_gpencil_stroke_merge_distance(bGPdata *gpd, else { pt->flag |= GP_SPOINT_TAG; } - /* Jump to next pair of points, keeping first point segment equals.*/ + /* Jump to next pair of points, keeping first point segment equals. */ step++; } else { @@ -2423,9 +2480,9 @@ bool BKE_gpencil_convert_mesh(Main *bmain, /* Use evaluated data to get mesh with all modifiers on top. */ Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, ob_mesh); - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); - MPoly *mp, *mpoly = me_eval->mpoly; - MLoop *mloop = me_eval->mloop; + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); + const MPoly *mpoly = me_eval->mpoly; + const MLoop *mloop = me_eval->mloop; int mpoly_len = me_eval->totpoly; char element_name[200]; @@ -2458,8 +2515,9 @@ bool BKE_gpencil_convert_mesh(Main *bmain, bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get( gpl_fill, CFRA + frame_offset, GP_GETFRAME_ADD_NEW); int i; - for (i = 0, mp = mpoly; i < mpoly_len; i++, mp++) { - MLoop *ml = &mloop[mp->loopstart]; + for (i = 0; i < mpoly_len; i++) { + const MPoly *mp = &mpoly[i]; + /* Find material. */ int mat_idx = 0; Material *ma = BKE_object_material_get(ob_mesh, mp->mat_nr + 1); @@ -2482,8 +2540,10 @@ bool BKE_gpencil_convert_mesh(Main *bmain, gps_fill->flag |= GP_STROKE_CYCLIC; /* Add points to strokes. */ - for (int j = 0; j < mp->totloop; j++, ml++) { - MVert *mv = &me_eval->mvert[ml->v]; + for (int j = 0; j < mp->totloop; j++) { + const MLoop *ml = &mloop[mp->loopstart + j]; + const MVert *mv = &me_eval->mvert[ml->v]; + bGPDspoint *pt = &gps_fill->points[j]; copy_v3_v3(&pt->x, mv->co); mul_m4_v3(matrix, &pt->x); @@ -2559,7 +2619,7 @@ void BKE_gpencil_transform(bGPdata *gpd, const float mat[4][4]) } /* Used for "move only origins" in object_data_transform.c */ -int BKE_gpencil_stroke_point_count(bGPdata *gpd) +int BKE_gpencil_stroke_point_count(const bGPdata *gpd) { int total_points = 0; @@ -2567,7 +2627,7 @@ int BKE_gpencil_stroke_point_count(bGPdata *gpd) return 0; } - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + LISTBASE_FOREACH (const bGPDlayer *, gpl, &gpd->layers) { /* FIXME: For now, we just skip parented layers. * Otherwise, we have to update each frame to find * the current parent position/effects. @@ -2576,7 +2636,7 @@ int BKE_gpencil_stroke_point_count(bGPdata *gpd) continue; } - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (const bGPDframe *, gpf, &gpl->frames) { LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { total_points += gps->totpoints; } @@ -2811,7 +2871,7 @@ static void gpencil_stroke_join_islands(bGPdata *gpd, MDeformVert *dvert_src = NULL; MDeformVert *dvert_dst = NULL; - /* Copy weights (last before)*/ + /* Copy weights (last before). */ e1 = 0; e2 = 0; for (int i = 0; i < totpoints; i++) { @@ -3751,11 +3811,11 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd, last_prev_pt[0] -= 1.0f; } - /* generate points for start cap */ + /* Generate points for start cap. */ num_perimeter_points += generate_perimeter_cap( first_pt, first_next_pt, first_radius, perimeter_right_side, subdivisions, gps->caps[0]); - /* generate perimeter points */ + /* Generate perimeter points. */ float curr_pt[3], next_pt[3], prev_pt[3]; float vec_next[2], vec_prev[2]; float nvec_next[2], nvec_prev[2]; diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 58715ac2e05..a67e78ceea0 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -54,15 +54,15 @@ static CLG_LogRef LOG = {"bke.idprop"}; -/*local size table.*/ +/* Local size table. */ static size_t idp_size_table[] = { 1, /*strings*/ sizeof(int), sizeof(float), - sizeof(float[3]), /*Vector type, deprecated*/ - sizeof(float[16]), /*Matrix type, deprecated*/ - 0, /*arrays don't have a fixed size*/ - sizeof(ListBase), /*Group type*/ + sizeof(float[3]), /* Vector type, deprecated. */ + sizeof(float[16]), /* Matrix type, deprecated. */ + 0, /* Arrays don't have a fixed size. */ + sizeof(ListBase), /* Group type. */ sizeof(void *), sizeof(double), }; @@ -99,12 +99,12 @@ IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag) narray->data.pointer = MEM_dupallocN(array->data.pointer); for (int i = 0; i < narray->len; i++) { - /* ok, the copy functions always allocate a new structure, + /* OK, the copy functions always allocate a new structure, * which doesn't work here. instead, simply copy the * contents of the new structure into the array cell, * then free it. this makes for more maintainable * code than simply re-implementing the copy functions - * in this loop.*/ + * in this loop. */ IDProperty *tmp = IDP_CopyProperty_ex(GETPROP(narray, i), flag); memcpy(GETPROP(narray, i), tmp, sizeof(IDProperty)); MEM_freeN(tmp); @@ -228,7 +228,7 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr) } } -/*this function works for strings too!*/ +/* This function works for strings too! */ void IDP_ResizeArray(IDProperty *prop, int newlen) { const bool is_grow = newlen >= prop->len; @@ -390,8 +390,8 @@ void IDP_ConcatStringC(IDProperty *prop, const char *st) BLI_assert(prop->type == IDP_STRING); int newlen = prop->len + (int)strlen(st); - /* we have to remember that prop->len includes the null byte for strings. - * so there's no need to add +1 to the resize function.*/ + /* We have to remember that prop->len includes the null byte for strings. + * so there's no need to add +1 to the resize function. */ IDP_ResizeArray(prop, newlen); strcat(prop->data.pointer, st); } @@ -400,8 +400,8 @@ void IDP_ConcatString(IDProperty *str1, IDProperty *append) { BLI_assert(append->type == IDP_STRING); - /* since ->len for strings includes the NULL byte, we have to subtract one or - * we'll get an extra null byte after each concatenation operation.*/ + /* Since ->len for strings includes the NULL byte, we have to subtract one or + * we'll get an extra null byte after each concatenation operation. */ int newlen = str1->len + append->len - 1; IDP_ResizeArray(str1, newlen); strcat(str1->data.pointer, append->data.pointer); @@ -775,10 +775,10 @@ IDProperty *IDP_GetProperties(ID *id, const bool create_if_needed) if (create_if_needed) { id->properties = MEM_callocN(sizeof(IDProperty), "IDProperty"); id->properties->type = IDP_GROUP; - /* don't overwrite the data's name and type + /* NOTE(campbell): Don't overwrite the data's name and type * some functions might need this if they - * don't have a real ID, should be named elsewhere - Campbell */ - /* strcpy(id->name, "top_level_group");*/ + * don't have a real ID, should be named elsewhere. */ + // strcpy(id->name, "top_level_group"); } return id->properties; } @@ -1106,7 +1106,7 @@ void IDP_WriteProperty_OnlyData(const IDProperty *prop, BlendWriter *writer); static void IDP_WriteArray(const IDProperty *prop, BlendWriter *writer) { - /*REMEMBER to set totalen to len in the linking code!!*/ + /* Remember to set #IDProperty.totallen to len in the linking code! */ if (prop->data.pointer) { BLO_write_raw(writer, MEM_allocN_len(prop->data.pointer), prop->data.pointer); @@ -1123,7 +1123,7 @@ static void IDP_WriteArray(const IDProperty *prop, BlendWriter *writer) static void IDP_WriteIDPArray(const IDProperty *prop, BlendWriter *writer) { - /*REMEMBER to set totalen to len in the linking code!!*/ + /* Remember to set #IDProperty.totallen to len in the linking code! */ if (prop->data.pointer) { const IDProperty *array = prop->data.pointer; @@ -1137,7 +1137,7 @@ static void IDP_WriteIDPArray(const IDProperty *prop, BlendWriter *writer) static void IDP_WriteString(const IDProperty *prop, BlendWriter *writer) { - /*REMEMBER to set totalen to len in the linking code!!*/ + /* Remember to set #IDProperty.totallen to len in the linking code! */ BLO_write_raw(writer, (size_t)prop->len, prop->data.pointer); } @@ -1219,7 +1219,7 @@ static void IDP_DirectLinkArray(IDProperty *prop, BlendDataReader *reader) static void IDP_DirectLinkString(IDProperty *prop, BlendDataReader *reader) { - /*since we didn't save the extra string buffer, set totallen to len.*/ + /* Since we didn't save the extra string buffer, set totallen to len. */ prop->totallen = prop->len; BLO_read_data_address(reader, &prop->data.pointer); } @@ -1230,7 +1230,7 @@ static void IDP_DirectLinkGroup(IDProperty *prop, BlendDataReader *reader) BLO_read_list(reader, lb); - /*Link child id properties now*/ + /* Link child id properties now. */ LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) { IDP_DirectLinkProperty(loop, reader); } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 7a3619154a6..740c9b3864c 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1056,9 +1056,11 @@ Image *BKE_image_add_generated(Main *bmain, return ima; } -/* Create an image image from ibuf. The refcount of ibuf is increased, +/** + * Create an image from ibuf. The refcount of ibuf is increased, * caller should take care to drop its reference by calling - * IMB_freeImBuf if needed. */ + * #IMB_freeImBuf if needed. + */ Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name) { /* on save, type is changed to FILE in editsima.c */ @@ -3208,7 +3210,7 @@ Image *BKE_image_ensure_viewer(Main *bmain, int type, const char *name) ima = image_alloc(bmain, name, IMA_SRC_VIEWER, type); } - /* happens on reload, imagewindow cannot be image user when hidden*/ + /* Happens on reload, imagewindow cannot be image user when hidden. */ if (ima->id.us == 0) { id_us_ensure_real(&ima->id); } @@ -4349,7 +4351,7 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const i BKE_image_user_file_path(&iuser_t, ima, str); - /* FIXME: make several stream accessible in image editor, too*/ + /* FIXME: make several stream accessible in image editor, too. */ ia->anim = openanim(str, flags, 0, ima->colorspace_settings.name); /* let's initialize this user */ @@ -5188,7 +5190,7 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser) return ibuf != NULL; } -/* ******** Pool for image buffers ******** */ +/* ******** Pool for image buffers ******** */ typedef struct ImagePoolItem { struct ImagePoolItem *next, *prev; diff --git a/source/blender/blenkernel/intern/image_save.c b/source/blender/blenkernel/intern/image_save.c index e571499ba8e..b68cd9e4d2d 100644 --- a/source/blender/blenkernel/intern/image_save.c +++ b/source/blender/blenkernel/intern/image_save.c @@ -207,7 +207,7 @@ static bool image_save_single(ReportList *reports, goto cleanup; } - /* it shouldn't ever happen*/ + /* It shouldn't ever happen. */ if ((BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name)) == NULL) || (BLI_findstring(&rr->views, STEREO_RIGHT_NAME, offsetof(RenderView, name)) == NULL)) { BKE_reportf(reports, diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index bdc763cf4ca..f365e759221 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -262,7 +262,7 @@ static AdrBit2Path *adrcode_bitmaps_to_paths(int blocktype, int adrcode, int *to /* Object types */ static const char *ob_adrcodes_to_paths(int adrcode, int *array_index) { - /* set array index like this in-case nothing sets it correctly */ + /* Set array index like this in-case nothing sets it correctly. */ *array_index = 0; /* result depends on adrcode */ @@ -377,7 +377,7 @@ static const char *ob_adrcodes_to_paths(int adrcode, int *array_index) */ static const char *pchan_adrcodes_to_paths(int adrcode, int *array_index) { - /* set array index like this in-case nothing sets it correctly */ + /* Set array index like this in-case nothing sets it correctly. */ *array_index = 0; /* result depends on adrcode */ @@ -434,7 +434,7 @@ static const char *pchan_adrcodes_to_paths(int adrcode, int *array_index) /* Constraint types */ static const char *constraint_adrcodes_to_paths(int adrcode, int *array_index) { - /* set array index like this in-case nothing sets it correctly */ + /* Set array index like this in-case nothing sets it correctly. */ *array_index = 0; /* result depends on adrcode */ @@ -605,7 +605,7 @@ static const char *mtex_adrcodes_to_paths(int adrcode, int *UNUSED(array_index)) /* Texture types */ static const char *texture_adrcodes_to_paths(int adrcode, int *array_index) { - /* set array index like this in-case nothing sets it correctly */ + /* Set array index like this in-case nothing sets it correctly. */ *array_index = 0; /* result depends on adrcode */ @@ -692,7 +692,7 @@ static const char *texture_adrcodes_to_paths(int adrcode, int *array_index) /* Material Types */ static const char *material_adrcodes_to_paths(int adrcode, int *array_index) { - /* set array index like this in-case nothing sets it correctly */ + /* Set array index like this in-case nothing sets it correctly. */ *array_index = 0; /* result depends on adrcode */ @@ -785,7 +785,7 @@ static const char *material_adrcodes_to_paths(int adrcode, int *array_index) /* Camera Types */ static const char *camera_adrcodes_to_paths(int adrcode, int *array_index) { - /* set array index like this in-case nothing sets it correctly */ + /* Set array index like this in-case nothing sets it correctly. */ *array_index = 0; /* result depends on adrcode */ @@ -830,7 +830,7 @@ static const char *camera_adrcodes_to_paths(int adrcode, int *array_index) /* Light Types */ static const char *light_adrcodes_to_paths(int adrcode, int *array_index) { - /* set array index like this in-case nothing sets it correctly */ + /* Set array index like this in-case nothing sets it correctly. */ *array_index = 0; /* result depends on adrcode */ @@ -875,7 +875,7 @@ static const char *light_adrcodes_to_paths(int adrcode, int *array_index) /* Sound Types */ static const char *sound_adrcodes_to_paths(int adrcode, int *array_index) { - /* set array index like this in-case nothing sets it correctly */ + /* Set array index like this in-case nothing sets it correctly. */ *array_index = 0; /* result depends on adrcode */ @@ -901,7 +901,7 @@ static const char *sound_adrcodes_to_paths(int adrcode, int *array_index) /* World Types */ static const char *world_adrcodes_to_paths(int adrcode, int *array_index) { - /* set array index like this in-case nothing sets it correctly */ + /* Set array index like this in-case nothing sets it correctly. */ *array_index = 0; /* result depends on adrcode */ @@ -947,7 +947,7 @@ static const char *world_adrcodes_to_paths(int adrcode, int *array_index) /* Particle Types */ static const char *particle_adrcodes_to_paths(int adrcode, int *array_index) { - /* set array index like this in-case nothing sets it correctly */ + /* Set array index like this in-case nothing sets it correctly. */ *array_index = 0; /* result depends on adrcode */ diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 073276b7011..6cc90f86b4a 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -315,11 +315,11 @@ Key *BKE_key_add(Main *bmain, ID *id) /* common function */ return key; } -/* Sort shape keys and Ipo curves after a change. This assumes that at most - * one key was moved, which is a valid assumption for the places it's - * currently being called. +/** + * Sort shape keys after a change. + * This assumes that at most one key was moved, + * which is a valid assumption for the places it's currently being called. */ - void BKE_key_sort(Key *key) { KeyBlock *kb; @@ -2048,9 +2048,9 @@ void BKE_keyblock_convert_to_lattice(KeyBlock *kb, Lattice *lt) /************************* Curve ************************/ -int BKE_keyblock_curve_element_count(ListBase *nurb) +int BKE_keyblock_curve_element_count(const ListBase *nurb) { - Nurb *nu; + const Nurb *nu; int tot = 0; nu = nurb->first; diff --git a/source/blender/blenkernel/intern/keyconfig.c b/source/blender/blenkernel/intern/keyconfig.c index 552760c9b34..d25f475c140 100644 --- a/source/blender/blenkernel/intern/keyconfig.c +++ b/source/blender/blenkernel/intern/keyconfig.c @@ -55,7 +55,7 @@ wmKeyConfigPref *BKE_keyconfig_pref_ensure(UserDef *userdef, const char *kc_idna } if (kpt->prop == NULL) { IDPropertyTemplate val = {0}; - kpt->prop = IDP_New(IDP_GROUP, &val, kc_idname); /* name is unimportant */ + kpt->prop = IDP_New(IDP_GROUP, &val, kc_idname); /* name is unimportant. */ } return kpt; } diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c index a8126cb5538..a3133b58a0a 100644 --- a/source/blender/blenkernel/intern/lattice_deform.c +++ b/source/blender/blenkernel/intern/lattice_deform.c @@ -93,18 +93,18 @@ LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Ob /* for example with a particle system: (ob == NULL) */ if (ob == NULL) { - /* in deformspace, calc matrix */ + /* In deform-space, calc matrix. */ invert_m4_m4(latmat, oblatt->obmat); /* back: put in deform array */ invert_m4_m4(imat, latmat); } else { - /* in deformspace, calc matrix */ + /* In deform-space, calc matrix. */ invert_m4_m4(imat, oblatt->obmat); mul_m4_m4m4(latmat, imat, ob->obmat); - /* back: put in deform array */ + /* back: put in deform array. */ invert_m4_m4(imat, latmat); } diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 2ac10586fd9..d49eb0d4da8 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -676,10 +676,10 @@ LayerCollection *BKE_layer_collection_activate_parent(ViewLayer *view_layer, Lay /** * Recursively get the count of collections */ -static int collection_count(ListBase *lb) +static int collection_count(const ListBase *lb) { int i = 0; - LISTBASE_FOREACH (LayerCollection *, lc, lb) { + LISTBASE_FOREACH (const LayerCollection *, lc, lb) { i += collection_count(&lc->layer_collections) + 1; } return i; @@ -689,7 +689,7 @@ static int collection_count(ListBase *lb) * Get the total number of collections * (including all the nested collections) */ -int BKE_layer_collection_count(ViewLayer *view_layer) +int BKE_layer_collection_count(const ViewLayer *view_layer) { return collection_count(&view_layer->layer_collections); } @@ -819,7 +819,7 @@ static void layer_collection_sync(ViewLayer *view_layer, } /* We separate restrict viewport and visible view layer because a layer collection can be - * hidden in the view layer yet (locally) visible in a viewport (if it is not restricted).*/ + * hidden in the view layer yet (locally) visible in a viewport (if it is not restricted). */ if (child_restrict & COLLECTION_RESTRICT_VIEWPORT) { lc->runtime_flag |= LAYER_COLLECTION_RESTRICT_VIEWPORT; } @@ -1000,7 +1000,7 @@ void BKE_main_collection_sync_remap(const Main *bmain) /* On remapping of object or collection pointers free caches. */ /* TODO: try to make this faster */ - for (const Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { MEM_SAFE_FREE(view_layer->object_bases_array); @@ -1009,6 +1009,10 @@ void BKE_main_collection_sync_remap(const Main *bmain) view_layer->object_bases_hash = NULL; } } + + BKE_collection_object_cache_free(scene->master_collection); + DEG_id_tag_update_ex((Main *)bmain, &scene->master_collection->id, ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update_ex((Main *)bmain, &scene->id, ID_RECALC_COPY_ON_WRITE); } for (Collection *collection = bmain->collections.first; collection; @@ -1500,7 +1504,7 @@ static LayerCollection *find_layer_collection_by_scene_collection(LayerCollectio /** * Return the first matching LayerCollection in the ViewLayer for the Collection. */ -LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *view_layer, +LayerCollection *BKE_layer_collection_first_from_scene_collection(const ViewLayer *view_layer, const Collection *collection) { LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) { @@ -1516,7 +1520,7 @@ LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *vie /** * See if view layer has the scene collection linked directly, or indirectly (nested) */ -bool BKE_view_layer_has_collection(ViewLayer *view_layer, const Collection *collection) +bool BKE_view_layer_has_collection(const ViewLayer *view_layer, const Collection *collection) { return BKE_layer_collection_first_from_scene_collection(view_layer, collection) != NULL; } @@ -1823,7 +1827,7 @@ void BKE_view_layer_bases_in_mode_iterator_end(BLI_Iterator *UNUSED(iter)) /** \} */ -/* Evaluation */ +/* Evaluation. */ /* Applies object's restrict flags on top of flags coming from the collection * and stores those in base->flag. BASE_VISIBLE_DEPSGRAPH ignores viewport flags visibility diff --git a/source/blender/blenkernel/intern/layer_utils.c b/source/blender/blenkernel/intern/layer_utils.c index 974a5a24e8a..10ab0a06dd0 100644 --- a/source/blender/blenkernel/intern/layer_utils.c +++ b/source/blender/blenkernel/intern/layer_utils.c @@ -164,11 +164,11 @@ Object **BKE_view_layer_array_from_objects_in_mode_params(ViewLayer *view_layer, /** \name Filter Functions * \{ */ -bool BKE_view_layer_filter_edit_mesh_has_uvs(Object *ob, void *UNUSED(user_data)) +bool BKE_view_layer_filter_edit_mesh_has_uvs(const Object *ob, void *UNUSED(user_data)) { if (ob->type == OB_MESH) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_mesh; + const Mesh *me = ob->data; + const BMEditMesh *em = me->edit_mesh; if (em != NULL) { if (CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV) != -1) { return true; @@ -178,11 +178,11 @@ bool BKE_view_layer_filter_edit_mesh_has_uvs(Object *ob, void *UNUSED(user_data) return false; } -bool BKE_view_layer_filter_edit_mesh_has_edges(Object *ob, void *UNUSED(user_data)) +bool BKE_view_layer_filter_edit_mesh_has_edges(const Object *ob, void *UNUSED(user_data)) { if (ob->type == OB_MESH) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_mesh; + const Mesh *me = ob->data; + const BMEditMesh *em = me->edit_mesh; if (em != NULL) { if (em->bm->totedge != 0) { return true; diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index b7cacba20b3..297ee565257 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -1941,13 +1941,13 @@ void BKE_library_make_local(Main *bmain, ntree->tag &= ~LIB_TAG_DOIT; } - if (id->lib == NULL) { + if (!ID_IS_LINKED(id)) { id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW); id->flag &= ~LIB_INDIRECT_WEAK_LINK; if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && ELEM(lib, NULL, id->override_library->reference->lib) && ((untagged_only == false) || !(id->tag & LIB_TAG_PRE_EXISTING))) { - BKE_lib_override_library_free(&id->override_library, true); + BKE_lib_override_library_make_local(id); } } /* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so it's possible to tag data diff --git a/source/blender/blenkernel/intern/lib_id_eval.c b/source/blender/blenkernel/intern/lib_id_eval.c new file mode 100644 index 00000000000..140fe403ac3 --- /dev/null +++ b/source/blender/blenkernel/intern/lib_id_eval.c @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/** \file + * \ingroup bke + * + * Contains management of ID's and libraries + * allocate and free of all library data + */ + +#include "DNA_ID.h" +#include "DNA_mesh_types.h" + +#include "BLI_utildefines.h" + +#include "BKE_lib_id.h" +#include "BKE_mesh.h" + +/** + * Copy relatives parameters, from `id` to `id_cow`. + * Use handle the #ID_RECALC_PARAMETERS tag. + * \note Keep in sync with #ID_TYPE_SUPPORTS_PARAMS_WITHOUT_COW. + */ +void BKE_id_eval_properties_copy(ID *id_cow, ID *id) +{ + const ID_Type id_type = GS(id->name); + BLI_assert((id_cow->tag & LIB_TAG_COPIED_ON_WRITE) && !(id->tag & LIB_TAG_COPIED_ON_WRITE)); + BLI_assert(ID_TYPE_SUPPORTS_PARAMS_WITHOUT_COW(id_type)); + if (id_type == ID_ME) { + BKE_mesh_copy_parameters((Mesh *)id_cow, (const Mesh *)id); + } + else { + BLI_assert_unreachable(); + } +} diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index c93971e7b11..595e470876d 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -52,12 +52,17 @@ #include "BKE_report.h" #include "BKE_scene.h" +#include "BLO_readfile.h" + #include "BLI_ghash.h" +#include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_task.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "RNA_access.h" #include "RNA_types.h" @@ -466,11 +471,14 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain, typedef struct LibOverrideGroupTagData { Main *bmain; + Scene *scene; ID *id_root; uint tag; uint missing_tag; /* Whether we are looping on override data, or their references (linked) one. */ bool is_override; + /* Whether we are creating new override, or resyncing existing one. */ + bool is_resync; } LibOverrideGroupTagData; /* Tag all IDs in dependency relationships within an override hierarchy/group. @@ -591,7 +599,9 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat static void lib_override_linked_group_tag(LibOverrideGroupTagData *data) { Main *bmain = data->bmain; + Scene *scene = data->scene; ID *id_root = data->id_root; + const bool is_resync = data->is_resync; BLI_assert(!data->is_override); if ((id_root->tag & LIB_TAG_MISSING)) { @@ -616,6 +626,43 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data) } } } + + /* For each object tagged for override, ensure we get at least one local or liboverride + * collection to host it. Avoids getting a bunch of random object in the scene's master + * collection when all objects' dependencies are not properly 'packed' into a single root + * collection. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + if (ID_IS_LINKED(ob) && (ob->id.tag & data->tag) != 0) { + Collection *instantiating_collection = NULL; + Collection *instantiating_collection_override_candidate = NULL; + /* Loop over all collections instantiating the object, if we already have a 'locale' one we + * have nothing to do, otherwise try to find a 'linked' one that we can override too. */ + while ((instantiating_collection = BKE_collection_object_find( + bmain, scene, instantiating_collection, ob)) != NULL) { + /* In (recursive) resync case, if a collection of a 'parent' lib instantiates the linked + * object, it is also fine. */ + if (!ID_IS_LINKED(instantiating_collection) || + (is_resync && ID_IS_LINKED(id_root) && + instantiating_collection->id.lib->temp_index < id_root->lib->temp_index)) { + break; + } + if (ID_IS_LINKED(instantiating_collection) && + (!is_resync || instantiating_collection->id.lib == id_root->lib)) { + instantiating_collection_override_candidate = instantiating_collection; + } + } + + if (instantiating_collection == NULL && + instantiating_collection_override_candidate != NULL) { + if ((instantiating_collection_override_candidate->id.tag & LIB_TAG_MISSING)) { + instantiating_collection_override_candidate->id.tag |= data->missing_tag; + } + else { + instantiating_collection_override_candidate->id.tag |= data->tag; + } + } + } + } } } @@ -694,14 +741,16 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data) lib_override_overrides_group_tag_recursive(data); } -static bool lib_override_library_create_do(Main *bmain, ID *id_root) +static bool lib_override_library_create_do(Main *bmain, Scene *scene, ID *id_root) { BKE_main_relations_create(bmain, 0); LibOverrideGroupTagData data = {.bmain = bmain, + .scene = scene, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING, - .is_override = false}; + .is_override = false, + .is_resync = false}; lib_override_linked_group_tag(&data); BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); @@ -862,7 +911,7 @@ bool BKE_lib_override_library_create(Main *bmain, *r_id_root_override = NULL; } - const bool success = lib_override_library_create_do(bmain, id_root); + const bool success = lib_override_library_create_do(bmain, scene, id_root); if (!success) { return success; @@ -958,7 +1007,7 @@ bool BKE_lib_override_library_resync(Main *bmain, Collection *override_resync_residual_storage, const bool do_hierarchy_enforce, const bool do_post_process, - ReportList *reports) + BlendFileReadReport *reports) { BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); @@ -966,10 +1015,12 @@ bool BKE_lib_override_library_resync(Main *bmain, BKE_main_relations_create(bmain, 0); LibOverrideGroupTagData data = {.bmain = bmain, + .scene = scene, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING, - .is_override = true}; + .is_override = true, + .is_resync = true}; lib_override_overrides_group_tag(&data); BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); @@ -1286,7 +1337,7 @@ bool BKE_lib_override_library_resync(Main *bmain, id_root = id_root_reference->newid; if (user_edited_overrides_deletion_count > 0) { - BKE_reportf(reports, + BKE_reportf(reports != NULL ? reports->reports : NULL, RPT_WARNING, "During resync of data-block %s, %d obsolete overrides were deleted, that had " "local changes defined by user", @@ -1438,8 +1489,11 @@ static void lib_override_library_main_resync_on_library_indirect_level( ViewLayer *view_layer, Collection *override_resync_residual_storage, const int library_indirect_level, - ReportList *reports) + BlendFileReadReport *reports) { + const bool do_reports_recursive_resync_timing = (library_indirect_level != 0); + const double init_time = do_reports_recursive_resync_timing ? PIL_check_seconds_timer() : 0.0; + BKE_main_relations_create(bmain, 0); BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); @@ -1460,10 +1514,12 @@ static void lib_override_library_main_resync_on_library_indirect_level( } LibOverrideGroupTagData data = {.bmain = bmain, + .scene = scene, .id_root = id->override_library->reference, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING, - .is_override = false}; + .is_override = false, + .is_resync = true}; lib_override_linked_group_tag(&data); BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); lib_override_hierarchy_dependencies_recursive_tag(&data); @@ -1530,6 +1586,7 @@ static void lib_override_library_main_resync_on_library_indirect_level( (!ID_IS_LINKED(id) && library_indirect_level != 0)) { continue; } + Library *library = id->lib; int level = 0; /* In complex non-supported cases, with several different override hierarchies sharing @@ -1541,12 +1598,21 @@ static void lib_override_library_main_resync_on_library_indirect_level( id = lib_override_library_main_resync_find_root_recurse(id, &level); id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC; BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id)); + BLI_assert(id->lib == library); do_continue = true; - CLOG_INFO(&LOG, 2, "Resyncing %s (%p)...", id->name, id->lib); + CLOG_INFO(&LOG, 2, "Resyncing %s (%p)...", id->name, library); const bool success = BKE_lib_override_library_resync( bmain, scene, view_layer, id, override_resync_residual_storage, false, false, reports); CLOG_INFO(&LOG, 2, "\tSuccess: %d", success); + if (success) { + reports->count.resynced_lib_overrides++; + if (library_indirect_level > 0 && + BLI_linklist_index(reports->resynced_lib_overrides_libraries, library) < 0) { + BLI_linklist_prepend(&reports->resynced_lib_overrides_libraries, library); + reports->resynced_lib_overrides_libraries_count++; + } + } break; } FOREACH_MAIN_LISTBASE_ID_END; @@ -1556,6 +1622,10 @@ static void lib_override_library_main_resync_on_library_indirect_level( } FOREACH_MAIN_LISTBASE_END; } + + if (do_reports_recursive_resync_timing) { + reports->duration.lib_overrides_recursive_resync += PIL_check_seconds_timer() - init_time; + } } static int lib_override_sort_libraries_func(LibraryIDLinkCallbackData *cb_data) @@ -1633,7 +1703,7 @@ static int lib_override_libraries_index_define(Main *bmain) void BKE_lib_override_library_main_resync(Main *bmain, Scene *scene, ViewLayer *view_layer, - ReportList *reports) + BlendFileReadReport *reports) { /* We use a specific collection to gather/store all 'orphaned' override collections and objects * generated by re-sync-process. This avoids putting them in scene's master collection. */ @@ -1688,10 +1758,12 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root) /* Tag all library overrides in the chains of dependencies from the given root one. */ BKE_main_relations_create(bmain, 0); LibOverrideGroupTagData data = {.bmain = bmain, + .scene = NULL, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING, - .is_override = true}; + .is_override = true, + .is_resync = false}; lib_override_overrides_group_tag(&data); BKE_main_relations_free(bmain); @@ -1716,6 +1788,33 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root) BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); } +/** Make given ID fully local. + * + * \note Only differs from lower-level `BKE_lib_override_library_free in infamous embedded ID + * cases. + */ +void BKE_lib_override_library_make_local(ID *id) +{ + BKE_lib_override_library_free(&id->override_library, true); + + Key *shape_key = BKE_key_from_id(id); + if (shape_key != NULL) { + shape_key->id.flag &= ~LIB_EMBEDDED_DATA_LIB_OVERRIDE; + } + + if (GS(id->name) == ID_SCE) { + Collection *master_collection = ((Scene *)id)->master_collection; + if (master_collection != NULL) { + master_collection->id.flag &= ~LIB_EMBEDDED_DATA_LIB_OVERRIDE; + } + } + + bNodeTree *node_tree = ntreeFromID(id); + if (node_tree != NULL) { + node_tree->id.flag &= ~LIB_EMBEDDED_DATA_LIB_OVERRIDE; + } +} + BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_runtime_ensure( IDOverrideLibrary *override) { diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index b748061ef8a..9d2552777bf 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -83,7 +83,7 @@ bool BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int ID *old_id = *id_pp; /* Update the callback flags with the ones defined (or forbidden) in `data` by the generic - * caller code. */ + * caller code. */ cb_flag = ((cb_flag | data->cb_flag) & ~data->cb_flag_clear); /* Update the callback flags with some extra information regarding overrides: all 'loopback', diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index a3f122115d8..371af2a95ed 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1923,7 +1923,7 @@ static void interp_weights_uv_v2_apply(const float uv[2], r_pt[1] += dvec[0] * uv[1]; } -/* when a new points added - resize all shapekey array */ +/* When a new points added - resize all shape-key array. */ void BKE_mask_layer_shape_changed_add(MaskLayer *masklay, int index, bool do_init, diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 6bef11dea76..f5d898e801b 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -158,7 +158,7 @@ static void metaball_blend_read_data(BlendDataReader *reader, ID *id) mb->editelems = NULL; /* Must always be cleared (meta's don't have their own edit-data). */ mb->needs_flush_to_id = 0; - /* mb->edit_elems.first= mb->edit_elems.last= NULL;*/ + // mb->edit_elems.first = mb->edit_elems.last = NULL; mb->lastelem = NULL; mb->batch_cache = NULL; } diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index bb46c7b16c0..413cefd2271 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -272,20 +272,20 @@ static void build_bvh_spatial(PROCESS *process, * any and all purposes, provided that this notice appears in all copies. */ -#define L 0 /* left direction: -x, -i */ -#define R 1 /* right direction: +x, +i */ -#define B 2 /* bottom direction: -y, -j */ -#define T 3 /* top direction: +y, +j */ -#define N 4 /* near direction: -z, -k */ -#define F 5 /* far direction: +z, +k */ -#define LBN 0 /* left bottom near corner */ -#define LBF 1 /* left bottom far corner */ -#define LTN 2 /* left top near corner */ -#define LTF 3 /* left top far corner */ -#define RBN 4 /* right bottom near corner */ -#define RBF 5 /* right bottom far corner */ -#define RTN 6 /* right top near corner */ -#define RTF 7 /* right top far corner */ +#define L 0 /* Left direction: -x, -i. */ +#define R 1 /* Right direction: +x, +i. */ +#define B 2 /* Bottom direction: -y, -j. */ +#define T 3 /* Top direction: +y, +j. */ +#define N 4 /* Near direction: -z, -k. */ +#define F 5 /* Far direction: +z, +k. */ +#define LBN 0 /* Left bottom near corner. */ +#define LBF 1 /* Left bottom far corner. */ +#define LTN 2 /* Left top near corner. */ +#define LTF 3 /* Left top far corner. */ +#define RBN 4 /* Right bottom near corner. */ +#define RBF 5 /* Right bottom far corner. */ +#define RTN 6 /* Right top near corner. */ +#define RTF 7 /* Right top far corner. */ /** * the LBN corner of cube (i, j, k), corresponds with location @@ -293,7 +293,8 @@ static void build_bvh_spatial(PROCESS *process, */ #define HASHBIT (5) -#define HASHSIZE (size_t)(1 << (3 * HASHBIT)) /*! < hash table size (32768) */ +/** Hash table size (32768). */ +#define HASHSIZE (size_t)(1 << (3 * HASHBIT)) #define HASH(i, j, k) ((((((i)&31) << 5) | ((j)&31)) << 5) | ((k)&31)) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 08d3236f3a9..b518f35fac7 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -413,8 +413,7 @@ static const char *cmpcode_to_str(int code) } } -/* thresh is threshold for comparing vertices, uvs, vertex colors, - * weights, etc.*/ +/** Thresh is threshold for comparing vertices, UV's, vertex colors, weights, etc. */ static int customdata_compare( CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2, const float thresh) { @@ -479,11 +478,11 @@ static int customdata_compare( if (len_squared_v3v3(v1->co, v2->co) > thresh_sq) { return MESHCMP_VERTCOMISMATCH; } - /* I don't care about normals, let's just do coordinates */ + /* I don't care about normals, let's just do coordinates. */ } } - /*we're order-agnostic for edges here*/ + /* We're order-agnostic for edges here. */ if (l1->type == CD_MEDGE) { MEdge *e1 = l1->data; MEdge *e2 = l2->data; @@ -748,12 +747,14 @@ bool BKE_mesh_clear_facemap_customdata(struct Mesh *me) return changed; } -/* this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or +/** + * This ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or * mloopcol and mcol) have the same relative active/render/clone/mask indices. * - * note that for undo mesh data we want to skip 'ensure_tess_cd' call since + * NOTE(campbell): that for undo mesh data we want to skip 'ensure_tess_cd' call since * we don't want to store memory for tessface when its only used for older - * versions of the mesh. - campbell*/ + * Versions of the mesh. + */ static void mesh_update_linked_customdata(Mesh *me, const bool do_ensure_tess_cd) { if (do_ensure_tess_cd) { @@ -811,7 +812,7 @@ static void mesh_clear_geometry(Mesh *mesh) /* Note that materials and shape keys are not freed here. This is intentional, as freeing * shape keys requires tagging the depsgraph for updated relations, which is expensive. - * Material slots should be kept in sync with the object.*/ + * Material slots should be kept in sync with the object. */ mesh->totvert = 0; mesh->totedge = 0; @@ -2087,6 +2088,14 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) SplitFaceNewVert *new_verts = NULL; SplitFaceNewEdge *new_edges = NULL; + /* Ensure we own the layers, we need to do this before split_faces_prepare_new_verts as it will + * directly assign new indices to existing edges and loops. */ + CustomData_duplicate_referenced_layers(&mesh->vdata, mesh->totvert); + CustomData_duplicate_referenced_layers(&mesh->edata, mesh->totedge); + CustomData_duplicate_referenced_layers(&mesh->ldata, mesh->totloop); + /* Update pointers in case we duplicated referenced layers. */ + BKE_mesh_update_customdata_pointers(mesh, false); + /* Detect loop normal spaces (a.k.a. smooth fans) that will need a new vert. */ const int num_new_verts = split_faces_prepare_new_verts( mesh, &lnors_spacearr, &new_verts, memarena); diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index cfb1c192afe..c162458ffb9 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -304,7 +304,7 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes, r_info->mesh_edge_offset[mi] = e; r_info->mesh_poly_offset[mi] = f; /* Get matrix that transforms a coordinate in objects[mi]'s local space - * to the target space space.*/ + * to the target space space. */ const float4x4 objn_mat = (obmats[mi] == nullptr) ? float4x4::identity() : clean_obmat(*obmats[mi]); r_info->to_target_transform[mi] = inv_target_mat * objn_mat; @@ -776,7 +776,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) /** * Do a mesh boolean operation directly on meshes (without going back and forth to BMesh). - * \param meshes: An array of of Mesh pointers. + * \param meshes: An array of Mesh pointers. * \param obmats: An array of pointers to the obmat matrices that transform local * coordinates to global ones. It is allowed for the pointers to be null, meaning the * transformation is the identity. diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 934f9ce5018..cfad5e1100d 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -247,7 +247,7 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ /* use specified dispbase */ -int BKE_mesh_nurbs_displist_to_mdata(Object *ob, +int BKE_mesh_nurbs_displist_to_mdata(const Object *ob, const ListBase *dispbase, MVert **r_allvert, int *r_totvert, @@ -259,8 +259,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, int *r_totloop, int *r_totpoly) { - Curve *cu = ob->data; - DispList *dl; + const Curve *cu = ob->data; MVert *mvert; MPoly *mpoly; MLoop *mloop; @@ -276,8 +275,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, (ob->type == OB_SURF)); /* count */ - dl = dispbase->first; - while (dl) { + LISTBASE_FOREACH (const DispList *, dl, dispbase) { if (dl->type == DL_SEGM) { totvert += dl->parts * dl->nr; totedge += dl->parts * (dl->nr - 1); @@ -305,7 +303,6 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, totpoly += tot; totloop += tot * 3; } - dl = dl->next; } if (totvert == 0) { @@ -327,8 +324,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, /* verts and faces */ vertcount = 0; - dl = dispbase->first; - while (dl) { + LISTBASE_FOREACH (const DispList *, dl, dispbase) { const bool is_smooth = (dl->rt & CU_SMOOTH) != 0; if (dl->type == DL_SEGM) { @@ -507,8 +503,6 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, } } } - - dl = dl->next; } if (totpoly) { @@ -523,7 +517,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, return 0; } -Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase) +Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase *dispbase) { Mesh *mesh; MVert *allvert; @@ -551,10 +545,18 @@ Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase) mesh = BKE_mesh_new_nomain(totvert, totedge, 0, totloop, totpoly); mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; - memcpy(mesh->mvert, allvert, totvert * sizeof(MVert)); - memcpy(mesh->medge, alledge, totedge * sizeof(MEdge)); - memcpy(mesh->mloop, allloop, totloop * sizeof(MLoop)); - memcpy(mesh->mpoly, allpoly, totpoly * sizeof(MPoly)); + if (totvert != 0) { + memcpy(mesh->mvert, allvert, totvert * sizeof(MVert)); + } + if (totedge != 0) { + memcpy(mesh->medge, alledge, totedge * sizeof(MEdge)); + } + if (totloop != 0) { + memcpy(mesh->mloop, allloop, totloop * sizeof(MLoop)); + } + if (totpoly != 0) { + memcpy(mesh->mpoly, allpoly, totpoly * sizeof(MPoly)); + } if (alluv) { const char *uvname = "UVMap"; @@ -1113,7 +1115,7 @@ static void curve_to_mesh_eval_ensure(Object *object) * Brecht says hold off with that. */ Mesh *mesh_eval = NULL; BKE_displist_make_curveTypes_forRender( - NULL, NULL, &remapped_object, &remapped_object.runtime.curve_cache->disp, false, &mesh_eval); + NULL, NULL, &remapped_object, &remapped_object.runtime.curve_cache->disp, &mesh_eval); /* Note: this is to be consistent with `BKE_displist_make_curveTypes()`, however that is not a * real issue currently, code here is broken in more than one way, fix(es) will be done diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 2260ffc668a..6eac96ba85b 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -25,8 +25,6 @@ #include <limits.h> -#include "CLG_log.h" - #include "MEM_guardedalloc.h" #include "DNA_mesh_types.h" @@ -36,2118 +34,14 @@ #include "BLI_alloca.h" #include "BLI_bitmap.h" #include "BLI_edgehash.h" -#include "BLI_linklist.h" -#include "BLI_linklist_stack.h" + #include "BLI_math.h" -#include "BLI_memarena.h" -#include "BLI_stack.h" -#include "BLI_task.h" #include "BLI_utildefines.h" #include "BKE_customdata.h" -#include "BKE_editmesh_cache.h" -#include "BKE_global.h" + #include "BKE_mesh.h" #include "BKE_multires.h" -#include "BKE_report.h" - -#include "BLI_strict_flags.h" - -#include "atomic_ops.h" -#include "mikktspace.h" - -// #define DEBUG_TIME - -#include "PIL_time.h" -#ifdef DEBUG_TIME -# include "PIL_time_utildefines.h" -#endif - -static CLG_LogRef LOG = {"bke.mesh_evaluate"}; - -/* -------------------------------------------------------------------- */ -/** \name Mesh Normal Calculation - * \{ */ - -/** - * Call when there are no polygons. - */ -static void mesh_calc_normals_vert_fallback(MVert *mverts, int numVerts) -{ - for (int i = 0; i < numVerts; i++) { - MVert *mv = &mverts[i]; - float no[3]; - - normalize_v3_v3(no, mv->co); - normal_float_to_short_v3(mv->no, no); - } -} - -/* TODO(Sybren): we can probably rename this to BKE_mesh_calc_normals_mapping(), - * and remove the function of the same name below, as that one doesn't seem to be - * called anywhere. */ -void BKE_mesh_calc_normals_mapping_simple(struct Mesh *mesh) -{ - const bool only_face_normals = CustomData_is_referenced_layer(&mesh->vdata, CD_MVERT); - - BKE_mesh_calc_normals_mapping_ex(mesh->mvert, - mesh->totvert, - mesh->mloop, - mesh->mpoly, - mesh->totloop, - mesh->totpoly, - NULL, - mesh->mface, - mesh->totface, - NULL, - NULL, - only_face_normals); -} - -/* Calculate vertex and face normals, face normals are returned in *r_faceNors if non-NULL - * and vertex normals are stored in actual mverts. - */ -void BKE_mesh_calc_normals_mapping(MVert *mverts, - int numVerts, - const MLoop *mloop, - const MPoly *mpolys, - int numLoops, - int numPolys, - float (*r_polyNors)[3], - const MFace *mfaces, - int numFaces, - const int *origIndexFace, - float (*r_faceNors)[3]) -{ - BKE_mesh_calc_normals_mapping_ex(mverts, - numVerts, - mloop, - mpolys, - numLoops, - numPolys, - r_polyNors, - mfaces, - numFaces, - origIndexFace, - r_faceNors, - false); -} -/* extended version of 'BKE_mesh_calc_normals_poly' with option not to calc vertex normals */ -void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, - int numVerts, - const MLoop *mloop, - const MPoly *mpolys, - int numLoops, - int numPolys, - float (*r_polyNors)[3], - const MFace *mfaces, - int numFaces, - const int *origIndexFace, - float (*r_faceNors)[3], - const bool only_face_normals) -{ - float(*pnors)[3] = r_polyNors, (*fnors)[3] = r_faceNors; - - if (numPolys == 0) { - if (only_face_normals == false) { - mesh_calc_normals_vert_fallback(mverts, numVerts); - } - return; - } - - /* if we are not calculating verts and no verts were passes then we have nothing to do */ - if ((only_face_normals == true) && (r_polyNors == NULL) && (r_faceNors == NULL)) { - CLOG_WARN(&LOG, "called with nothing to do"); - return; - } - - if (!pnors) { - pnors = MEM_calloc_arrayN((size_t)numPolys, sizeof(float[3]), __func__); - } - /* NO NEED TO ALLOC YET */ - /* if (!fnors) fnors = MEM_calloc_arrayN(numFaces, sizeof(float[3]), "face nors mesh.c"); */ - - if (only_face_normals == false) { - /* vertex normals are optional, they require some extra calculations, - * so make them optional */ - BKE_mesh_calc_normals_poly( - mverts, NULL, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false); - } - else { - /* only calc poly normals */ - const MPoly *mp = mpolys; - for (int i = 0; i < numPolys; i++, mp++) { - BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]); - } - } - - if (origIndexFace && - /* fnors == r_faceNors */ /* NO NEED TO ALLOC YET */ - fnors != NULL && - numFaces) { - const MFace *mf = mfaces; - for (int i = 0; i < numFaces; i++, mf++, origIndexFace++) { - if (*origIndexFace < numPolys) { - copy_v3_v3(fnors[i], pnors[*origIndexFace]); - } - else { - /* eek, we're not corresponding to polys */ - CLOG_ERROR(&LOG, "tessellation face indices are incorrect. normals may look bad."); - } - } - } - - if (pnors != r_polyNors) { - MEM_freeN(pnors); - } - /* if (fnors != r_faceNors) MEM_freeN(fnors); */ /* NO NEED TO ALLOC YET */ - - fnors = pnors = NULL; -} - -typedef struct MeshCalcNormalsData { - const MPoly *mpolys; - const MLoop *mloop; - MVert *mverts; - float (*pnors)[3]; - float (*lnors_weighted)[3]; - float (*vnors)[3]; -} MeshCalcNormalsData; - -static void mesh_calc_normals_poly_cb(void *__restrict userdata, - const int pidx, - const TaskParallelTLS *__restrict UNUSED(tls)) -{ - MeshCalcNormalsData *data = userdata; - const MPoly *mp = &data->mpolys[pidx]; - - BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mverts, data->pnors[pidx]); -} - -static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata, - const int pidx, - const TaskParallelTLS *__restrict UNUSED(tls)) -{ - MeshCalcNormalsData *data = userdata; - const MPoly *mp = &data->mpolys[pidx]; - const MLoop *ml = &data->mloop[mp->loopstart]; - const MVert *mverts = data->mverts; - - float pnor_temp[3]; - float *pnor = data->pnors ? data->pnors[pidx] : pnor_temp; - float(*lnors_weighted)[3] = data->lnors_weighted; - - const int nverts = mp->totloop; - float(*edgevecbuf)[3] = BLI_array_alloca(edgevecbuf, (size_t)nverts); - - /* Polygon Normal and edge-vector */ - /* inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors */ - { - int i_prev = nverts - 1; - const float *v_prev = mverts[ml[i_prev].v].co; - const float *v_curr; - - zero_v3(pnor); - /* Newell's Method */ - for (int i = 0; i < nverts; i++) { - v_curr = mverts[ml[i].v].co; - add_newell_cross_v3_v3v3(pnor, v_prev, v_curr); - - /* Unrelated to normalize, calculate edge-vector */ - sub_v3_v3v3(edgevecbuf[i_prev], v_prev, v_curr); - normalize_v3(edgevecbuf[i_prev]); - i_prev = i; - - v_prev = v_curr; - } - if (UNLIKELY(normalize_v3(pnor) == 0.0f)) { - pnor[2] = 1.0f; /* other axes set to 0.0 */ - } - } - - /* accumulate angle weighted face normal */ - /* inline version of #accumulate_vertex_normals_poly_v3, - * split between this threaded callback and #mesh_calc_normals_poly_accum_cb. */ - { - const float *prev_edge = edgevecbuf[nverts - 1]; - - for (int i = 0; i < nverts; i++) { - const int lidx = mp->loopstart + i; - const float *cur_edge = edgevecbuf[i]; - - /* calculate angle between the two poly edges incident on - * this vertex */ - const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); - - /* Store for later accumulation */ - mul_v3_v3fl(lnors_weighted[lidx], pnor, fac); - - prev_edge = cur_edge; - } - } -} - -static void mesh_calc_normals_poly_finalize_cb(void *__restrict userdata, - const int vidx, - const TaskParallelTLS *__restrict UNUSED(tls)) -{ - MeshCalcNormalsData *data = userdata; - - MVert *mv = &data->mverts[vidx]; - float *no = data->vnors[vidx]; - - if (UNLIKELY(normalize_v3(no) == 0.0f)) { - /* following Mesh convention; we use vertex coordinate itself for normal in this case */ - normalize_v3_v3(no, mv->co); - } - - normal_float_to_short_v3(mv->no, no); -} - -void BKE_mesh_calc_normals_poly(MVert *mverts, - float (*r_vertnors)[3], - int numVerts, - const MLoop *mloop, - const MPoly *mpolys, - int numLoops, - int numPolys, - float (*r_polynors)[3], - const bool only_face_normals) -{ - float(*pnors)[3] = r_polynors; - - TaskParallelSettings settings; - BLI_parallel_range_settings_defaults(&settings); - settings.min_iter_per_thread = 1024; - - if (only_face_normals) { - BLI_assert((pnors != NULL) || (numPolys == 0)); - BLI_assert(r_vertnors == NULL); - - MeshCalcNormalsData data = { - .mpolys = mpolys, - .mloop = mloop, - .mverts = mverts, - .pnors = pnors, - }; - - BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_cb, &settings); - return; - } - - float(*vnors)[3] = r_vertnors; - float(*lnors_weighted)[3] = MEM_malloc_arrayN( - (size_t)numLoops, sizeof(*lnors_weighted), __func__); - bool free_vnors = false; - - /* first go through and calculate normals for all the polys */ - if (vnors == NULL) { - vnors = MEM_calloc_arrayN((size_t)numVerts, sizeof(*vnors), __func__); - free_vnors = true; - } - else { - memset(vnors, 0, sizeof(*vnors) * (size_t)numVerts); - } - - MeshCalcNormalsData data = { - .mpolys = mpolys, - .mloop = mloop, - .mverts = mverts, - .pnors = pnors, - .lnors_weighted = lnors_weighted, - .vnors = vnors, - }; - - /* Compute poly normals, and prepare weighted loop normals. */ - BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_prepare_cb, &settings); - - /* Actually accumulate weighted loop normals into vertex ones. */ - /* Unfortunately, not possible to thread that - * (not in a reasonable, totally lock- and barrier-free fashion), - * since several loops will point to the same vertex... */ - for (int lidx = 0; lidx < numLoops; lidx++) { - add_v3_v3(vnors[mloop[lidx].v], data.lnors_weighted[lidx]); - } - - /* Normalize and validate computed vertex normals. */ - BLI_task_parallel_range(0, numVerts, &data, mesh_calc_normals_poly_finalize_cb, &settings); - - if (free_vnors) { - MEM_freeN(vnors); - } - MEM_freeN(lnors_weighted); -} - -void BKE_mesh_ensure_normals(Mesh *mesh) -{ - if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) { - BKE_mesh_calc_normals(mesh); - } - BLI_assert((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) == 0); -} - -/** - * Called after calculating all modifiers. - */ -void BKE_mesh_ensure_normals_for_display(Mesh *mesh) -{ - switch ((eMeshWrapperType)mesh->runtime.wrapper_type) { - case ME_WRAPPER_TYPE_MDATA: - /* Run code below. */ - break; - case ME_WRAPPER_TYPE_BMESH: { - struct BMEditMesh *em = mesh->edit_mesh; - EditMeshData *emd = mesh->runtime.edit_data; - if (emd->vertexCos) { - BKE_editmesh_cache_ensure_vert_normals(em, emd); - BKE_editmesh_cache_ensure_poly_normals(em, emd); - } - return; - } - } - - float(*poly_nors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL); - const bool do_vert_normals = (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) != 0; - const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL || poly_nors == NULL); - - if (do_vert_normals || do_poly_normals) { - const bool do_add_poly_nors_cddata = (poly_nors == NULL); - if (do_add_poly_nors_cddata) { - poly_nors = MEM_malloc_arrayN((size_t)mesh->totpoly, sizeof(*poly_nors), __func__); - } - - /* calculate poly/vert normals */ - BKE_mesh_calc_normals_poly(mesh->mvert, - NULL, - mesh->totvert, - mesh->mloop, - mesh->mpoly, - mesh->totloop, - mesh->totpoly, - poly_nors, - !do_vert_normals); - - if (do_add_poly_nors_cddata) { - CustomData_add_layer(&mesh->pdata, CD_NORMAL, CD_ASSIGN, poly_nors, mesh->totpoly); - } - - mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; - mesh->runtime.cd_dirty_poly &= ~CD_MASK_NORMAL; - } -} - -/* Note that this does not update the CD_NORMAL layer, - * but does update the normals in the CD_MVERT layer. */ -void BKE_mesh_calc_normals(Mesh *mesh) -{ -#ifdef DEBUG_TIME - TIMEIT_START_AVERAGED(BKE_mesh_calc_normals); -#endif - BKE_mesh_calc_normals_poly(mesh->mvert, - NULL, - mesh->totvert, - mesh->mloop, - mesh->mpoly, - mesh->totloop, - mesh->totpoly, - NULL, - false); -#ifdef DEBUG_TIME - TIMEIT_END_AVERAGED(BKE_mesh_calc_normals); -#endif - mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; -} - -void BKE_mesh_calc_normals_looptri(MVert *mverts, - int numVerts, - const MLoop *mloop, - const MLoopTri *looptri, - int looptri_num, - float (*r_tri_nors)[3]) -{ - float(*tnorms)[3] = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tnorms), "tnorms"); - float(*fnors)[3] = (r_tri_nors) ? - r_tri_nors : - MEM_calloc_arrayN((size_t)looptri_num, sizeof(*fnors), "meshnormals"); - - if (!tnorms || !fnors) { - goto cleanup; - } - - for (int i = 0; i < looptri_num; i++) { - const MLoopTri *lt = &looptri[i]; - float *f_no = fnors[i]; - const uint vtri[3] = { - mloop[lt->tri[0]].v, - mloop[lt->tri[1]].v, - mloop[lt->tri[2]].v, - }; - - normal_tri_v3(f_no, mverts[vtri[0]].co, mverts[vtri[1]].co, mverts[vtri[2]].co); - - accumulate_vertex_normals_tri_v3(tnorms[vtri[0]], - tnorms[vtri[1]], - tnorms[vtri[2]], - f_no, - mverts[vtri[0]].co, - mverts[vtri[1]].co, - mverts[vtri[2]].co); - } - - /* following Mesh convention; we use vertex coordinate itself for normal in this case */ - for (int i = 0; i < numVerts; i++) { - MVert *mv = &mverts[i]; - float *no = tnorms[i]; - - if (UNLIKELY(normalize_v3(no) == 0.0f)) { - normalize_v3_v3(no, mv->co); - } - - normal_float_to_short_v3(mv->no, no); - } - -cleanup: - MEM_freeN(tnorms); - - if (fnors != r_tri_nors) { - MEM_freeN(fnors); - } -} - -void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, - const int numLoops, - const char data_type) -{ - if (!(lnors_spacearr->lspacearr && lnors_spacearr->loops_pool)) { - MemArena *mem; - - if (!lnors_spacearr->mem) { - lnors_spacearr->mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - } - mem = lnors_spacearr->mem; - lnors_spacearr->lspacearr = BLI_memarena_calloc(mem, - sizeof(MLoopNorSpace *) * (size_t)numLoops); - lnors_spacearr->loops_pool = BLI_memarena_alloc(mem, sizeof(LinkNode) * (size_t)numLoops); - - lnors_spacearr->num_spaces = 0; - } - BLI_assert(ELEM(data_type, MLNOR_SPACEARR_BMLOOP_PTR, MLNOR_SPACEARR_LOOP_INDEX)); - lnors_spacearr->data_type = data_type; -} - -void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr) -{ - lnors_spacearr->num_spaces = 0; - lnors_spacearr->lspacearr = NULL; - lnors_spacearr->loops_pool = NULL; - if (lnors_spacearr->mem != NULL) { - BLI_memarena_clear(lnors_spacearr->mem); - } -} - -void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr) -{ - lnors_spacearr->num_spaces = 0; - lnors_spacearr->lspacearr = NULL; - lnors_spacearr->loops_pool = NULL; - BLI_memarena_free(lnors_spacearr->mem); - lnors_spacearr->mem = NULL; -} - -MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr) -{ - lnors_spacearr->num_spaces++; - return BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace)); -} - -/* This threshold is a bit touchy (usual float precision issue), this value seems OK. */ -#define LNOR_SPACE_TRIGO_THRESHOLD (1.0f - 1e-4f) - -/* Should only be called once. - * Beware, this modifies ref_vec and other_vec in place! - * In case no valid space can be generated, ref_alpha and ref_beta are set to zero - * (which means 'use auto lnors'). - */ -void BKE_lnor_space_define(MLoopNorSpace *lnor_space, - const float lnor[3], - float vec_ref[3], - float vec_other[3], - BLI_Stack *edge_vectors) -{ - const float pi2 = (float)M_PI * 2.0f; - float tvec[3], dtp; - const float dtp_ref = dot_v3v3(vec_ref, lnor); - const float dtp_other = dot_v3v3(vec_other, lnor); - - if (UNLIKELY(fabsf(dtp_ref) >= LNOR_SPACE_TRIGO_THRESHOLD || - fabsf(dtp_other) >= LNOR_SPACE_TRIGO_THRESHOLD)) { - /* If vec_ref or vec_other are too much aligned with lnor, we can't build lnor space, - * tag it as invalid and abort. */ - lnor_space->ref_alpha = lnor_space->ref_beta = 0.0f; - - if (edge_vectors) { - BLI_stack_clear(edge_vectors); - } - return; - } - - copy_v3_v3(lnor_space->vec_lnor, lnor); - - /* Compute ref alpha, average angle of all available edge vectors to lnor. */ - if (edge_vectors) { - float alpha = 0.0f; - int nbr = 0; - while (!BLI_stack_is_empty(edge_vectors)) { - const float *vec = BLI_stack_peek(edge_vectors); - alpha += saacosf(dot_v3v3(vec, lnor)); - BLI_stack_discard(edge_vectors); - nbr++; - } - /* Note: In theory, this could be 'nbr > 2', - * but there is one case where we only have two edges for two loops: - * a smooth vertex with only two edges and two faces (our Monkey's nose has that, e.g.). - */ - BLI_assert(nbr >= 2); /* This piece of code shall only be called for more than one loop... */ - lnor_space->ref_alpha = alpha / (float)nbr; - } - else { - lnor_space->ref_alpha = (saacosf(dot_v3v3(vec_ref, lnor)) + - saacosf(dot_v3v3(vec_other, lnor))) / - 2.0f; - } - - /* Project vec_ref on lnor's ortho plane. */ - mul_v3_v3fl(tvec, lnor, dtp_ref); - sub_v3_v3(vec_ref, tvec); - normalize_v3_v3(lnor_space->vec_ref, vec_ref); - - cross_v3_v3v3(tvec, lnor, lnor_space->vec_ref); - normalize_v3_v3(lnor_space->vec_ortho, tvec); - - /* Project vec_other on lnor's ortho plane. */ - mul_v3_v3fl(tvec, lnor, dtp_other); - sub_v3_v3(vec_other, tvec); - normalize_v3(vec_other); - - /* Beta is angle between ref_vec and other_vec, around lnor. */ - dtp = dot_v3v3(lnor_space->vec_ref, vec_other); - if (LIKELY(dtp < LNOR_SPACE_TRIGO_THRESHOLD)) { - const float beta = saacos(dtp); - lnor_space->ref_beta = (dot_v3v3(lnor_space->vec_ortho, vec_other) < 0.0f) ? pi2 - beta : beta; - } - else { - lnor_space->ref_beta = pi2; - } -} - -/** - * Add a new given loop to given lnor_space. - * Depending on \a lnor_space->data_type, we expect \a bm_loop to be a pointer to BMLoop struct - * (in case of BMLOOP_PTR), or NULL (in case of LOOP_INDEX), loop index is then stored in pointer. - * If \a is_single is set, the BMLoop or loop index is directly stored in \a lnor_space->loops - * pointer (since there is only one loop in this fan), - * else it is added to the linked list of loops in the fan. - */ -void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr, - MLoopNorSpace *lnor_space, - const int ml_index, - void *bm_loop, - const bool is_single) -{ - BLI_assert((lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX && bm_loop == NULL) || - (lnors_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR && bm_loop != NULL)); - - lnors_spacearr->lspacearr[ml_index] = lnor_space; - if (bm_loop == NULL) { - bm_loop = POINTER_FROM_INT(ml_index); - } - if (is_single) { - BLI_assert(lnor_space->loops == NULL); - lnor_space->flags |= MLNOR_SPACE_IS_SINGLE; - lnor_space->loops = bm_loop; - } - else { - BLI_assert((lnor_space->flags & MLNOR_SPACE_IS_SINGLE) == 0); - BLI_linklist_prepend_nlink(&lnor_space->loops, bm_loop, &lnors_spacearr->loops_pool[ml_index]); - } -} - -MINLINE float unit_short_to_float(const short val) -{ - return (float)val / (float)SHRT_MAX; -} - -MINLINE short unit_float_to_short(const float val) -{ - /* Rounding... */ - return (short)floorf(val * (float)SHRT_MAX + 0.5f); -} - -void BKE_lnor_space_custom_data_to_normal(MLoopNorSpace *lnor_space, - const short clnor_data[2], - float r_custom_lnor[3]) -{ - /* NOP custom normal data or invalid lnor space, return. */ - if (clnor_data[0] == 0 || lnor_space->ref_alpha == 0.0f || lnor_space->ref_beta == 0.0f) { - copy_v3_v3(r_custom_lnor, lnor_space->vec_lnor); - return; - } - - { - /* TODO Check whether using sincosf() gives any noticeable benefit - * (could not even get it working under linux though)! */ - const float pi2 = (float)(M_PI * 2.0); - const float alphafac = unit_short_to_float(clnor_data[0]); - const float alpha = (alphafac > 0.0f ? lnor_space->ref_alpha : pi2 - lnor_space->ref_alpha) * - alphafac; - const float betafac = unit_short_to_float(clnor_data[1]); - - mul_v3_v3fl(r_custom_lnor, lnor_space->vec_lnor, cosf(alpha)); - - if (betafac == 0.0f) { - madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinf(alpha)); - } - else { - const float sinalpha = sinf(alpha); - const float beta = (betafac > 0.0f ? lnor_space->ref_beta : pi2 - lnor_space->ref_beta) * - betafac; - madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinalpha * cosf(beta)); - madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ortho, sinalpha * sinf(beta)); - } - } -} - -void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, - const float custom_lnor[3], - short r_clnor_data[2]) -{ - /* We use null vector as NOP custom normal (can be simpler than giving autocomputed lnor...). */ - if (is_zero_v3(custom_lnor) || compare_v3v3(lnor_space->vec_lnor, custom_lnor, 1e-4f)) { - r_clnor_data[0] = r_clnor_data[1] = 0; - return; - } - - { - const float pi2 = (float)(M_PI * 2.0); - const float cos_alpha = dot_v3v3(lnor_space->vec_lnor, custom_lnor); - float vec[3], cos_beta; - float alpha; - - alpha = saacosf(cos_alpha); - if (alpha > lnor_space->ref_alpha) { - /* Note we could stick to [0, pi] range here, - * but makes decoding more complex, not worth it. */ - r_clnor_data[0] = unit_float_to_short(-(pi2 - alpha) / (pi2 - lnor_space->ref_alpha)); - } - else { - r_clnor_data[0] = unit_float_to_short(alpha / lnor_space->ref_alpha); - } - - /* Project custom lnor on (vec_ref, vec_ortho) plane. */ - mul_v3_v3fl(vec, lnor_space->vec_lnor, -cos_alpha); - add_v3_v3(vec, custom_lnor); - normalize_v3(vec); - - cos_beta = dot_v3v3(lnor_space->vec_ref, vec); - - if (cos_beta < LNOR_SPACE_TRIGO_THRESHOLD) { - float beta = saacosf(cos_beta); - if (dot_v3v3(lnor_space->vec_ortho, vec) < 0.0f) { - beta = pi2 - beta; - } - - if (beta > lnor_space->ref_beta) { - r_clnor_data[1] = unit_float_to_short(-(pi2 - beta) / (pi2 - lnor_space->ref_beta)); - } - else { - r_clnor_data[1] = unit_float_to_short(beta / lnor_space->ref_beta); - } - } - else { - r_clnor_data[1] = 0; - } - } -} - -#define LOOP_SPLIT_TASK_BLOCK_SIZE 1024 - -typedef struct LoopSplitTaskData { - /* Specific to each instance (each task). */ - - /** We have to create those outside of tasks, since afaik memarena is not threadsafe. */ - MLoopNorSpace *lnor_space; - float (*lnor)[3]; - const MLoop *ml_curr; - const MLoop *ml_prev; - int ml_curr_index; - int ml_prev_index; - /** Also used a flag to switch between single or fan process! */ - const int *e2l_prev; - int mp_index; - - /** This one is special, it's owned and managed by worker tasks, - * avoid to have to create it for each fan! */ - BLI_Stack *edge_vectors; - - char pad_c; -} LoopSplitTaskData; - -typedef struct LoopSplitTaskDataCommon { - /* Read/write. - * Note we do not need to protect it, though, since two different tasks will *always* affect - * different elements in the arrays. */ - MLoopNorSpaceArray *lnors_spacearr; - float (*loopnors)[3]; - short (*clnors_data)[2]; - - /* Read-only. */ - const MVert *mverts; - const MEdge *medges; - const MLoop *mloops; - const MPoly *mpolys; - int (*edge_to_loops)[2]; - int *loop_to_poly; - const float (*polynors)[3]; - - int numEdges; - int numLoops; - int numPolys; -} LoopSplitTaskDataCommon; - -#define INDEX_UNSET INT_MIN -#define INDEX_INVALID -1 -/* See comment about edge_to_loops below. */ -#define IS_EDGE_SHARP(_e2l) (ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID)) - -static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data, - const bool check_angle, - const float split_angle, - const bool do_sharp_edges_tag) -{ - const MVert *mverts = data->mverts; - const MEdge *medges = data->medges; - const MLoop *mloops = data->mloops; - - const MPoly *mpolys = data->mpolys; - - const int numEdges = data->numEdges; - const int numPolys = data->numPolys; - - float(*loopnors)[3] = data->loopnors; /* Note: loopnors may be NULL here. */ - const float(*polynors)[3] = data->polynors; - - int(*edge_to_loops)[2] = data->edge_to_loops; - int *loop_to_poly = data->loop_to_poly; - - BLI_bitmap *sharp_edges = do_sharp_edges_tag ? BLI_BITMAP_NEW(numEdges, __func__) : NULL; - - const MPoly *mp; - int mp_index; - - const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f; - - for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) { - const MLoop *ml_curr; - int *e2l; - int ml_curr_index = mp->loopstart; - const int ml_last_index = (ml_curr_index + mp->totloop) - 1; - - ml_curr = &mloops[ml_curr_index]; - - for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++) { - e2l = edge_to_loops[ml_curr->e]; - - loop_to_poly[ml_curr_index] = mp_index; - - /* Pre-populate all loop normals as if their verts were all-smooth, - * this way we don't have to compute those later! - */ - if (loopnors) { - normal_short_to_float_v3(loopnors[ml_curr_index], mverts[ml_curr->v].no); - } - - /* Check whether current edge might be smooth or sharp */ - if ((e2l[0] | e2l[1]) == 0) { - /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */ - e2l[0] = ml_curr_index; - /* We have to check this here too, else we might miss some flat faces!!! */ - e2l[1] = (mp->flag & ME_SMOOTH) ? INDEX_UNSET : INDEX_INVALID; - } - else if (e2l[1] == INDEX_UNSET) { - const bool is_angle_sharp = (check_angle && - dot_v3v3(polynors[loop_to_poly[e2l[0]]], polynors[mp_index]) < - split_angle_cos); - - /* Second loop using this edge, time to test its sharpness. - * An edge is sharp if it is tagged as such, or its face is not smooth, - * or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the - * same vertex, or angle between both its polys' normals is above split_angle value. - */ - if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) || - ml_curr->v == mloops[e2l[0]].v || is_angle_sharp) { - /* Note: we are sure that loop != 0 here ;) */ - e2l[1] = INDEX_INVALID; - - /* We want to avoid tagging edges as sharp when it is already defined as such by - * other causes than angle threshold... */ - if (do_sharp_edges_tag && is_angle_sharp) { - BLI_BITMAP_SET(sharp_edges, ml_curr->e, true); - } - } - else { - e2l[1] = ml_curr_index; - } - } - else if (!IS_EDGE_SHARP(e2l)) { - /* More than two loops using this edge, tag as sharp if not yet done. */ - e2l[1] = INDEX_INVALID; - - /* We want to avoid tagging edges as sharp when it is already defined as such by - * other causes than angle threshold... */ - if (do_sharp_edges_tag) { - BLI_BITMAP_SET(sharp_edges, ml_curr->e, false); - } - } - /* Else, edge is already 'disqualified' (i.e. sharp)! */ - } - } - - /* If requested, do actual tagging of edges as sharp in another loop. */ - if (do_sharp_edges_tag) { - MEdge *me; - int me_index; - for (me = (MEdge *)medges, me_index = 0; me_index < numEdges; me++, me_index++) { - if (BLI_BITMAP_TEST(sharp_edges, me_index)) { - me->flag |= ME_SHARP; - } - } - - MEM_freeN(sharp_edges); - } -} - -/** - * Define sharp edges as needed to mimic 'autosmooth' from angle threshold. - * - * Used when defining an empty custom loop normals data layer, - * to keep same shading as with autosmooth! - */ -void BKE_edges_sharp_from_angle_set(const struct MVert *mverts, - const int UNUSED(numVerts), - struct MEdge *medges, - const int numEdges, - struct MLoop *mloops, - const int numLoops, - struct MPoly *mpolys, - const float (*polynors)[3], - const int numPolys, - const float split_angle) -{ - if (split_angle >= (float)M_PI) { - /* Nothing to do! */ - return; - } - - /* Mapping edge -> loops. See BKE_mesh_normals_loop_split() for details. */ - int(*edge_to_loops)[2] = MEM_calloc_arrayN((size_t)numEdges, sizeof(*edge_to_loops), __func__); - - /* Simple mapping from a loop to its polygon index. */ - int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__); - - LoopSplitTaskDataCommon common_data = { - .mverts = mverts, - .medges = medges, - .mloops = mloops, - .mpolys = mpolys, - .edge_to_loops = edge_to_loops, - .loop_to_poly = loop_to_poly, - .polynors = polynors, - .numEdges = numEdges, - .numPolys = numPolys, - }; - - mesh_edges_sharp_tag(&common_data, true, split_angle, true); - - MEM_freeN(edge_to_loops); - MEM_freeN(loop_to_poly); -} - -void BKE_mesh_loop_manifold_fan_around_vert_next(const MLoop *mloops, - const MPoly *mpolys, - const int *loop_to_poly, - const int *e2lfan_curr, - const uint mv_pivot_index, - const MLoop **r_mlfan_curr, - int *r_mlfan_curr_index, - int *r_mlfan_vert_index, - int *r_mpfan_curr_index) -{ - const MLoop *mlfan_next; - const MPoly *mpfan_next; - - /* Warning! This is rather complex! - * We have to find our next edge around the vertex (fan mode). - * First we find the next loop, which is either previous or next to mlfan_curr_index, depending - * whether both loops using current edge are in the same direction or not, and whether - * mlfan_curr_index actually uses the vertex we are fanning around! - * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one - * (i.e. not the future mlfan_curr)... - */ - *r_mlfan_curr_index = (e2lfan_curr[0] == *r_mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0]; - *r_mpfan_curr_index = loop_to_poly[*r_mlfan_curr_index]; - - BLI_assert(*r_mlfan_curr_index >= 0); - BLI_assert(*r_mpfan_curr_index >= 0); - - mlfan_next = &mloops[*r_mlfan_curr_index]; - mpfan_next = &mpolys[*r_mpfan_curr_index]; - if (((*r_mlfan_curr)->v == mlfan_next->v && (*r_mlfan_curr)->v == mv_pivot_index) || - ((*r_mlfan_curr)->v != mlfan_next->v && (*r_mlfan_curr)->v != mv_pivot_index)) { - /* We need the previous loop, but current one is our vertex's loop. */ - *r_mlfan_vert_index = *r_mlfan_curr_index; - if (--(*r_mlfan_curr_index) < mpfan_next->loopstart) { - *r_mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1; - } - } - else { - /* We need the next loop, which is also our vertex's loop. */ - if (++(*r_mlfan_curr_index) >= mpfan_next->loopstart + mpfan_next->totloop) { - *r_mlfan_curr_index = mpfan_next->loopstart; - } - *r_mlfan_vert_index = *r_mlfan_curr_index; - } - *r_mlfan_curr = &mloops[*r_mlfan_curr_index]; - /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */ -} - -static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data) -{ - MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr; - const short(*clnors_data)[2] = common_data->clnors_data; - - const MVert *mverts = common_data->mverts; - const MEdge *medges = common_data->medges; - const float(*polynors)[3] = common_data->polynors; - - MLoopNorSpace *lnor_space = data->lnor_space; - float(*lnor)[3] = data->lnor; - const MLoop *ml_curr = data->ml_curr; - const MLoop *ml_prev = data->ml_prev; - const int ml_curr_index = data->ml_curr_index; -#if 0 /* Not needed for 'single' loop. */ - const int ml_prev_index = data->ml_prev_index; - const int *e2l_prev = data->e2l_prev; -#endif - const int mp_index = data->mp_index; - - /* Simple case (both edges around that vertex are sharp in current polygon), - * this loop just takes its poly normal. - */ - copy_v3_v3(*lnor, polynors[mp_index]); - -#if 0 - printf("BASIC: handling loop %d / edge %d / vert %d / poly %d\n", - ml_curr_index, - ml_curr->e, - ml_curr->v, - mp_index); -#endif - - /* If needed, generate this (simple!) lnor space. */ - if (lnors_spacearr) { - float vec_curr[3], vec_prev[3]; - - const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */ - const MVert *mv_pivot = &mverts[mv_pivot_index]; - const MEdge *me_curr = &medges[ml_curr->e]; - const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] : - &mverts[me_curr->v1]; - const MEdge *me_prev = &medges[ml_prev->e]; - const MVert *mv_3 = (me_prev->v1 == mv_pivot_index) ? &mverts[me_prev->v2] : - &mverts[me_prev->v1]; - - sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co); - normalize_v3(vec_curr); - sub_v3_v3v3(vec_prev, mv_3->co, mv_pivot->co); - normalize_v3(vec_prev); - - BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, NULL); - /* We know there is only one loop in this space, - * no need to create a linklist in this case... */ - BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, NULL, true); - - if (clnors_data) { - BKE_lnor_space_custom_data_to_normal(lnor_space, clnors_data[ml_curr_index], *lnor); - } - } -} - -static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data) -{ - MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr; - float(*loopnors)[3] = common_data->loopnors; - short(*clnors_data)[2] = common_data->clnors_data; - - const MVert *mverts = common_data->mverts; - const MEdge *medges = common_data->medges; - const MLoop *mloops = common_data->mloops; - const MPoly *mpolys = common_data->mpolys; - const int(*edge_to_loops)[2] = common_data->edge_to_loops; - const int *loop_to_poly = common_data->loop_to_poly; - const float(*polynors)[3] = common_data->polynors; - - MLoopNorSpace *lnor_space = data->lnor_space; -#if 0 /* Not needed for 'fan' loops. */ - float(*lnor)[3] = data->lnor; -#endif - const MLoop *ml_curr = data->ml_curr; - const MLoop *ml_prev = data->ml_prev; - const int ml_curr_index = data->ml_curr_index; - const int ml_prev_index = data->ml_prev_index; - const int mp_index = data->mp_index; - const int *e2l_prev = data->e2l_prev; - - BLI_Stack *edge_vectors = data->edge_vectors; - - /* Gah... We have to fan around current vertex, until we find the other non-smooth edge, - * and accumulate face normals into the vertex! - * Note in case this vertex has only one sharp edges, this is a waste because the normal is the - * same as the vertex normal, but I do not see any easy way to detect that (would need to count - * number of sharp edges per vertex, I doubt the additional memory usage would be worth it, - * especially as it should not be a common case in real-life meshes anyway). - */ - const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */ - const MVert *mv_pivot = &mverts[mv_pivot_index]; - - /* ml_curr would be mlfan_prev if we needed that one. */ - const MEdge *me_org = &medges[ml_curr->e]; - - const int *e2lfan_curr; - float vec_curr[3], vec_prev[3], vec_org[3]; - const MLoop *mlfan_curr; - float lnor[3] = {0.0f, 0.0f, 0.0f}; - /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */ - int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index; - - /* We validate clnors data on the fly - cheapest way to do! */ - int clnors_avg[2] = {0, 0}; - short(*clnor_ref)[2] = NULL; - int clnors_nbr = 0; - bool clnors_invalid = false; - - /* Temp loop normal stack. */ - BLI_SMALLSTACK_DECLARE(normal, float *); - /* Temp clnors stack. */ - BLI_SMALLSTACK_DECLARE(clnors, short *); - - e2lfan_curr = e2l_prev; - mlfan_curr = ml_prev; - mlfan_curr_index = ml_prev_index; - mlfan_vert_index = ml_curr_index; - mpfan_curr_index = mp_index; - - BLI_assert(mlfan_curr_index >= 0); - BLI_assert(mlfan_vert_index >= 0); - BLI_assert(mpfan_curr_index >= 0); - - /* Only need to compute previous edge's vector once, then we can just reuse old current one! */ - { - const MVert *mv_2 = (me_org->v1 == mv_pivot_index) ? &mverts[me_org->v2] : &mverts[me_org->v1]; - - sub_v3_v3v3(vec_org, mv_2->co, mv_pivot->co); - normalize_v3(vec_org); - copy_v3_v3(vec_prev, vec_org); - - if (lnors_spacearr) { - BLI_stack_push(edge_vectors, vec_org); - } - } - - // printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e); - - while (true) { - const MEdge *me_curr = &medges[mlfan_curr->e]; - /* Compute edge vectors. - * NOTE: We could pre-compute those into an array, in the first iteration, instead of computing - * them twice (or more) here. However, time gained is not worth memory and time lost, - * given the fact that this code should not be called that much in real-life meshes... - */ - { - const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] : - &mverts[me_curr->v1]; - - sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co); - normalize_v3(vec_curr); - } - - // printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index); - - { - /* Code similar to accumulate_vertex_normals_poly_v3. */ - /* Calculate angle between the two poly edges incident on this vertex. */ - const float fac = saacos(dot_v3v3(vec_curr, vec_prev)); - /* Accumulate */ - madd_v3_v3fl(lnor, polynors[mpfan_curr_index], fac); - - if (clnors_data) { - /* Accumulate all clnors, if they are not all equal we have to fix that! */ - short(*clnor)[2] = &clnors_data[mlfan_vert_index]; - if (clnors_nbr) { - clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] || (*clnor_ref)[1] != (*clnor)[1]); - } - else { - clnor_ref = clnor; - } - clnors_avg[0] += (*clnor)[0]; - clnors_avg[1] += (*clnor)[1]; - clnors_nbr++; - /* We store here a pointer to all custom lnors processed. */ - BLI_SMALLSTACK_PUSH(clnors, (short *)*clnor); - } - } - - /* We store here a pointer to all loop-normals processed. */ - BLI_SMALLSTACK_PUSH(normal, (float *)(loopnors[mlfan_vert_index])); - - if (lnors_spacearr) { - /* Assign current lnor space to current 'vertex' loop. */ - BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, NULL, false); - if (me_curr != me_org) { - /* We store here all edges-normalized vectors processed. */ - BLI_stack_push(edge_vectors, vec_curr); - } - } - - if (IS_EDGE_SHARP(e2lfan_curr) || (me_curr == me_org)) { - /* Current edge is sharp and we have finished with this fan of faces around this vert, - * or this vert is smooth, and we have completed a full turn around it. - */ - // printf("FAN: Finished!\n"); - break; - } - - copy_v3_v3(vec_prev, vec_curr); - - /* Find next loop of the smooth fan. */ - BKE_mesh_loop_manifold_fan_around_vert_next(mloops, - mpolys, - loop_to_poly, - e2lfan_curr, - mv_pivot_index, - &mlfan_curr, - &mlfan_curr_index, - &mlfan_vert_index, - &mpfan_curr_index); - - e2lfan_curr = edge_to_loops[mlfan_curr->e]; - } - - { - float lnor_len = normalize_v3(lnor); - - /* If we are generating lnor spacearr, we can now define the one for this fan, - * and optionally compute final lnor from custom data too! - */ - if (lnors_spacearr) { - if (UNLIKELY(lnor_len == 0.0f)) { - /* Use vertex normal as fallback! */ - copy_v3_v3(lnor, loopnors[mlfan_vert_index]); - lnor_len = 1.0f; - } - - BKE_lnor_space_define(lnor_space, lnor, vec_org, vec_curr, edge_vectors); - - if (clnors_data) { - if (clnors_invalid) { - short *clnor; - - clnors_avg[0] /= clnors_nbr; - clnors_avg[1] /= clnors_nbr; - /* Fix/update all clnors of this fan with computed average value. */ - if (G.debug & G_DEBUG) { - printf("Invalid clnors in this fan!\n"); - } - while ((clnor = BLI_SMALLSTACK_POP(clnors))) { - // print_v2("org clnor", clnor); - clnor[0] = (short)clnors_avg[0]; - clnor[1] = (short)clnors_avg[1]; - } - // print_v2("new clnors", clnors_avg); - } - /* Extra bonus: since small-stack is local to this function, - * no more need to empty it at all cost! */ - - BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor); - } - } - - /* In case we get a zero normal here, just use vertex normal already set! */ - if (LIKELY(lnor_len != 0.0f)) { - /* Copy back the final computed normal into all related loop-normals. */ - float *nor; - - while ((nor = BLI_SMALLSTACK_POP(normal))) { - copy_v3_v3(nor, lnor); - } - } - /* Extra bonus: since small-stack is local to this function, - * no more need to empty it at all cost! */ - } -} - -static void loop_split_worker_do(LoopSplitTaskDataCommon *common_data, - LoopSplitTaskData *data, - BLI_Stack *edge_vectors) -{ - BLI_assert(data->ml_curr); - if (data->e2l_prev) { - BLI_assert((edge_vectors == NULL) || BLI_stack_is_empty(edge_vectors)); - data->edge_vectors = edge_vectors; - split_loop_nor_fan_do(common_data, data); - } - else { - /* No need for edge_vectors for 'single' case! */ - split_loop_nor_single_do(common_data, data); - } -} - -static void loop_split_worker(TaskPool *__restrict pool, void *taskdata) -{ - LoopSplitTaskDataCommon *common_data = BLI_task_pool_user_data(pool); - LoopSplitTaskData *data = taskdata; - - /* Temp edge vectors stack, only used when computing lnor spacearr. */ - BLI_Stack *edge_vectors = common_data->lnors_spacearr ? - BLI_stack_new(sizeof(float[3]), __func__) : - NULL; - -#ifdef DEBUG_TIME - TIMEIT_START_AVERAGED(loop_split_worker); -#endif - - for (int i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) { - /* A NULL ml_curr is used to tag ended data! */ - if (data->ml_curr == NULL) { - break; - } - - loop_split_worker_do(common_data, data, edge_vectors); - } - - if (edge_vectors) { - BLI_stack_free(edge_vectors); - } - -#ifdef DEBUG_TIME - TIMEIT_END_AVERAGED(loop_split_worker); -#endif -} - -/** - * Check whether given loop is part of an unknown-so-far cyclic smooth fan, or not. - * Needed because cyclic smooth fans have no obvious 'entry point', - * and yet we need to walk them once, and only once. - */ -static bool loop_split_generator_check_cyclic_smooth_fan(const MLoop *mloops, - const MPoly *mpolys, - const int (*edge_to_loops)[2], - const int *loop_to_poly, - const int *e2l_prev, - BLI_bitmap *skip_loops, - const MLoop *ml_curr, - const MLoop *ml_prev, - const int ml_curr_index, - const int ml_prev_index, - const int mp_curr_index) -{ - const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */ - const int *e2lfan_curr; - const MLoop *mlfan_curr; - /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */ - int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index; - - e2lfan_curr = e2l_prev; - if (IS_EDGE_SHARP(e2lfan_curr)) { - /* Sharp loop, so not a cyclic smooth fan... */ - return false; - } - - mlfan_curr = ml_prev; - mlfan_curr_index = ml_prev_index; - mlfan_vert_index = ml_curr_index; - mpfan_curr_index = mp_curr_index; - - BLI_assert(mlfan_curr_index >= 0); - BLI_assert(mlfan_vert_index >= 0); - BLI_assert(mpfan_curr_index >= 0); - - BLI_assert(!BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)); - BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index); - - while (true) { - /* Find next loop of the smooth fan. */ - BKE_mesh_loop_manifold_fan_around_vert_next(mloops, - mpolys, - loop_to_poly, - e2lfan_curr, - mv_pivot_index, - &mlfan_curr, - &mlfan_curr_index, - &mlfan_vert_index, - &mpfan_curr_index); - - e2lfan_curr = edge_to_loops[mlfan_curr->e]; - - if (IS_EDGE_SHARP(e2lfan_curr)) { - /* Sharp loop/edge, so not a cyclic smooth fan... */ - return false; - } - /* Smooth loop/edge... */ - if (BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)) { - if (mlfan_vert_index == ml_curr_index) { - /* We walked around a whole cyclic smooth fan without finding any already-processed loop, - * means we can use initial ml_curr/ml_prev edge as start for this smooth fan. */ - return true; - } - /* ... already checked in some previous looping, we can abort. */ - return false; - } - - /* ... we can skip it in future, and keep checking the smooth fan. */ - BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index); - } -} - -static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common_data) -{ - MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr; - float(*loopnors)[3] = common_data->loopnors; - - const MLoop *mloops = common_data->mloops; - const MPoly *mpolys = common_data->mpolys; - const int *loop_to_poly = common_data->loop_to_poly; - const int(*edge_to_loops)[2] = common_data->edge_to_loops; - const int numLoops = common_data->numLoops; - const int numPolys = common_data->numPolys; - - const MPoly *mp; - int mp_index; - - const MLoop *ml_curr; - const MLoop *ml_prev; - int ml_curr_index; - int ml_prev_index; - - BLI_bitmap *skip_loops = BLI_BITMAP_NEW(numLoops, __func__); - - LoopSplitTaskData *data_buff = NULL; - int data_idx = 0; - - /* Temp edge vectors stack, only used when computing lnor spacearr - * (and we are not multi-threading). */ - BLI_Stack *edge_vectors = NULL; - -#ifdef DEBUG_TIME - TIMEIT_START_AVERAGED(loop_split_generator); -#endif - - if (!pool) { - if (lnors_spacearr) { - edge_vectors = BLI_stack_new(sizeof(float[3]), __func__); - } - } - - /* We now know edges that can be smoothed (with their vector, and their two loops), - * and edges that will be hard! Now, time to generate the normals. - */ - for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) { - float(*lnors)[3]; - const int ml_last_index = (mp->loopstart + mp->totloop) - 1; - ml_curr_index = mp->loopstart; - ml_prev_index = ml_last_index; - - ml_curr = &mloops[ml_curr_index]; - ml_prev = &mloops[ml_prev_index]; - lnors = &loopnors[ml_curr_index]; - - for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++, lnors++) { - const int *e2l_curr = edge_to_loops[ml_curr->e]; - const int *e2l_prev = edge_to_loops[ml_prev->e]; - -#if 0 - printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)...", - ml_curr_index, - ml_curr->e, - ml_curr->v, - IS_EDGE_SHARP(e2l_curr), - BLI_BITMAP_TEST_BOOL(skip_loops, ml_curr_index)); -#endif - - /* A smooth edge, we have to check for cyclic smooth fan case. - * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge - * as 'entry point', otherwise we can skip it. */ - - /* Note: In theory, we could make loop_split_generator_check_cyclic_smooth_fan() store - * mlfan_vert_index'es and edge indexes in two stacks, to avoid having to fan again around - * the vert during actual computation of clnor & clnorspace. However, this would complicate - * the code, add more memory usage, and despite its logical complexity, - * loop_manifold_fan_around_vert_next() is quite cheap in term of CPU cycles, - * so really think it's not worth it. */ - if (!IS_EDGE_SHARP(e2l_curr) && (BLI_BITMAP_TEST(skip_loops, ml_curr_index) || - !loop_split_generator_check_cyclic_smooth_fan(mloops, - mpolys, - edge_to_loops, - loop_to_poly, - e2l_prev, - skip_loops, - ml_curr, - ml_prev, - ml_curr_index, - ml_prev_index, - mp_index))) { - // printf("SKIPPING!\n"); - } - else { - LoopSplitTaskData *data, data_local; - - // printf("PROCESSING!\n"); - - if (pool) { - if (data_idx == 0) { - data_buff = MEM_calloc_arrayN( - LOOP_SPLIT_TASK_BLOCK_SIZE, sizeof(*data_buff), __func__); - } - data = &data_buff[data_idx]; - } - else { - data = &data_local; - memset(data, 0, sizeof(*data)); - } - - if (IS_EDGE_SHARP(e2l_curr) && IS_EDGE_SHARP(e2l_prev)) { - data->lnor = lnors; - data->ml_curr = ml_curr; - data->ml_prev = ml_prev; - data->ml_curr_index = ml_curr_index; -#if 0 /* Not needed for 'single' loop. */ - data->ml_prev_index = ml_prev_index; - data->e2l_prev = NULL; /* Tag as 'single' task. */ -#endif - data->mp_index = mp_index; - if (lnors_spacearr) { - data->lnor_space = BKE_lnor_space_create(lnors_spacearr); - } - } - /* We *do not need* to check/tag loops as already computed! - * Due to the fact a loop only links to one of its two edges, - * a same fan *will never be walked more than once!* - * Since we consider edges having neighbor polys with inverted - * (flipped) normals as sharp, we are sure that no fan will be skipped, - * even only considering the case (sharp curr_edge, smooth prev_edge), - * and not the alternative (smooth curr_edge, sharp prev_edge). - * All this due/thanks to link between normals and loop ordering (i.e. winding). - */ - else { -#if 0 /* Not needed for 'fan' loops. */ - data->lnor = lnors; -#endif - data->ml_curr = ml_curr; - data->ml_prev = ml_prev; - data->ml_curr_index = ml_curr_index; - data->ml_prev_index = ml_prev_index; - data->e2l_prev = e2l_prev; /* Also tag as 'fan' task. */ - data->mp_index = mp_index; - if (lnors_spacearr) { - data->lnor_space = BKE_lnor_space_create(lnors_spacearr); - } - } - - if (pool) { - data_idx++; - if (data_idx == LOOP_SPLIT_TASK_BLOCK_SIZE) { - BLI_task_pool_push(pool, loop_split_worker, data_buff, true, NULL); - data_idx = 0; - } - } - else { - loop_split_worker_do(common_data, data, edge_vectors); - } - } - - ml_prev = ml_curr; - ml_prev_index = ml_curr_index; - } - } - - /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper, - * everything is fine. */ - if (pool && data_idx) { - BLI_task_pool_push(pool, loop_split_worker, data_buff, true, NULL); - } - - if (edge_vectors) { - BLI_stack_free(edge_vectors); - } - MEM_freeN(skip_loops); - -#ifdef DEBUG_TIME - TIMEIT_END_AVERAGED(loop_split_generator); -#endif -} - -/** - * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals'). - * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry - * (splitting edges). - */ -void BKE_mesh_normals_loop_split(const MVert *mverts, - const int UNUSED(numVerts), - MEdge *medges, - const int numEdges, - MLoop *mloops, - float (*r_loopnors)[3], - const int numLoops, - MPoly *mpolys, - const float (*polynors)[3], - const int numPolys, - const bool use_split_normals, - const float split_angle, - MLoopNorSpaceArray *r_lnors_spacearr, - short (*clnors_data)[2], - int *r_loop_to_poly) -{ - /* For now this is not supported. - * If we do not use split normals, we do not generate anything fancy! */ - BLI_assert(use_split_normals || !(r_lnors_spacearr)); - - if (!use_split_normals) { - /* In this case, we simply fill lnors with vnors (or fnors for flat faces), quite simple! - * Note this is done here to keep some logic and consistency in this quite complex code, - * since we may want to use lnors even when mesh's 'autosmooth' is disabled - * (see e.g. mesh mapping code). - * As usual, we could handle that on case-by-case basis, - * but simpler to keep it well confined here. - */ - int mp_index; - - for (mp_index = 0; mp_index < numPolys; mp_index++) { - MPoly *mp = &mpolys[mp_index]; - int ml_index = mp->loopstart; - const int ml_index_end = ml_index + mp->totloop; - const bool is_poly_flat = ((mp->flag & ME_SMOOTH) == 0); - - for (; ml_index < ml_index_end; ml_index++) { - if (r_loop_to_poly) { - r_loop_to_poly[ml_index] = mp_index; - } - if (is_poly_flat) { - copy_v3_v3(r_loopnors[ml_index], polynors[mp_index]); - } - else { - normal_short_to_float_v3(r_loopnors[ml_index], mverts[mloops[ml_index].v].no); - } - } - } - return; - } - - /** - * Mapping edge -> loops. - * If that edge is used by more than two loops (polys), - * it is always sharp (and tagged as such, see below). - * We also use the second loop index as a kind of flag: - * - * - smooth edge: > 0. - * - sharp edge: < 0 (INDEX_INVALID || INDEX_UNSET). - * - unset: INDEX_UNSET. - * - * Note that currently we only have two values for second loop of sharp edges. - * However, if needed, we can store the negated value of loop index instead of INDEX_INVALID - * to retrieve the real value later in code). - * Note also that loose edges always have both values set to 0! */ - int(*edge_to_loops)[2] = MEM_calloc_arrayN((size_t)numEdges, sizeof(*edge_to_loops), __func__); - - /* Simple mapping from a loop to its polygon index. */ - int *loop_to_poly = r_loop_to_poly ? - r_loop_to_poly : - MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__); - - /* When using custom loop normals, disable the angle feature! */ - const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == NULL); - - MLoopNorSpaceArray _lnors_spacearr = {NULL}; - -#ifdef DEBUG_TIME - TIMEIT_START_AVERAGED(BKE_mesh_normals_loop_split); -#endif - - if (!r_lnors_spacearr && clnors_data) { - /* We need to compute lnor spacearr if some custom lnor data are given to us! */ - r_lnors_spacearr = &_lnors_spacearr; - } - if (r_lnors_spacearr) { - BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops, MLNOR_SPACEARR_LOOP_INDEX); - } - - /* Init data common to all tasks. */ - LoopSplitTaskDataCommon common_data = { - .lnors_spacearr = r_lnors_spacearr, - .loopnors = r_loopnors, - .clnors_data = clnors_data, - .mverts = mverts, - .medges = medges, - .mloops = mloops, - .mpolys = mpolys, - .edge_to_loops = edge_to_loops, - .loop_to_poly = loop_to_poly, - .polynors = polynors, - .numEdges = numEdges, - .numLoops = numLoops, - .numPolys = numPolys, - }; - - /* This first loop check which edges are actually smooth, and compute edge vectors. */ - mesh_edges_sharp_tag(&common_data, check_angle, split_angle, false); - - if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) { - /* Not enough loops to be worth the whole threading overhead... */ - loop_split_generator(NULL, &common_data); - } - else { - TaskPool *task_pool = BLI_task_pool_create(&common_data, TASK_PRIORITY_HIGH); - - loop_split_generator(task_pool, &common_data); - - BLI_task_pool_work_and_wait(task_pool); - - BLI_task_pool_free(task_pool); - } - - MEM_freeN(edge_to_loops); - if (!r_loop_to_poly) { - MEM_freeN(loop_to_poly); - } - - if (r_lnors_spacearr) { - if (r_lnors_spacearr == &_lnors_spacearr) { - BKE_lnor_spacearr_free(r_lnors_spacearr); - } - } - -#ifdef DEBUG_TIME - TIMEIT_END_AVERAGED(BKE_mesh_normals_loop_split); -#endif -} - -#undef INDEX_UNSET -#undef INDEX_INVALID -#undef IS_EDGE_SHARP - -/** - * Compute internal representation of given custom normals (as an array of float[2]). - * It also makes sure the mesh matches those custom normals, by setting sharp edges flag as needed - * to get a same custom lnor for all loops sharing a same smooth fan. - * If use_vertices if true, r_custom_loopnors is assumed to be per-vertex, not per-loop - * (this allows to set whole vert's normals at once, useful in some cases). - * r_custom_loopnors is expected to have normalized normals, or zero ones, - * in which case they will be replaced by default loop/vertex normal. - */ -static void mesh_normals_loop_custom_set(const MVert *mverts, - const int numVerts, - MEdge *medges, - const int numEdges, - MLoop *mloops, - float (*r_custom_loopnors)[3], - const int numLoops, - MPoly *mpolys, - const float (*polynors)[3], - const int numPolys, - short (*r_clnors_data)[2], - const bool use_vertices) -{ - /* We *may* make that poor BKE_mesh_normals_loop_split() even more complex by making it handling - * that feature too, would probably be more efficient in absolute. - * However, this function *is not* performance-critical, since it is mostly expected to be called - * by io addons when importing custom normals, and modifier - * (and perhaps from some editing tools later?). - * So better to keep some simplicity here, and just call BKE_mesh_normals_loop_split() twice! - */ - MLoopNorSpaceArray lnors_spacearr = {NULL}; - BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)numLoops, __func__); - float(*lnors)[3] = MEM_calloc_arrayN((size_t)numLoops, sizeof(*lnors), __func__); - int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(int), __func__); - /* In this case we always consider split nors as ON, - * and do not want to use angle to define smooth fans! */ - const bool use_split_normals = true; - const float split_angle = (float)M_PI; - - BLI_SMALLSTACK_DECLARE(clnors_data, short *); - - /* Compute current lnor spacearr. */ - BKE_mesh_normals_loop_split(mverts, - numVerts, - medges, - numEdges, - mloops, - lnors, - numLoops, - mpolys, - polynors, - numPolys, - use_split_normals, - split_angle, - &lnors_spacearr, - NULL, - loop_to_poly); - - /* Set all given zero vectors to their default value. */ - if (use_vertices) { - for (int i = 0; i < numVerts; i++) { - if (is_zero_v3(r_custom_loopnors[i])) { - normal_short_to_float_v3(r_custom_loopnors[i], mverts[i].no); - } - } - } - else { - for (int i = 0; i < numLoops; i++) { - if (is_zero_v3(r_custom_loopnors[i])) { - copy_v3_v3(r_custom_loopnors[i], lnors[i]); - } - } - } - - BLI_assert(lnors_spacearr.data_type == MLNOR_SPACEARR_LOOP_INDEX); - - /* Now, check each current smooth fan (one lnor space per smooth fan!), - * and if all its matching custom lnors are not (enough) equal, add sharp edges as needed. - * This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans - * matching given custom lnors. - * Note this code *will never* unsharp edges! And quite obviously, - * when we set custom normals per vertices, running this is absolutely useless. - */ - if (!use_vertices) { - for (int i = 0; i < numLoops; i++) { - if (!lnors_spacearr.lspacearr[i]) { - /* This should not happen in theory, but in some rare case (probably ugly geometry) - * we can get some NULL loopspacearr at this point. :/ - * Maybe we should set those loops' edges as sharp? - */ - BLI_BITMAP_ENABLE(done_loops, i); - if (G.debug & G_DEBUG) { - printf("WARNING! Getting invalid NULL loop space for loop %d!\n", i); - } - continue; - } - - if (!BLI_BITMAP_TEST(done_loops, i)) { - /* Notes: - * * In case of mono-loop smooth fan, we have nothing to do. - * * Loops in this linklist are ordered (in reversed order compared to how they were - * discovered by BKE_mesh_normals_loop_split(), but this is not a problem). - * Which means if we find a mismatching clnor, - * we know all remaining loops will have to be in a new, different smooth fan/lnor space. - * * In smooth fan case, we compare each clnor against a ref one, - * to avoid small differences adding up into a real big one in the end! - */ - if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) { - BLI_BITMAP_ENABLE(done_loops, i); - continue; - } - - LinkNode *loops = lnors_spacearr.lspacearr[i]->loops; - MLoop *prev_ml = NULL; - const float *org_nor = NULL; - - while (loops) { - const int lidx = POINTER_AS_INT(loops->link); - MLoop *ml = &mloops[lidx]; - const int nidx = lidx; - float *nor = r_custom_loopnors[nidx]; - - if (!org_nor) { - org_nor = nor; - } - else if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) { - /* Current normal differs too much from org one, we have to tag the edge between - * previous loop's face and current's one as sharp. - * We know those two loops do not point to the same edge, - * since we do not allow reversed winding in a same smooth fan. - */ - const MPoly *mp = &mpolys[loop_to_poly[lidx]]; - const MLoop *mlp = - &mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1]; - medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP; - - org_nor = nor; - } - - prev_ml = ml; - loops = loops->next; - BLI_BITMAP_ENABLE(done_loops, lidx); - } - - /* We also have to check between last and first loops, - * otherwise we may miss some sharp edges here! - * This is just a simplified version of above while loop. - * See T45984. */ - loops = lnors_spacearr.lspacearr[i]->loops; - if (loops && org_nor) { - const int lidx = POINTER_AS_INT(loops->link); - MLoop *ml = &mloops[lidx]; - const int nidx = lidx; - float *nor = r_custom_loopnors[nidx]; - - if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) { - const MPoly *mp = &mpolys[loop_to_poly[lidx]]; - const MLoop *mlp = - &mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1]; - medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP; - } - } - } - } - - /* And now, recompute our new auto lnors and lnor spacearr! */ - BKE_lnor_spacearr_clear(&lnors_spacearr); - BKE_mesh_normals_loop_split(mverts, - numVerts, - medges, - numEdges, - mloops, - lnors, - numLoops, - mpolys, - polynors, - numPolys, - use_split_normals, - split_angle, - &lnors_spacearr, - NULL, - loop_to_poly); - } - else { - BLI_bitmap_set_all(done_loops, true, (size_t)numLoops); - } - - /* And we just have to convert plain object-space custom normals to our - * lnor space-encoded ones. */ - for (int i = 0; i < numLoops; i++) { - if (!lnors_spacearr.lspacearr[i]) { - BLI_BITMAP_DISABLE(done_loops, i); - if (G.debug & G_DEBUG) { - printf("WARNING! Still getting invalid NULL loop space in second loop for loop %d!\n", i); - } - continue; - } - - if (BLI_BITMAP_TEST_BOOL(done_loops, i)) { - /* Note we accumulate and average all custom normals in current smooth fan, - * to avoid getting different clnors data (tiny differences in plain custom normals can - * give rather huge differences in computed 2D factors). - */ - LinkNode *loops = lnors_spacearr.lspacearr[i]->loops; - if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) { - BLI_assert(POINTER_AS_INT(loops) == i); - const int nidx = use_vertices ? (int)mloops[i].v : i; - float *nor = r_custom_loopnors[nidx]; - - BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]); - BLI_BITMAP_DISABLE(done_loops, i); - } - else { - int nbr_nors = 0; - float avg_nor[3]; - short clnor_data_tmp[2], *clnor_data; - - zero_v3(avg_nor); - while (loops) { - const int lidx = POINTER_AS_INT(loops->link); - const int nidx = use_vertices ? (int)mloops[lidx].v : lidx; - float *nor = r_custom_loopnors[nidx]; - - nbr_nors++; - add_v3_v3(avg_nor, nor); - BLI_SMALLSTACK_PUSH(clnors_data, (short *)r_clnors_data[lidx]); - - loops = loops->next; - BLI_BITMAP_DISABLE(done_loops, lidx); - } - - mul_v3_fl(avg_nor, 1.0f / (float)nbr_nors); - BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], avg_nor, clnor_data_tmp); - - while ((clnor_data = BLI_SMALLSTACK_POP(clnors_data))) { - clnor_data[0] = clnor_data_tmp[0]; - clnor_data[1] = clnor_data_tmp[1]; - } - } - } - } - - MEM_freeN(lnors); - MEM_freeN(loop_to_poly); - MEM_freeN(done_loops); - BKE_lnor_spacearr_free(&lnors_spacearr); -} - -void BKE_mesh_normals_loop_custom_set(const MVert *mverts, - const int numVerts, - MEdge *medges, - const int numEdges, - MLoop *mloops, - float (*r_custom_loopnors)[3], - const int numLoops, - MPoly *mpolys, - const float (*polynors)[3], - const int numPolys, - short (*r_clnors_data)[2]) -{ - mesh_normals_loop_custom_set(mverts, - numVerts, - medges, - numEdges, - mloops, - r_custom_loopnors, - numLoops, - mpolys, - polynors, - numPolys, - r_clnors_data, - false); -} - -void BKE_mesh_normals_loop_custom_from_vertices_set(const MVert *mverts, - float (*r_custom_vertnors)[3], - const int numVerts, - MEdge *medges, - const int numEdges, - MLoop *mloops, - const int numLoops, - MPoly *mpolys, - const float (*polynors)[3], - const int numPolys, - short (*r_clnors_data)[2]) -{ - mesh_normals_loop_custom_set(mverts, - numVerts, - medges, - numEdges, - mloops, - r_custom_vertnors, - numLoops, - mpolys, - polynors, - numPolys, - r_clnors_data, - true); -} - -static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const bool use_vertices) -{ - short(*clnors)[2]; - const int numloops = mesh->totloop; - - clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); - if (clnors != NULL) { - memset(clnors, 0, sizeof(*clnors) * (size_t)numloops); - } - else { - clnors = CustomData_add_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, numloops); - } - - float(*polynors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL); - bool free_polynors = false; - if (polynors == NULL) { - polynors = MEM_mallocN(sizeof(float[3]) * (size_t)mesh->totpoly, __func__); - BKE_mesh_calc_normals_poly(mesh->mvert, - NULL, - mesh->totvert, - mesh->mloop, - mesh->mpoly, - mesh->totloop, - mesh->totpoly, - polynors, - false); - free_polynors = true; - } - - mesh_normals_loop_custom_set(mesh->mvert, - mesh->totvert, - mesh->medge, - mesh->totedge, - mesh->mloop, - r_custom_nors, - mesh->totloop, - mesh->mpoly, - polynors, - mesh->totpoly, - clnors, - use_vertices); - - if (free_polynors) { - MEM_freeN(polynors); - } -} - -/** - * Higher level functions hiding most of the code needed around call to - * #BKE_mesh_normals_loop_custom_set(). - * - * \param r_custom_loopnors: is not const, since code will replace zero_v3 normals there - * with automatically computed vectors. - */ -void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loopnors)[3]) -{ - mesh_set_custom_normals(mesh, r_custom_loopnors, false); -} - -/** - * Higher level functions hiding most of the code needed around call to - * #BKE_mesh_normals_loop_custom_from_vertices_set(). - * - * \param r_custom_vertnors: is not const, since code will replace zero_v3 normals there - * with automatically computed vectors. - */ -void BKE_mesh_set_custom_normals_from_vertices(Mesh *mesh, float (*r_custom_vertnors)[3]) -{ - mesh_set_custom_normals(mesh, r_custom_vertnors, true); -} - -/** - * Computes average per-vertex normals from given custom loop normals. - * - * \param clnors: The computed custom loop normals. - * \param r_vert_clnors: The (already allocated) array where to store averaged per-vertex normals. - */ -void BKE_mesh_normals_loop_to_vertex(const int numVerts, - const MLoop *mloops, - const int numLoops, - const float (*clnors)[3], - float (*r_vert_clnors)[3]) -{ - int *vert_loops_nbr = MEM_calloc_arrayN((size_t)numVerts, sizeof(*vert_loops_nbr), __func__); - - copy_vn_fl((float *)r_vert_clnors, 3 * numVerts, 0.0f); - - int i; - const MLoop *ml; - for (i = 0, ml = mloops; i < numLoops; i++, ml++) { - const uint v = ml->v; - - add_v3_v3(r_vert_clnors[v], clnors[i]); - vert_loops_nbr[v]++; - } - - for (i = 0; i < numVerts; i++) { - mul_v3_fl(r_vert_clnors[i], 1.0f / (float)vert_loops_nbr[i]); - } - - MEM_freeN(vert_loops_nbr); -} - -#undef LNOR_SPACE_TRIGO_THRESHOLD - -/** \} */ /* -------------------------------------------------------------------- */ /** \name Polygon Calculations @@ -3280,8 +1174,8 @@ void BKE_mesh_flush_select_from_polys_ex(MVert *mvert, i = totpoly; for (mp = mpoly; i--; mp++) { - /* assume if its selected its not hidden and none of its verts/edges are hidden - * (a common assumption)*/ + /* Assume if its selected its not hidden and none of its verts/edges are hidden + * (a common assumption). */ if (mp->flag & ME_FACE_SEL) { const MLoop *ml; int j; diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index d4119f48193..c469a65449d 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -535,7 +535,7 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, * * This has the advantage that it can operate on any data-types. * - * \param totsource: The total number of elements the that \a final_origindex points to. + * \param totsource: The total number of elements that \a final_origindex points to. * \param totfinal: The size of \a final_origindex * \param final_origindex: The size of the final array. * diff --git a/source/blender/blenkernel/intern/mesh_merge.c b/source/blender/blenkernel/intern/mesh_merge.c index fb73152cb8e..1e51ee73c7c 100644 --- a/source/blender/blenkernel/intern/mesh_merge.c +++ b/source/blender/blenkernel/intern/mesh_merge.c @@ -109,7 +109,7 @@ static int cddm_poly_compare(MLoop *mloop_array, i_loop_source++; if (i_loop_source == mpoly_source->totloop) { - /* End of loops for source, must match end of loop for target. */ + /* End of loops for source, must match end of loop for target. */ if (i_loop_target_offset == mpoly_target->totloop - 1) { compare_completed = true; same_loops = true; @@ -597,7 +597,7 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh, mp_new->loopstart = STACK_SIZE(mloop) - c; STACK_PUSH(oldp, i); - } /* end of the loop that tests polys */ + } /* End of the loop that tests polys. */ if (poly_gset) { // printf("hash quality %.6f\n", BLI_gset_calc_quality(poly_gset)); @@ -606,11 +606,11 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh, MEM_freeN(poly_keys); } - /*create new cddm*/ + /* Create new cddm. */ result = BKE_mesh_new_nomain_from_template( mesh, STACK_SIZE(mvert), STACK_SIZE(medge), 0, STACK_SIZE(mloop), STACK_SIZE(mpoly)); - /*update edge indices and copy customdata*/ + /* Update edge indices and copy customdata. */ med = medge; for (i = 0; i < result->totedge; i++, med++) { BLI_assert(newv[med->v1] != -1); @@ -624,7 +624,7 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh, CustomData_copy_data(&mesh->edata, &result->edata, olde[i], i, 1); } - /*update loop indices and copy customdata*/ + /* Update loop indices and copy customdata. */ ml = mloop; for (i = 0; i < result->totloop; i++, ml++) { /* Edge remapping has already be done in main loop handling part above. */ @@ -634,19 +634,19 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh, CustomData_copy_data(&mesh->ldata, &result->ldata, oldl[i], i, 1); } - /*copy vertex customdata*/ + /* Copy vertex customdata. */ mv = mvert; for (i = 0; i < result->totvert; i++, mv++) { CustomData_copy_data(&mesh->vdata, &result->vdata, oldv[i], i, 1); } - /*copy poly customdata*/ + /* Copy poly customdata. */ mp = mpoly; for (i = 0; i < result->totpoly; i++, mp++) { CustomData_copy_data(&mesh->pdata, &result->pdata, oldp[i], i, 1); } - /*copy over data. CustomData_add_layer can do this, need to look it up.*/ + /* Copy over data. #CustomData_add_layer can do this, need to look it up. */ memcpy(result->mvert, mvert, sizeof(MVert) * STACK_SIZE(mvert)); memcpy(result->medge, medge, sizeof(MEdge) * STACK_SIZE(medge)); memcpy(result->mloop, mloop, sizeof(MLoop) * STACK_SIZE(mloop)); diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c index 3d30c218fba..9aeaa1ada52 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.c +++ b/source/blender/blenkernel/intern/mesh_mirror.c @@ -70,9 +70,9 @@ Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(MirrorModifierData *mm /* Define bisecting plane (aka mirror plane). */ float plane[4]; if (!do_bisect_flip_axis) { - /* That reversed condition is a tad weird, but for some reason that's how you keep - * the part of the mesh which is on the non-mirrored side when flip option is disabled, - * think that that is the expected behavior. */ + /* That reversed condition is a little weird, but for some reason that's how you keep + * the part of the mesh which is on the non-mirrored side when flip option is disabled. + * I think this is the expected behavior. */ negate_v3(plane_no); } plane_from_point_normal_v3(plane, plane_co, plane_no); diff --git a/source/blender/blenkernel/intern/mesh_normals.c b/source/blender/blenkernel/intern/mesh_normals.c new file mode 100644 index 00000000000..a268f814cd0 --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_normals.c @@ -0,0 +1,2144 @@ +/* + * 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup bke + * + * Mesh normal calculation functions. + * + * \see bmesh_mesh_normals.c for the equivalent #BMesh functionality. + */ + +#include <limits.h> + +#include "CLG_log.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_alloca.h" +#include "BLI_bitmap.h" + +#include "BLI_linklist.h" +#include "BLI_linklist_stack.h" +#include "BLI_math.h" +#include "BLI_memarena.h" +#include "BLI_stack.h" +#include "BLI_task.h" +#include "BLI_utildefines.h" + +#include "BKE_customdata.h" +#include "BKE_editmesh_cache.h" +#include "BKE_global.h" +#include "BKE_mesh.h" + +// #define DEBUG_TIME + +#ifdef DEBUG_TIME +# include "PIL_time.h" +# include "PIL_time_utildefines.h" +#endif + +static CLG_LogRef LOG = {"bke.mesh_normals"}; + +/* -------------------------------------------------------------------- */ +/** \name Mesh Normal Calculation + * \{ */ + +/** + * Call when there are no polygons. + */ +static void mesh_calc_normals_vert_fallback(MVert *mverts, int numVerts) +{ + for (int i = 0; i < numVerts; i++) { + MVert *mv = &mverts[i]; + float no[3]; + + normalize_v3_v3(no, mv->co); + normal_float_to_short_v3(mv->no, no); + } +} + +/* TODO(Sybren): we can probably rename this to BKE_mesh_calc_normals_mapping(), + * and remove the function of the same name below, as that one doesn't seem to be + * called anywhere. */ +void BKE_mesh_calc_normals_mapping_simple(struct Mesh *mesh) +{ + const bool only_face_normals = CustomData_is_referenced_layer(&mesh->vdata, CD_MVERT); + + BKE_mesh_calc_normals_mapping_ex(mesh->mvert, + mesh->totvert, + mesh->mloop, + mesh->mpoly, + mesh->totloop, + mesh->totpoly, + NULL, + mesh->mface, + mesh->totface, + NULL, + NULL, + only_face_normals); +} + +/* Calculate vertex and face normals, face normals are returned in *r_faceNors if non-NULL + * and vertex normals are stored in actual mverts. + */ +void BKE_mesh_calc_normals_mapping(MVert *mverts, + int numVerts, + const MLoop *mloop, + const MPoly *mpolys, + int numLoops, + int numPolys, + float (*r_polyNors)[3], + const MFace *mfaces, + int numFaces, + const int *origIndexFace, + float (*r_faceNors)[3]) +{ + BKE_mesh_calc_normals_mapping_ex(mverts, + numVerts, + mloop, + mpolys, + numLoops, + numPolys, + r_polyNors, + mfaces, + numFaces, + origIndexFace, + r_faceNors, + false); +} +/* extended version of 'BKE_mesh_calc_normals_poly' with option not to calc vertex normals */ +void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, + int numVerts, + const MLoop *mloop, + const MPoly *mpolys, + int numLoops, + int numPolys, + float (*r_polyNors)[3], + const MFace *mfaces, + int numFaces, + const int *origIndexFace, + float (*r_faceNors)[3], + const bool only_face_normals) +{ + float(*pnors)[3] = r_polyNors, (*fnors)[3] = r_faceNors; + + if (numPolys == 0) { + if (only_face_normals == false) { + mesh_calc_normals_vert_fallback(mverts, numVerts); + } + return; + } + + /* if we are not calculating verts and no verts were passes then we have nothing to do */ + if ((only_face_normals == true) && (r_polyNors == NULL) && (r_faceNors == NULL)) { + CLOG_WARN(&LOG, "called with nothing to do"); + return; + } + + if (!pnors) { + pnors = MEM_calloc_arrayN((size_t)numPolys, sizeof(float[3]), __func__); + } + /* NO NEED TO ALLOC YET */ + /* if (!fnors) fnors = MEM_calloc_arrayN(numFaces, sizeof(float[3]), "face nors mesh.c"); */ + + if (only_face_normals == false) { + /* vertex normals are optional, they require some extra calculations, + * so make them optional */ + BKE_mesh_calc_normals_poly( + mverts, NULL, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false); + } + else { + /* only calc poly normals */ + const MPoly *mp = mpolys; + for (int i = 0; i < numPolys; i++, mp++) { + BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]); + } + } + + if (origIndexFace && + /* fnors == r_faceNors */ /* NO NEED TO ALLOC YET */ + fnors != NULL && + numFaces) { + const MFace *mf = mfaces; + for (int i = 0; i < numFaces; i++, mf++, origIndexFace++) { + if (*origIndexFace < numPolys) { + copy_v3_v3(fnors[i], pnors[*origIndexFace]); + } + else { + /* eek, we're not corresponding to polys */ + CLOG_ERROR(&LOG, "tessellation face indices are incorrect. normals may look bad."); + } + } + } + + if (pnors != r_polyNors) { + MEM_freeN(pnors); + } + /* if (fnors != r_faceNors) MEM_freeN(fnors); */ /* NO NEED TO ALLOC YET */ + + fnors = pnors = NULL; +} + +typedef struct MeshCalcNormalsData { + const MPoly *mpolys; + const MLoop *mloop; + MVert *mverts; + float (*pnors)[3]; + float (*lnors_weighted)[3]; + float (*vnors)[3]; +} MeshCalcNormalsData; + +static void mesh_calc_normals_poly_cb(void *__restrict userdata, + const int pidx, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + MeshCalcNormalsData *data = userdata; + const MPoly *mp = &data->mpolys[pidx]; + + BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mverts, data->pnors[pidx]); +} + +static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata, + const int pidx, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + MeshCalcNormalsData *data = userdata; + const MPoly *mp = &data->mpolys[pidx]; + const MLoop *ml = &data->mloop[mp->loopstart]; + const MVert *mverts = data->mverts; + + float pnor_temp[3]; + float *pnor = data->pnors ? data->pnors[pidx] : pnor_temp; + float(*lnors_weighted)[3] = data->lnors_weighted; + + const int nverts = mp->totloop; + float(*edgevecbuf)[3] = BLI_array_alloca(edgevecbuf, (size_t)nverts); + + /* Polygon Normal and edge-vector */ + /* inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors */ + { + int i_prev = nverts - 1; + const float *v_prev = mverts[ml[i_prev].v].co; + const float *v_curr; + + zero_v3(pnor); + /* Newell's Method */ + for (int i = 0; i < nverts; i++) { + v_curr = mverts[ml[i].v].co; + add_newell_cross_v3_v3v3(pnor, v_prev, v_curr); + + /* Unrelated to normalize, calculate edge-vector */ + sub_v3_v3v3(edgevecbuf[i_prev], v_prev, v_curr); + normalize_v3(edgevecbuf[i_prev]); + i_prev = i; + + v_prev = v_curr; + } + if (UNLIKELY(normalize_v3(pnor) == 0.0f)) { + pnor[2] = 1.0f; /* other axes set to 0.0 */ + } + } + + /* accumulate angle weighted face normal */ + /* inline version of #accumulate_vertex_normals_poly_v3, + * split between this threaded callback and #mesh_calc_normals_poly_accum_cb. */ + { + const float *prev_edge = edgevecbuf[nverts - 1]; + + for (int i = 0; i < nverts; i++) { + const int lidx = mp->loopstart + i; + const float *cur_edge = edgevecbuf[i]; + + /* calculate angle between the two poly edges incident on + * this vertex */ + const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); + + /* Store for later accumulation */ + mul_v3_v3fl(lnors_weighted[lidx], pnor, fac); + + prev_edge = cur_edge; + } + } +} + +static void mesh_calc_normals_poly_finalize_cb(void *__restrict userdata, + const int vidx, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + MeshCalcNormalsData *data = userdata; + + MVert *mv = &data->mverts[vidx]; + float *no = data->vnors[vidx]; + + if (UNLIKELY(normalize_v3(no) == 0.0f)) { + /* following Mesh convention; we use vertex coordinate itself for normal in this case */ + normalize_v3_v3(no, mv->co); + } + + normal_float_to_short_v3(mv->no, no); +} + +void BKE_mesh_calc_normals_poly(MVert *mverts, + float (*r_vertnors)[3], + int numVerts, + const MLoop *mloop, + const MPoly *mpolys, + int numLoops, + int numPolys, + float (*r_polynors)[3], + const bool only_face_normals) +{ + float(*pnors)[3] = r_polynors; + + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.min_iter_per_thread = 1024; + + if (only_face_normals) { + BLI_assert((pnors != NULL) || (numPolys == 0)); + BLI_assert(r_vertnors == NULL); + + MeshCalcNormalsData data = { + .mpolys = mpolys, + .mloop = mloop, + .mverts = mverts, + .pnors = pnors, + }; + + BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_cb, &settings); + return; + } + + float(*vnors)[3] = r_vertnors; + float(*lnors_weighted)[3] = MEM_malloc_arrayN( + (size_t)numLoops, sizeof(*lnors_weighted), __func__); + bool free_vnors = false; + + /* first go through and calculate normals for all the polys */ + if (vnors == NULL) { + vnors = MEM_calloc_arrayN((size_t)numVerts, sizeof(*vnors), __func__); + free_vnors = true; + } + else { + memset(vnors, 0, sizeof(*vnors) * (size_t)numVerts); + } + + MeshCalcNormalsData data = { + .mpolys = mpolys, + .mloop = mloop, + .mverts = mverts, + .pnors = pnors, + .lnors_weighted = lnors_weighted, + .vnors = vnors, + }; + + /* Compute poly normals, and prepare weighted loop normals. */ + BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_prepare_cb, &settings); + + /* Actually accumulate weighted loop normals into vertex ones. */ + /* Unfortunately, not possible to thread that + * (not in a reasonable, totally lock- and barrier-free fashion), + * since several loops will point to the same vertex... */ + for (int lidx = 0; lidx < numLoops; lidx++) { + add_v3_v3(vnors[mloop[lidx].v], data.lnors_weighted[lidx]); + } + + /* Normalize and validate computed vertex normals. */ + BLI_task_parallel_range(0, numVerts, &data, mesh_calc_normals_poly_finalize_cb, &settings); + + if (free_vnors) { + MEM_freeN(vnors); + } + MEM_freeN(lnors_weighted); +} + +void BKE_mesh_ensure_normals(Mesh *mesh) +{ + if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) { + BKE_mesh_calc_normals(mesh); + } + BLI_assert((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) == 0); +} + +/** + * Called after calculating all modifiers. + */ +void BKE_mesh_ensure_normals_for_display(Mesh *mesh) +{ + switch ((eMeshWrapperType)mesh->runtime.wrapper_type) { + case ME_WRAPPER_TYPE_MDATA: + /* Run code below. */ + break; + case ME_WRAPPER_TYPE_BMESH: { + struct BMEditMesh *em = mesh->edit_mesh; + EditMeshData *emd = mesh->runtime.edit_data; + if (emd->vertexCos) { + BKE_editmesh_cache_ensure_vert_normals(em, emd); + BKE_editmesh_cache_ensure_poly_normals(em, emd); + } + return; + } + } + + float(*poly_nors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL); + const bool do_vert_normals = (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) != 0; + const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL || poly_nors == NULL); + + if (do_vert_normals || do_poly_normals) { + const bool do_add_poly_nors_cddata = (poly_nors == NULL); + if (do_add_poly_nors_cddata) { + poly_nors = MEM_malloc_arrayN((size_t)mesh->totpoly, sizeof(*poly_nors), __func__); + } + + /* calculate poly/vert normals */ + BKE_mesh_calc_normals_poly(mesh->mvert, + NULL, + mesh->totvert, + mesh->mloop, + mesh->mpoly, + mesh->totloop, + mesh->totpoly, + poly_nors, + !do_vert_normals); + + if (do_add_poly_nors_cddata) { + CustomData_add_layer(&mesh->pdata, CD_NORMAL, CD_ASSIGN, poly_nors, mesh->totpoly); + } + + mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; + mesh->runtime.cd_dirty_poly &= ~CD_MASK_NORMAL; + } +} + +/* Note that this does not update the CD_NORMAL layer, + * but does update the normals in the CD_MVERT layer. */ +void BKE_mesh_calc_normals(Mesh *mesh) +{ +#ifdef DEBUG_TIME + TIMEIT_START_AVERAGED(BKE_mesh_calc_normals); +#endif + BKE_mesh_calc_normals_poly(mesh->mvert, + NULL, + mesh->totvert, + mesh->mloop, + mesh->mpoly, + mesh->totloop, + mesh->totpoly, + NULL, + false); +#ifdef DEBUG_TIME + TIMEIT_END_AVERAGED(BKE_mesh_calc_normals); +#endif + mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; +} + +void BKE_mesh_calc_normals_looptri(MVert *mverts, + int numVerts, + const MLoop *mloop, + const MLoopTri *looptri, + int looptri_num, + float (*r_tri_nors)[3]) +{ + float(*tnorms)[3] = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tnorms), "tnorms"); + float(*fnors)[3] = (r_tri_nors) ? + r_tri_nors : + MEM_calloc_arrayN((size_t)looptri_num, sizeof(*fnors), "meshnormals"); + + if (!tnorms || !fnors) { + goto cleanup; + } + + for (int i = 0; i < looptri_num; i++) { + const MLoopTri *lt = &looptri[i]; + float *f_no = fnors[i]; + const uint vtri[3] = { + mloop[lt->tri[0]].v, + mloop[lt->tri[1]].v, + mloop[lt->tri[2]].v, + }; + + normal_tri_v3(f_no, mverts[vtri[0]].co, mverts[vtri[1]].co, mverts[vtri[2]].co); + + accumulate_vertex_normals_tri_v3(tnorms[vtri[0]], + tnorms[vtri[1]], + tnorms[vtri[2]], + f_no, + mverts[vtri[0]].co, + mverts[vtri[1]].co, + mverts[vtri[2]].co); + } + + /* following Mesh convention; we use vertex coordinate itself for normal in this case */ + for (int i = 0; i < numVerts; i++) { + MVert *mv = &mverts[i]; + float *no = tnorms[i]; + + if (UNLIKELY(normalize_v3(no) == 0.0f)) { + normalize_v3_v3(no, mv->co); + } + + normal_float_to_short_v3(mv->no, no); + } + +cleanup: + MEM_freeN(tnorms); + + if (fnors != r_tri_nors) { + MEM_freeN(fnors); + } +} + +void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, + const int numLoops, + const char data_type) +{ + if (!(lnors_spacearr->lspacearr && lnors_spacearr->loops_pool)) { + MemArena *mem; + + if (!lnors_spacearr->mem) { + lnors_spacearr->mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + } + mem = lnors_spacearr->mem; + lnors_spacearr->lspacearr = BLI_memarena_calloc(mem, + sizeof(MLoopNorSpace *) * (size_t)numLoops); + lnors_spacearr->loops_pool = BLI_memarena_alloc(mem, sizeof(LinkNode) * (size_t)numLoops); + + lnors_spacearr->num_spaces = 0; + } + BLI_assert(ELEM(data_type, MLNOR_SPACEARR_BMLOOP_PTR, MLNOR_SPACEARR_LOOP_INDEX)); + lnors_spacearr->data_type = data_type; +} + +void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr) +{ + lnors_spacearr->num_spaces = 0; + lnors_spacearr->lspacearr = NULL; + lnors_spacearr->loops_pool = NULL; + if (lnors_spacearr->mem != NULL) { + BLI_memarena_clear(lnors_spacearr->mem); + } +} + +void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr) +{ + lnors_spacearr->num_spaces = 0; + lnors_spacearr->lspacearr = NULL; + lnors_spacearr->loops_pool = NULL; + BLI_memarena_free(lnors_spacearr->mem); + lnors_spacearr->mem = NULL; +} + +MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr) +{ + lnors_spacearr->num_spaces++; + return BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace)); +} + +/* This threshold is a bit touchy (usual float precision issue), this value seems OK. */ +#define LNOR_SPACE_TRIGO_THRESHOLD (1.0f - 1e-4f) + +/* Should only be called once. + * Beware, this modifies ref_vec and other_vec in place! + * In case no valid space can be generated, ref_alpha and ref_beta are set to zero + * (which means 'use auto lnors'). + */ +void BKE_lnor_space_define(MLoopNorSpace *lnor_space, + const float lnor[3], + float vec_ref[3], + float vec_other[3], + BLI_Stack *edge_vectors) +{ + const float pi2 = (float)M_PI * 2.0f; + float tvec[3], dtp; + const float dtp_ref = dot_v3v3(vec_ref, lnor); + const float dtp_other = dot_v3v3(vec_other, lnor); + + if (UNLIKELY(fabsf(dtp_ref) >= LNOR_SPACE_TRIGO_THRESHOLD || + fabsf(dtp_other) >= LNOR_SPACE_TRIGO_THRESHOLD)) { + /* If vec_ref or vec_other are too much aligned with lnor, we can't build lnor space, + * tag it as invalid and abort. */ + lnor_space->ref_alpha = lnor_space->ref_beta = 0.0f; + + if (edge_vectors) { + BLI_stack_clear(edge_vectors); + } + return; + } + + copy_v3_v3(lnor_space->vec_lnor, lnor); + + /* Compute ref alpha, average angle of all available edge vectors to lnor. */ + if (edge_vectors) { + float alpha = 0.0f; + int nbr = 0; + while (!BLI_stack_is_empty(edge_vectors)) { + const float *vec = BLI_stack_peek(edge_vectors); + alpha += saacosf(dot_v3v3(vec, lnor)); + BLI_stack_discard(edge_vectors); + nbr++; + } + /* Note: In theory, this could be 'nbr > 2', + * but there is one case where we only have two edges for two loops: + * a smooth vertex with only two edges and two faces (our Monkey's nose has that, e.g.). + */ + BLI_assert(nbr >= 2); /* This piece of code shall only be called for more than one loop... */ + lnor_space->ref_alpha = alpha / (float)nbr; + } + else { + lnor_space->ref_alpha = (saacosf(dot_v3v3(vec_ref, lnor)) + + saacosf(dot_v3v3(vec_other, lnor))) / + 2.0f; + } + + /* Project vec_ref on lnor's ortho plane. */ + mul_v3_v3fl(tvec, lnor, dtp_ref); + sub_v3_v3(vec_ref, tvec); + normalize_v3_v3(lnor_space->vec_ref, vec_ref); + + cross_v3_v3v3(tvec, lnor, lnor_space->vec_ref); + normalize_v3_v3(lnor_space->vec_ortho, tvec); + + /* Project vec_other on lnor's ortho plane. */ + mul_v3_v3fl(tvec, lnor, dtp_other); + sub_v3_v3(vec_other, tvec); + normalize_v3(vec_other); + + /* Beta is angle between ref_vec and other_vec, around lnor. */ + dtp = dot_v3v3(lnor_space->vec_ref, vec_other); + if (LIKELY(dtp < LNOR_SPACE_TRIGO_THRESHOLD)) { + const float beta = saacos(dtp); + lnor_space->ref_beta = (dot_v3v3(lnor_space->vec_ortho, vec_other) < 0.0f) ? pi2 - beta : beta; + } + else { + lnor_space->ref_beta = pi2; + } +} + +/** + * Add a new given loop to given lnor_space. + * Depending on \a lnor_space->data_type, we expect \a bm_loop to be a pointer to BMLoop struct + * (in case of BMLOOP_PTR), or NULL (in case of LOOP_INDEX), loop index is then stored in pointer. + * If \a is_single is set, the BMLoop or loop index is directly stored in \a lnor_space->loops + * pointer (since there is only one loop in this fan), + * else it is added to the linked list of loops in the fan. + */ +void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr, + MLoopNorSpace *lnor_space, + const int ml_index, + void *bm_loop, + const bool is_single) +{ + BLI_assert((lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX && bm_loop == NULL) || + (lnors_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR && bm_loop != NULL)); + + lnors_spacearr->lspacearr[ml_index] = lnor_space; + if (bm_loop == NULL) { + bm_loop = POINTER_FROM_INT(ml_index); + } + if (is_single) { + BLI_assert(lnor_space->loops == NULL); + lnor_space->flags |= MLNOR_SPACE_IS_SINGLE; + lnor_space->loops = bm_loop; + } + else { + BLI_assert((lnor_space->flags & MLNOR_SPACE_IS_SINGLE) == 0); + BLI_linklist_prepend_nlink(&lnor_space->loops, bm_loop, &lnors_spacearr->loops_pool[ml_index]); + } +} + +MINLINE float unit_short_to_float(const short val) +{ + return (float)val / (float)SHRT_MAX; +} + +MINLINE short unit_float_to_short(const float val) +{ + /* Rounding... */ + return (short)floorf(val * (float)SHRT_MAX + 0.5f); +} + +void BKE_lnor_space_custom_data_to_normal(MLoopNorSpace *lnor_space, + const short clnor_data[2], + float r_custom_lnor[3]) +{ + /* NOP custom normal data or invalid lnor space, return. */ + if (clnor_data[0] == 0 || lnor_space->ref_alpha == 0.0f || lnor_space->ref_beta == 0.0f) { + copy_v3_v3(r_custom_lnor, lnor_space->vec_lnor); + return; + } + + { + /* TODO: Check whether using #sincosf() gives any noticeable benefit + * (could not even get it working under linux though)! */ + const float pi2 = (float)(M_PI * 2.0); + const float alphafac = unit_short_to_float(clnor_data[0]); + const float alpha = (alphafac > 0.0f ? lnor_space->ref_alpha : pi2 - lnor_space->ref_alpha) * + alphafac; + const float betafac = unit_short_to_float(clnor_data[1]); + + mul_v3_v3fl(r_custom_lnor, lnor_space->vec_lnor, cosf(alpha)); + + if (betafac == 0.0f) { + madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinf(alpha)); + } + else { + const float sinalpha = sinf(alpha); + const float beta = (betafac > 0.0f ? lnor_space->ref_beta : pi2 - lnor_space->ref_beta) * + betafac; + madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinalpha * cosf(beta)); + madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ortho, sinalpha * sinf(beta)); + } + } +} + +void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, + const float custom_lnor[3], + short r_clnor_data[2]) +{ + /* We use null vector as NOP custom normal (can be simpler than giving auto-computed `lnor`). */ + if (is_zero_v3(custom_lnor) || compare_v3v3(lnor_space->vec_lnor, custom_lnor, 1e-4f)) { + r_clnor_data[0] = r_clnor_data[1] = 0; + return; + } + + { + const float pi2 = (float)(M_PI * 2.0); + const float cos_alpha = dot_v3v3(lnor_space->vec_lnor, custom_lnor); + float vec[3], cos_beta; + float alpha; + + alpha = saacosf(cos_alpha); + if (alpha > lnor_space->ref_alpha) { + /* Note we could stick to [0, pi] range here, + * but makes decoding more complex, not worth it. */ + r_clnor_data[0] = unit_float_to_short(-(pi2 - alpha) / (pi2 - lnor_space->ref_alpha)); + } + else { + r_clnor_data[0] = unit_float_to_short(alpha / lnor_space->ref_alpha); + } + + /* Project custom lnor on (vec_ref, vec_ortho) plane. */ + mul_v3_v3fl(vec, lnor_space->vec_lnor, -cos_alpha); + add_v3_v3(vec, custom_lnor); + normalize_v3(vec); + + cos_beta = dot_v3v3(lnor_space->vec_ref, vec); + + if (cos_beta < LNOR_SPACE_TRIGO_THRESHOLD) { + float beta = saacosf(cos_beta); + if (dot_v3v3(lnor_space->vec_ortho, vec) < 0.0f) { + beta = pi2 - beta; + } + + if (beta > lnor_space->ref_beta) { + r_clnor_data[1] = unit_float_to_short(-(pi2 - beta) / (pi2 - lnor_space->ref_beta)); + } + else { + r_clnor_data[1] = unit_float_to_short(beta / lnor_space->ref_beta); + } + } + else { + r_clnor_data[1] = 0; + } + } +} + +#define LOOP_SPLIT_TASK_BLOCK_SIZE 1024 + +typedef struct LoopSplitTaskData { + /* Specific to each instance (each task). */ + + /** We have to create those outside of tasks, since #MemArena is not thread-safe. */ + MLoopNorSpace *lnor_space; + float (*lnor)[3]; + const MLoop *ml_curr; + const MLoop *ml_prev; + int ml_curr_index; + int ml_prev_index; + /** Also used a flag to switch between single or fan process! */ + const int *e2l_prev; + int mp_index; + + /** This one is special, it's owned and managed by worker tasks, + * avoid to have to create it for each fan! */ + BLI_Stack *edge_vectors; + + char pad_c; +} LoopSplitTaskData; + +typedef struct LoopSplitTaskDataCommon { + /* Read/write. + * Note we do not need to protect it, though, since two different tasks will *always* affect + * different elements in the arrays. */ + MLoopNorSpaceArray *lnors_spacearr; + float (*loopnors)[3]; + short (*clnors_data)[2]; + + /* Read-only. */ + const MVert *mverts; + const MEdge *medges; + const MLoop *mloops; + const MPoly *mpolys; + int (*edge_to_loops)[2]; + int *loop_to_poly; + const float (*polynors)[3]; + + int numEdges; + int numLoops; + int numPolys; +} LoopSplitTaskDataCommon; + +#define INDEX_UNSET INT_MIN +#define INDEX_INVALID -1 +/* See comment about edge_to_loops below. */ +#define IS_EDGE_SHARP(_e2l) (ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID)) + +static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data, + const bool check_angle, + const float split_angle, + const bool do_sharp_edges_tag) +{ + const MVert *mverts = data->mverts; + const MEdge *medges = data->medges; + const MLoop *mloops = data->mloops; + + const MPoly *mpolys = data->mpolys; + + const int numEdges = data->numEdges; + const int numPolys = data->numPolys; + + float(*loopnors)[3] = data->loopnors; /* Note: loopnors may be NULL here. */ + const float(*polynors)[3] = data->polynors; + + int(*edge_to_loops)[2] = data->edge_to_loops; + int *loop_to_poly = data->loop_to_poly; + + BLI_bitmap *sharp_edges = do_sharp_edges_tag ? BLI_BITMAP_NEW(numEdges, __func__) : NULL; + + const MPoly *mp; + int mp_index; + + const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f; + + for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) { + const MLoop *ml_curr; + int *e2l; + int ml_curr_index = mp->loopstart; + const int ml_last_index = (ml_curr_index + mp->totloop) - 1; + + ml_curr = &mloops[ml_curr_index]; + + for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++) { + e2l = edge_to_loops[ml_curr->e]; + + loop_to_poly[ml_curr_index] = mp_index; + + /* Pre-populate all loop normals as if their verts were all-smooth, + * this way we don't have to compute those later! + */ + if (loopnors) { + normal_short_to_float_v3(loopnors[ml_curr_index], mverts[ml_curr->v].no); + } + + /* Check whether current edge might be smooth or sharp */ + if ((e2l[0] | e2l[1]) == 0) { + /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */ + e2l[0] = ml_curr_index; + /* We have to check this here too, else we might miss some flat faces!!! */ + e2l[1] = (mp->flag & ME_SMOOTH) ? INDEX_UNSET : INDEX_INVALID; + } + else if (e2l[1] == INDEX_UNSET) { + const bool is_angle_sharp = (check_angle && + dot_v3v3(polynors[loop_to_poly[e2l[0]]], polynors[mp_index]) < + split_angle_cos); + + /* Second loop using this edge, time to test its sharpness. + * An edge is sharp if it is tagged as such, or its face is not smooth, + * or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the + * same vertex, or angle between both its polys' normals is above split_angle value. + */ + if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) || + ml_curr->v == mloops[e2l[0]].v || is_angle_sharp) { + /* Note: we are sure that loop != 0 here ;) */ + e2l[1] = INDEX_INVALID; + + /* We want to avoid tagging edges as sharp when it is already defined as such by + * other causes than angle threshold... */ + if (do_sharp_edges_tag && is_angle_sharp) { + BLI_BITMAP_SET(sharp_edges, ml_curr->e, true); + } + } + else { + e2l[1] = ml_curr_index; + } + } + else if (!IS_EDGE_SHARP(e2l)) { + /* More than two loops using this edge, tag as sharp if not yet done. */ + e2l[1] = INDEX_INVALID; + + /* We want to avoid tagging edges as sharp when it is already defined as such by + * other causes than angle threshold... */ + if (do_sharp_edges_tag) { + BLI_BITMAP_SET(sharp_edges, ml_curr->e, false); + } + } + /* Else, edge is already 'disqualified' (i.e. sharp)! */ + } + } + + /* If requested, do actual tagging of edges as sharp in another loop. */ + if (do_sharp_edges_tag) { + MEdge *me; + int me_index; + for (me = (MEdge *)medges, me_index = 0; me_index < numEdges; me++, me_index++) { + if (BLI_BITMAP_TEST(sharp_edges, me_index)) { + me->flag |= ME_SHARP; + } + } + + MEM_freeN(sharp_edges); + } +} + +/** + * Define sharp edges as needed to mimic 'autosmooth' from angle threshold. + * + * Used when defining an empty custom loop normals data layer, + * to keep same shading as with auto-smooth! + */ +void BKE_edges_sharp_from_angle_set(const struct MVert *mverts, + const int UNUSED(numVerts), + struct MEdge *medges, + const int numEdges, + struct MLoop *mloops, + const int numLoops, + struct MPoly *mpolys, + const float (*polynors)[3], + const int numPolys, + const float split_angle) +{ + if (split_angle >= (float)M_PI) { + /* Nothing to do! */ + return; + } + + /* Mapping edge -> loops. See BKE_mesh_normals_loop_split() for details. */ + int(*edge_to_loops)[2] = MEM_calloc_arrayN((size_t)numEdges, sizeof(*edge_to_loops), __func__); + + /* Simple mapping from a loop to its polygon index. */ + int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__); + + LoopSplitTaskDataCommon common_data = { + .mverts = mverts, + .medges = medges, + .mloops = mloops, + .mpolys = mpolys, + .edge_to_loops = edge_to_loops, + .loop_to_poly = loop_to_poly, + .polynors = polynors, + .numEdges = numEdges, + .numPolys = numPolys, + }; + + mesh_edges_sharp_tag(&common_data, true, split_angle, true); + + MEM_freeN(edge_to_loops); + MEM_freeN(loop_to_poly); +} + +void BKE_mesh_loop_manifold_fan_around_vert_next(const MLoop *mloops, + const MPoly *mpolys, + const int *loop_to_poly, + const int *e2lfan_curr, + const uint mv_pivot_index, + const MLoop **r_mlfan_curr, + int *r_mlfan_curr_index, + int *r_mlfan_vert_index, + int *r_mpfan_curr_index) +{ + const MLoop *mlfan_next; + const MPoly *mpfan_next; + + /* Warning! This is rather complex! + * We have to find our next edge around the vertex (fan mode). + * First we find the next loop, which is either previous or next to mlfan_curr_index, depending + * whether both loops using current edge are in the same direction or not, and whether + * mlfan_curr_index actually uses the vertex we are fanning around! + * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one + * (i.e. not the future mlfan_curr)... + */ + *r_mlfan_curr_index = (e2lfan_curr[0] == *r_mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0]; + *r_mpfan_curr_index = loop_to_poly[*r_mlfan_curr_index]; + + BLI_assert(*r_mlfan_curr_index >= 0); + BLI_assert(*r_mpfan_curr_index >= 0); + + mlfan_next = &mloops[*r_mlfan_curr_index]; + mpfan_next = &mpolys[*r_mpfan_curr_index]; + if (((*r_mlfan_curr)->v == mlfan_next->v && (*r_mlfan_curr)->v == mv_pivot_index) || + ((*r_mlfan_curr)->v != mlfan_next->v && (*r_mlfan_curr)->v != mv_pivot_index)) { + /* We need the previous loop, but current one is our vertex's loop. */ + *r_mlfan_vert_index = *r_mlfan_curr_index; + if (--(*r_mlfan_curr_index) < mpfan_next->loopstart) { + *r_mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1; + } + } + else { + /* We need the next loop, which is also our vertex's loop. */ + if (++(*r_mlfan_curr_index) >= mpfan_next->loopstart + mpfan_next->totloop) { + *r_mlfan_curr_index = mpfan_next->loopstart; + } + *r_mlfan_vert_index = *r_mlfan_curr_index; + } + *r_mlfan_curr = &mloops[*r_mlfan_curr_index]; + /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */ +} + +static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data) +{ + MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr; + const short(*clnors_data)[2] = common_data->clnors_data; + + const MVert *mverts = common_data->mverts; + const MEdge *medges = common_data->medges; + const float(*polynors)[3] = common_data->polynors; + + MLoopNorSpace *lnor_space = data->lnor_space; + float(*lnor)[3] = data->lnor; + const MLoop *ml_curr = data->ml_curr; + const MLoop *ml_prev = data->ml_prev; + const int ml_curr_index = data->ml_curr_index; +#if 0 /* Not needed for 'single' loop. */ + const int ml_prev_index = data->ml_prev_index; + const int *e2l_prev = data->e2l_prev; +#endif + const int mp_index = data->mp_index; + + /* Simple case (both edges around that vertex are sharp in current polygon), + * this loop just takes its poly normal. + */ + copy_v3_v3(*lnor, polynors[mp_index]); + +#if 0 + printf("BASIC: handling loop %d / edge %d / vert %d / poly %d\n", + ml_curr_index, + ml_curr->e, + ml_curr->v, + mp_index); +#endif + + /* If needed, generate this (simple!) lnor space. */ + if (lnors_spacearr) { + float vec_curr[3], vec_prev[3]; + + const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */ + const MVert *mv_pivot = &mverts[mv_pivot_index]; + const MEdge *me_curr = &medges[ml_curr->e]; + const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] : + &mverts[me_curr->v1]; + const MEdge *me_prev = &medges[ml_prev->e]; + const MVert *mv_3 = (me_prev->v1 == mv_pivot_index) ? &mverts[me_prev->v2] : + &mverts[me_prev->v1]; + + sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co); + normalize_v3(vec_curr); + sub_v3_v3v3(vec_prev, mv_3->co, mv_pivot->co); + normalize_v3(vec_prev); + + BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, NULL); + /* We know there is only one loop in this space, + * no need to create a linklist in this case... */ + BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, NULL, true); + + if (clnors_data) { + BKE_lnor_space_custom_data_to_normal(lnor_space, clnors_data[ml_curr_index], *lnor); + } + } +} + +static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data) +{ + MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr; + float(*loopnors)[3] = common_data->loopnors; + short(*clnors_data)[2] = common_data->clnors_data; + + const MVert *mverts = common_data->mverts; + const MEdge *medges = common_data->medges; + const MLoop *mloops = common_data->mloops; + const MPoly *mpolys = common_data->mpolys; + const int(*edge_to_loops)[2] = common_data->edge_to_loops; + const int *loop_to_poly = common_data->loop_to_poly; + const float(*polynors)[3] = common_data->polynors; + + MLoopNorSpace *lnor_space = data->lnor_space; +#if 0 /* Not needed for 'fan' loops. */ + float(*lnor)[3] = data->lnor; +#endif + const MLoop *ml_curr = data->ml_curr; + const MLoop *ml_prev = data->ml_prev; + const int ml_curr_index = data->ml_curr_index; + const int ml_prev_index = data->ml_prev_index; + const int mp_index = data->mp_index; + const int *e2l_prev = data->e2l_prev; + + BLI_Stack *edge_vectors = data->edge_vectors; + + /* Gah... We have to fan around current vertex, until we find the other non-smooth edge, + * and accumulate face normals into the vertex! + * Note in case this vertex has only one sharp edges, this is a waste because the normal is the + * same as the vertex normal, but I do not see any easy way to detect that (would need to count + * number of sharp edges per vertex, I doubt the additional memory usage would be worth it, + * especially as it should not be a common case in real-life meshes anyway). + */ + const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */ + const MVert *mv_pivot = &mverts[mv_pivot_index]; + + /* ml_curr would be mlfan_prev if we needed that one. */ + const MEdge *me_org = &medges[ml_curr->e]; + + const int *e2lfan_curr; + float vec_curr[3], vec_prev[3], vec_org[3]; + const MLoop *mlfan_curr; + float lnor[3] = {0.0f, 0.0f, 0.0f}; + /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */ + int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index; + + /* We validate clnors data on the fly - cheapest way to do! */ + int clnors_avg[2] = {0, 0}; + short(*clnor_ref)[2] = NULL; + int clnors_nbr = 0; + bool clnors_invalid = false; + + /* Temp loop normal stack. */ + BLI_SMALLSTACK_DECLARE(normal, float *); + /* Temp clnors stack. */ + BLI_SMALLSTACK_DECLARE(clnors, short *); + + e2lfan_curr = e2l_prev; + mlfan_curr = ml_prev; + mlfan_curr_index = ml_prev_index; + mlfan_vert_index = ml_curr_index; + mpfan_curr_index = mp_index; + + BLI_assert(mlfan_curr_index >= 0); + BLI_assert(mlfan_vert_index >= 0); + BLI_assert(mpfan_curr_index >= 0); + + /* Only need to compute previous edge's vector once, then we can just reuse old current one! */ + { + const MVert *mv_2 = (me_org->v1 == mv_pivot_index) ? &mverts[me_org->v2] : &mverts[me_org->v1]; + + sub_v3_v3v3(vec_org, mv_2->co, mv_pivot->co); + normalize_v3(vec_org); + copy_v3_v3(vec_prev, vec_org); + + if (lnors_spacearr) { + BLI_stack_push(edge_vectors, vec_org); + } + } + + // printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e); + + while (true) { + const MEdge *me_curr = &medges[mlfan_curr->e]; + /* Compute edge vectors. + * NOTE: We could pre-compute those into an array, in the first iteration, instead of computing + * them twice (or more) here. However, time gained is not worth memory and time lost, + * given the fact that this code should not be called that much in real-life meshes... + */ + { + const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] : + &mverts[me_curr->v1]; + + sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co); + normalize_v3(vec_curr); + } + + // printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index); + + { + /* Code similar to accumulate_vertex_normals_poly_v3. */ + /* Calculate angle between the two poly edges incident on this vertex. */ + const float fac = saacos(dot_v3v3(vec_curr, vec_prev)); + /* Accumulate */ + madd_v3_v3fl(lnor, polynors[mpfan_curr_index], fac); + + if (clnors_data) { + /* Accumulate all clnors, if they are not all equal we have to fix that! */ + short(*clnor)[2] = &clnors_data[mlfan_vert_index]; + if (clnors_nbr) { + clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] || (*clnor_ref)[1] != (*clnor)[1]); + } + else { + clnor_ref = clnor; + } + clnors_avg[0] += (*clnor)[0]; + clnors_avg[1] += (*clnor)[1]; + clnors_nbr++; + /* We store here a pointer to all custom lnors processed. */ + BLI_SMALLSTACK_PUSH(clnors, (short *)*clnor); + } + } + + /* We store here a pointer to all loop-normals processed. */ + BLI_SMALLSTACK_PUSH(normal, (float *)(loopnors[mlfan_vert_index])); + + if (lnors_spacearr) { + /* Assign current lnor space to current 'vertex' loop. */ + BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, NULL, false); + if (me_curr != me_org) { + /* We store here all edges-normalized vectors processed. */ + BLI_stack_push(edge_vectors, vec_curr); + } + } + + if (IS_EDGE_SHARP(e2lfan_curr) || (me_curr == me_org)) { + /* Current edge is sharp and we have finished with this fan of faces around this vert, + * or this vert is smooth, and we have completed a full turn around it. + */ + // printf("FAN: Finished!\n"); + break; + } + + copy_v3_v3(vec_prev, vec_curr); + + /* Find next loop of the smooth fan. */ + BKE_mesh_loop_manifold_fan_around_vert_next(mloops, + mpolys, + loop_to_poly, + e2lfan_curr, + mv_pivot_index, + &mlfan_curr, + &mlfan_curr_index, + &mlfan_vert_index, + &mpfan_curr_index); + + e2lfan_curr = edge_to_loops[mlfan_curr->e]; + } + + { + float lnor_len = normalize_v3(lnor); + + /* If we are generating lnor spacearr, we can now define the one for this fan, + * and optionally compute final lnor from custom data too! + */ + if (lnors_spacearr) { + if (UNLIKELY(lnor_len == 0.0f)) { + /* Use vertex normal as fallback! */ + copy_v3_v3(lnor, loopnors[mlfan_vert_index]); + lnor_len = 1.0f; + } + + BKE_lnor_space_define(lnor_space, lnor, vec_org, vec_curr, edge_vectors); + + if (clnors_data) { + if (clnors_invalid) { + short *clnor; + + clnors_avg[0] /= clnors_nbr; + clnors_avg[1] /= clnors_nbr; + /* Fix/update all clnors of this fan with computed average value. */ + if (G.debug & G_DEBUG) { + printf("Invalid clnors in this fan!\n"); + } + while ((clnor = BLI_SMALLSTACK_POP(clnors))) { + // print_v2("org clnor", clnor); + clnor[0] = (short)clnors_avg[0]; + clnor[1] = (short)clnors_avg[1]; + } + // print_v2("new clnors", clnors_avg); + } + /* Extra bonus: since small-stack is local to this function, + * no more need to empty it at all cost! */ + + BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor); + } + } + + /* In case we get a zero normal here, just use vertex normal already set! */ + if (LIKELY(lnor_len != 0.0f)) { + /* Copy back the final computed normal into all related loop-normals. */ + float *nor; + + while ((nor = BLI_SMALLSTACK_POP(normal))) { + copy_v3_v3(nor, lnor); + } + } + /* Extra bonus: since small-stack is local to this function, + * no more need to empty it at all cost! */ + } +} + +static void loop_split_worker_do(LoopSplitTaskDataCommon *common_data, + LoopSplitTaskData *data, + BLI_Stack *edge_vectors) +{ + BLI_assert(data->ml_curr); + if (data->e2l_prev) { + BLI_assert((edge_vectors == NULL) || BLI_stack_is_empty(edge_vectors)); + data->edge_vectors = edge_vectors; + split_loop_nor_fan_do(common_data, data); + } + else { + /* No need for edge_vectors for 'single' case! */ + split_loop_nor_single_do(common_data, data); + } +} + +static void loop_split_worker(TaskPool *__restrict pool, void *taskdata) +{ + LoopSplitTaskDataCommon *common_data = BLI_task_pool_user_data(pool); + LoopSplitTaskData *data = taskdata; + + /* Temp edge vectors stack, only used when computing lnor spacearr. */ + BLI_Stack *edge_vectors = common_data->lnors_spacearr ? + BLI_stack_new(sizeof(float[3]), __func__) : + NULL; + +#ifdef DEBUG_TIME + TIMEIT_START_AVERAGED(loop_split_worker); +#endif + + for (int i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) { + /* A NULL ml_curr is used to tag ended data! */ + if (data->ml_curr == NULL) { + break; + } + + loop_split_worker_do(common_data, data, edge_vectors); + } + + if (edge_vectors) { + BLI_stack_free(edge_vectors); + } + +#ifdef DEBUG_TIME + TIMEIT_END_AVERAGED(loop_split_worker); +#endif +} + +/** + * Check whether given loop is part of an unknown-so-far cyclic smooth fan, or not. + * Needed because cyclic smooth fans have no obvious 'entry point', + * and yet we need to walk them once, and only once. + */ +static bool loop_split_generator_check_cyclic_smooth_fan(const MLoop *mloops, + const MPoly *mpolys, + const int (*edge_to_loops)[2], + const int *loop_to_poly, + const int *e2l_prev, + BLI_bitmap *skip_loops, + const MLoop *ml_curr, + const MLoop *ml_prev, + const int ml_curr_index, + const int ml_prev_index, + const int mp_curr_index) +{ + const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */ + const int *e2lfan_curr; + const MLoop *mlfan_curr; + /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */ + int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index; + + e2lfan_curr = e2l_prev; + if (IS_EDGE_SHARP(e2lfan_curr)) { + /* Sharp loop, so not a cyclic smooth fan... */ + return false; + } + + mlfan_curr = ml_prev; + mlfan_curr_index = ml_prev_index; + mlfan_vert_index = ml_curr_index; + mpfan_curr_index = mp_curr_index; + + BLI_assert(mlfan_curr_index >= 0); + BLI_assert(mlfan_vert_index >= 0); + BLI_assert(mpfan_curr_index >= 0); + + BLI_assert(!BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)); + BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index); + + while (true) { + /* Find next loop of the smooth fan. */ + BKE_mesh_loop_manifold_fan_around_vert_next(mloops, + mpolys, + loop_to_poly, + e2lfan_curr, + mv_pivot_index, + &mlfan_curr, + &mlfan_curr_index, + &mlfan_vert_index, + &mpfan_curr_index); + + e2lfan_curr = edge_to_loops[mlfan_curr->e]; + + if (IS_EDGE_SHARP(e2lfan_curr)) { + /* Sharp loop/edge, so not a cyclic smooth fan... */ + return false; + } + /* Smooth loop/edge... */ + if (BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)) { + if (mlfan_vert_index == ml_curr_index) { + /* We walked around a whole cyclic smooth fan without finding any already-processed loop, + * means we can use initial ml_curr/ml_prev edge as start for this smooth fan. */ + return true; + } + /* ... already checked in some previous looping, we can abort. */ + return false; + } + + /* ... we can skip it in future, and keep checking the smooth fan. */ + BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index); + } +} + +static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common_data) +{ + MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr; + float(*loopnors)[3] = common_data->loopnors; + + const MLoop *mloops = common_data->mloops; + const MPoly *mpolys = common_data->mpolys; + const int *loop_to_poly = common_data->loop_to_poly; + const int(*edge_to_loops)[2] = common_data->edge_to_loops; + const int numLoops = common_data->numLoops; + const int numPolys = common_data->numPolys; + + const MPoly *mp; + int mp_index; + + const MLoop *ml_curr; + const MLoop *ml_prev; + int ml_curr_index; + int ml_prev_index; + + BLI_bitmap *skip_loops = BLI_BITMAP_NEW(numLoops, __func__); + + LoopSplitTaskData *data_buff = NULL; + int data_idx = 0; + + /* Temp edge vectors stack, only used when computing lnor spacearr + * (and we are not multi-threading). */ + BLI_Stack *edge_vectors = NULL; + +#ifdef DEBUG_TIME + TIMEIT_START_AVERAGED(loop_split_generator); +#endif + + if (!pool) { + if (lnors_spacearr) { + edge_vectors = BLI_stack_new(sizeof(float[3]), __func__); + } + } + + /* We now know edges that can be smoothed (with their vector, and their two loops), + * and edges that will be hard! Now, time to generate the normals. + */ + for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) { + float(*lnors)[3]; + const int ml_last_index = (mp->loopstart + mp->totloop) - 1; + ml_curr_index = mp->loopstart; + ml_prev_index = ml_last_index; + + ml_curr = &mloops[ml_curr_index]; + ml_prev = &mloops[ml_prev_index]; + lnors = &loopnors[ml_curr_index]; + + for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++, lnors++) { + const int *e2l_curr = edge_to_loops[ml_curr->e]; + const int *e2l_prev = edge_to_loops[ml_prev->e]; + +#if 0 + printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)...", + ml_curr_index, + ml_curr->e, + ml_curr->v, + IS_EDGE_SHARP(e2l_curr), + BLI_BITMAP_TEST_BOOL(skip_loops, ml_curr_index)); +#endif + + /* A smooth edge, we have to check for cyclic smooth fan case. + * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge + * as 'entry point', otherwise we can skip it. */ + + /* Note: In theory, we could make #loop_split_generator_check_cyclic_smooth_fan() store + * mlfan_vert_index'es and edge indexes in two stacks, to avoid having to fan again around + * the vert during actual computation of `clnor` & `clnorspace`. + * However, this would complicate the code, add more memory usage, and despite its logical + * complexity, #loop_manifold_fan_around_vert_next() is quite cheap in term of CPU cycles, + * so really think it's not worth it. */ + if (!IS_EDGE_SHARP(e2l_curr) && (BLI_BITMAP_TEST(skip_loops, ml_curr_index) || + !loop_split_generator_check_cyclic_smooth_fan(mloops, + mpolys, + edge_to_loops, + loop_to_poly, + e2l_prev, + skip_loops, + ml_curr, + ml_prev, + ml_curr_index, + ml_prev_index, + mp_index))) { + // printf("SKIPPING!\n"); + } + else { + LoopSplitTaskData *data, data_local; + + // printf("PROCESSING!\n"); + + if (pool) { + if (data_idx == 0) { + data_buff = MEM_calloc_arrayN( + LOOP_SPLIT_TASK_BLOCK_SIZE, sizeof(*data_buff), __func__); + } + data = &data_buff[data_idx]; + } + else { + data = &data_local; + memset(data, 0, sizeof(*data)); + } + + if (IS_EDGE_SHARP(e2l_curr) && IS_EDGE_SHARP(e2l_prev)) { + data->lnor = lnors; + data->ml_curr = ml_curr; + data->ml_prev = ml_prev; + data->ml_curr_index = ml_curr_index; +#if 0 /* Not needed for 'single' loop. */ + data->ml_prev_index = ml_prev_index; + data->e2l_prev = NULL; /* Tag as 'single' task. */ +#endif + data->mp_index = mp_index; + if (lnors_spacearr) { + data->lnor_space = BKE_lnor_space_create(lnors_spacearr); + } + } + /* We *do not need* to check/tag loops as already computed! + * Due to the fact a loop only links to one of its two edges, + * a same fan *will never be walked more than once!* + * Since we consider edges having neighbor polys with inverted + * (flipped) normals as sharp, we are sure that no fan will be skipped, + * even only considering the case (sharp curr_edge, smooth prev_edge), + * and not the alternative (smooth curr_edge, sharp prev_edge). + * All this due/thanks to link between normals and loop ordering (i.e. winding). + */ + else { +#if 0 /* Not needed for 'fan' loops. */ + data->lnor = lnors; +#endif + data->ml_curr = ml_curr; + data->ml_prev = ml_prev; + data->ml_curr_index = ml_curr_index; + data->ml_prev_index = ml_prev_index; + data->e2l_prev = e2l_prev; /* Also tag as 'fan' task. */ + data->mp_index = mp_index; + if (lnors_spacearr) { + data->lnor_space = BKE_lnor_space_create(lnors_spacearr); + } + } + + if (pool) { + data_idx++; + if (data_idx == LOOP_SPLIT_TASK_BLOCK_SIZE) { + BLI_task_pool_push(pool, loop_split_worker, data_buff, true, NULL); + data_idx = 0; + } + } + else { + loop_split_worker_do(common_data, data, edge_vectors); + } + } + + ml_prev = ml_curr; + ml_prev_index = ml_curr_index; + } + } + + /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper, + * everything is fine. */ + if (pool && data_idx) { + BLI_task_pool_push(pool, loop_split_worker, data_buff, true, NULL); + } + + if (edge_vectors) { + BLI_stack_free(edge_vectors); + } + MEM_freeN(skip_loops); + +#ifdef DEBUG_TIME + TIMEIT_END_AVERAGED(loop_split_generator); +#endif +} + +/** + * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals'). + * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry + * (splitting edges). + */ +void BKE_mesh_normals_loop_split(const MVert *mverts, + const int UNUSED(numVerts), + MEdge *medges, + const int numEdges, + MLoop *mloops, + float (*r_loopnors)[3], + const int numLoops, + MPoly *mpolys, + const float (*polynors)[3], + const int numPolys, + const bool use_split_normals, + const float split_angle, + MLoopNorSpaceArray *r_lnors_spacearr, + short (*clnors_data)[2], + int *r_loop_to_poly) +{ + /* For now this is not supported. + * If we do not use split normals, we do not generate anything fancy! */ + BLI_assert(use_split_normals || !(r_lnors_spacearr)); + + if (!use_split_normals) { + /* In this case, we simply fill lnors with vnors (or fnors for flat faces), quite simple! + * Note this is done here to keep some logic and consistency in this quite complex code, + * since we may want to use lnors even when mesh's 'autosmooth' is disabled + * (see e.g. mesh mapping code). + * As usual, we could handle that on case-by-case basis, + * but simpler to keep it well confined here. + */ + int mp_index; + + for (mp_index = 0; mp_index < numPolys; mp_index++) { + MPoly *mp = &mpolys[mp_index]; + int ml_index = mp->loopstart; + const int ml_index_end = ml_index + mp->totloop; + const bool is_poly_flat = ((mp->flag & ME_SMOOTH) == 0); + + for (; ml_index < ml_index_end; ml_index++) { + if (r_loop_to_poly) { + r_loop_to_poly[ml_index] = mp_index; + } + if (is_poly_flat) { + copy_v3_v3(r_loopnors[ml_index], polynors[mp_index]); + } + else { + normal_short_to_float_v3(r_loopnors[ml_index], mverts[mloops[ml_index].v].no); + } + } + } + return; + } + + /** + * Mapping edge -> loops. + * If that edge is used by more than two loops (polys), + * it is always sharp (and tagged as such, see below). + * We also use the second loop index as a kind of flag: + * + * - smooth edge: > 0. + * - sharp edge: < 0 (INDEX_INVALID || INDEX_UNSET). + * - unset: INDEX_UNSET. + * + * Note that currently we only have two values for second loop of sharp edges. + * However, if needed, we can store the negated value of loop index instead of INDEX_INVALID + * to retrieve the real value later in code). + * Note also that loose edges always have both values set to 0! */ + int(*edge_to_loops)[2] = MEM_calloc_arrayN((size_t)numEdges, sizeof(*edge_to_loops), __func__); + + /* Simple mapping from a loop to its polygon index. */ + int *loop_to_poly = r_loop_to_poly ? + r_loop_to_poly : + MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__); + + /* When using custom loop normals, disable the angle feature! */ + const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == NULL); + + MLoopNorSpaceArray _lnors_spacearr = {NULL}; + +#ifdef DEBUG_TIME + TIMEIT_START_AVERAGED(BKE_mesh_normals_loop_split); +#endif + + if (!r_lnors_spacearr && clnors_data) { + /* We need to compute lnor spacearr if some custom lnor data are given to us! */ + r_lnors_spacearr = &_lnors_spacearr; + } + if (r_lnors_spacearr) { + BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops, MLNOR_SPACEARR_LOOP_INDEX); + } + + /* Init data common to all tasks. */ + LoopSplitTaskDataCommon common_data = { + .lnors_spacearr = r_lnors_spacearr, + .loopnors = r_loopnors, + .clnors_data = clnors_data, + .mverts = mverts, + .medges = medges, + .mloops = mloops, + .mpolys = mpolys, + .edge_to_loops = edge_to_loops, + .loop_to_poly = loop_to_poly, + .polynors = polynors, + .numEdges = numEdges, + .numLoops = numLoops, + .numPolys = numPolys, + }; + + /* This first loop check which edges are actually smooth, and compute edge vectors. */ + mesh_edges_sharp_tag(&common_data, check_angle, split_angle, false); + + if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) { + /* Not enough loops to be worth the whole threading overhead... */ + loop_split_generator(NULL, &common_data); + } + else { + TaskPool *task_pool = BLI_task_pool_create(&common_data, TASK_PRIORITY_HIGH); + + loop_split_generator(task_pool, &common_data); + + BLI_task_pool_work_and_wait(task_pool); + + BLI_task_pool_free(task_pool); + } + + MEM_freeN(edge_to_loops); + if (!r_loop_to_poly) { + MEM_freeN(loop_to_poly); + } + + if (r_lnors_spacearr) { + if (r_lnors_spacearr == &_lnors_spacearr) { + BKE_lnor_spacearr_free(r_lnors_spacearr); + } + } + +#ifdef DEBUG_TIME + TIMEIT_END_AVERAGED(BKE_mesh_normals_loop_split); +#endif +} + +#undef INDEX_UNSET +#undef INDEX_INVALID +#undef IS_EDGE_SHARP + +/** + * Compute internal representation of given custom normals (as an array of float[2]). + * It also makes sure the mesh matches those custom normals, by setting sharp edges flag as needed + * to get a same custom lnor for all loops sharing a same smooth fan. + * If use_vertices if true, r_custom_loopnors is assumed to be per-vertex, not per-loop + * (this allows to set whole vert's normals at once, useful in some cases). + * r_custom_loopnors is expected to have normalized normals, or zero ones, + * in which case they will be replaced by default loop/vertex normal. + */ +static void mesh_normals_loop_custom_set(const MVert *mverts, + const int numVerts, + MEdge *medges, + const int numEdges, + MLoop *mloops, + float (*r_custom_loopnors)[3], + const int numLoops, + MPoly *mpolys, + const float (*polynors)[3], + const int numPolys, + short (*r_clnors_data)[2], + const bool use_vertices) +{ + /* We *may* make that poor BKE_mesh_normals_loop_split() even more complex by making it handling + * that feature too, would probably be more efficient in absolute. + * However, this function *is not* performance-critical, since it is mostly expected to be called + * by io addons when importing custom normals, and modifier + * (and perhaps from some editing tools later?). + * So better to keep some simplicity here, and just call BKE_mesh_normals_loop_split() twice! + */ + MLoopNorSpaceArray lnors_spacearr = {NULL}; + BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)numLoops, __func__); + float(*lnors)[3] = MEM_calloc_arrayN((size_t)numLoops, sizeof(*lnors), __func__); + int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(int), __func__); + /* In this case we always consider split nors as ON, + * and do not want to use angle to define smooth fans! */ + const bool use_split_normals = true; + const float split_angle = (float)M_PI; + + BLI_SMALLSTACK_DECLARE(clnors_data, short *); + + /* Compute current lnor spacearr. */ + BKE_mesh_normals_loop_split(mverts, + numVerts, + medges, + numEdges, + mloops, + lnors, + numLoops, + mpolys, + polynors, + numPolys, + use_split_normals, + split_angle, + &lnors_spacearr, + NULL, + loop_to_poly); + + /* Set all given zero vectors to their default value. */ + if (use_vertices) { + for (int i = 0; i < numVerts; i++) { + if (is_zero_v3(r_custom_loopnors[i])) { + normal_short_to_float_v3(r_custom_loopnors[i], mverts[i].no); + } + } + } + else { + for (int i = 0; i < numLoops; i++) { + if (is_zero_v3(r_custom_loopnors[i])) { + copy_v3_v3(r_custom_loopnors[i], lnors[i]); + } + } + } + + BLI_assert(lnors_spacearr.data_type == MLNOR_SPACEARR_LOOP_INDEX); + + /* Now, check each current smooth fan (one lnor space per smooth fan!), + * and if all its matching custom lnors are not (enough) equal, add sharp edges as needed. + * This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans + * matching given custom lnors. + * Note this code *will never* unsharp edges! And quite obviously, + * when we set custom normals per vertices, running this is absolutely useless. + */ + if (!use_vertices) { + for (int i = 0; i < numLoops; i++) { + if (!lnors_spacearr.lspacearr[i]) { + /* This should not happen in theory, but in some rare case (probably ugly geometry) + * we can get some NULL loopspacearr at this point. :/ + * Maybe we should set those loops' edges as sharp? + */ + BLI_BITMAP_ENABLE(done_loops, i); + if (G.debug & G_DEBUG) { + printf("WARNING! Getting invalid NULL loop space for loop %d!\n", i); + } + continue; + } + + if (!BLI_BITMAP_TEST(done_loops, i)) { + /* Notes: + * * In case of mono-loop smooth fan, we have nothing to do. + * * Loops in this linklist are ordered (in reversed order compared to how they were + * discovered by BKE_mesh_normals_loop_split(), but this is not a problem). + * Which means if we find a mismatching clnor, + * we know all remaining loops will have to be in a new, different smooth fan/lnor space. + * * In smooth fan case, we compare each clnor against a ref one, + * to avoid small differences adding up into a real big one in the end! + */ + if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) { + BLI_BITMAP_ENABLE(done_loops, i); + continue; + } + + LinkNode *loops = lnors_spacearr.lspacearr[i]->loops; + MLoop *prev_ml = NULL; + const float *org_nor = NULL; + + while (loops) { + const int lidx = POINTER_AS_INT(loops->link); + MLoop *ml = &mloops[lidx]; + const int nidx = lidx; + float *nor = r_custom_loopnors[nidx]; + + if (!org_nor) { + org_nor = nor; + } + else if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) { + /* Current normal differs too much from org one, we have to tag the edge between + * previous loop's face and current's one as sharp. + * We know those two loops do not point to the same edge, + * since we do not allow reversed winding in a same smooth fan. + */ + const MPoly *mp = &mpolys[loop_to_poly[lidx]]; + const MLoop *mlp = + &mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1]; + medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP; + + org_nor = nor; + } + + prev_ml = ml; + loops = loops->next; + BLI_BITMAP_ENABLE(done_loops, lidx); + } + + /* We also have to check between last and first loops, + * otherwise we may miss some sharp edges here! + * This is just a simplified version of above while loop. + * See T45984. */ + loops = lnors_spacearr.lspacearr[i]->loops; + if (loops && org_nor) { + const int lidx = POINTER_AS_INT(loops->link); + MLoop *ml = &mloops[lidx]; + const int nidx = lidx; + float *nor = r_custom_loopnors[nidx]; + + if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) { + const MPoly *mp = &mpolys[loop_to_poly[lidx]]; + const MLoop *mlp = + &mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1]; + medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP; + } + } + } + } + + /* And now, recompute our new auto lnors and lnor spacearr! */ + BKE_lnor_spacearr_clear(&lnors_spacearr); + BKE_mesh_normals_loop_split(mverts, + numVerts, + medges, + numEdges, + mloops, + lnors, + numLoops, + mpolys, + polynors, + numPolys, + use_split_normals, + split_angle, + &lnors_spacearr, + NULL, + loop_to_poly); + } + else { + BLI_bitmap_set_all(done_loops, true, (size_t)numLoops); + } + + /* And we just have to convert plain object-space custom normals to our + * lnor space-encoded ones. */ + for (int i = 0; i < numLoops; i++) { + if (!lnors_spacearr.lspacearr[i]) { + BLI_BITMAP_DISABLE(done_loops, i); + if (G.debug & G_DEBUG) { + printf("WARNING! Still getting invalid NULL loop space in second loop for loop %d!\n", i); + } + continue; + } + + if (BLI_BITMAP_TEST_BOOL(done_loops, i)) { + /* Note we accumulate and average all custom normals in current smooth fan, + * to avoid getting different clnors data (tiny differences in plain custom normals can + * give rather huge differences in computed 2D factors). + */ + LinkNode *loops = lnors_spacearr.lspacearr[i]->loops; + if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) { + BLI_assert(POINTER_AS_INT(loops) == i); + const int nidx = use_vertices ? (int)mloops[i].v : i; + float *nor = r_custom_loopnors[nidx]; + + BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]); + BLI_BITMAP_DISABLE(done_loops, i); + } + else { + int nbr_nors = 0; + float avg_nor[3]; + short clnor_data_tmp[2], *clnor_data; + + zero_v3(avg_nor); + while (loops) { + const int lidx = POINTER_AS_INT(loops->link); + const int nidx = use_vertices ? (int)mloops[lidx].v : lidx; + float *nor = r_custom_loopnors[nidx]; + + nbr_nors++; + add_v3_v3(avg_nor, nor); + BLI_SMALLSTACK_PUSH(clnors_data, (short *)r_clnors_data[lidx]); + + loops = loops->next; + BLI_BITMAP_DISABLE(done_loops, lidx); + } + + mul_v3_fl(avg_nor, 1.0f / (float)nbr_nors); + BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], avg_nor, clnor_data_tmp); + + while ((clnor_data = BLI_SMALLSTACK_POP(clnors_data))) { + clnor_data[0] = clnor_data_tmp[0]; + clnor_data[1] = clnor_data_tmp[1]; + } + } + } + } + + MEM_freeN(lnors); + MEM_freeN(loop_to_poly); + MEM_freeN(done_loops); + BKE_lnor_spacearr_free(&lnors_spacearr); +} + +void BKE_mesh_normals_loop_custom_set(const MVert *mverts, + const int numVerts, + MEdge *medges, + const int numEdges, + MLoop *mloops, + float (*r_custom_loopnors)[3], + const int numLoops, + MPoly *mpolys, + const float (*polynors)[3], + const int numPolys, + short (*r_clnors_data)[2]) +{ + mesh_normals_loop_custom_set(mverts, + numVerts, + medges, + numEdges, + mloops, + r_custom_loopnors, + numLoops, + mpolys, + polynors, + numPolys, + r_clnors_data, + false); +} + +void BKE_mesh_normals_loop_custom_from_vertices_set(const MVert *mverts, + float (*r_custom_vertnors)[3], + const int numVerts, + MEdge *medges, + const int numEdges, + MLoop *mloops, + const int numLoops, + MPoly *mpolys, + const float (*polynors)[3], + const int numPolys, + short (*r_clnors_data)[2]) +{ + mesh_normals_loop_custom_set(mverts, + numVerts, + medges, + numEdges, + mloops, + r_custom_vertnors, + numLoops, + mpolys, + polynors, + numPolys, + r_clnors_data, + true); +} + +static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const bool use_vertices) +{ + short(*clnors)[2]; + const int numloops = mesh->totloop; + + clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); + if (clnors != NULL) { + memset(clnors, 0, sizeof(*clnors) * (size_t)numloops); + } + else { + clnors = CustomData_add_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, numloops); + } + + float(*polynors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL); + bool free_polynors = false; + if (polynors == NULL) { + polynors = MEM_mallocN(sizeof(float[3]) * (size_t)mesh->totpoly, __func__); + BKE_mesh_calc_normals_poly(mesh->mvert, + NULL, + mesh->totvert, + mesh->mloop, + mesh->mpoly, + mesh->totloop, + mesh->totpoly, + polynors, + false); + free_polynors = true; + } + + mesh_normals_loop_custom_set(mesh->mvert, + mesh->totvert, + mesh->medge, + mesh->totedge, + mesh->mloop, + r_custom_nors, + mesh->totloop, + mesh->mpoly, + polynors, + mesh->totpoly, + clnors, + use_vertices); + + if (free_polynors) { + MEM_freeN(polynors); + } +} + +/** + * Higher level functions hiding most of the code needed around call to + * #BKE_mesh_normals_loop_custom_set(). + * + * \param r_custom_loopnors: is not const, since code will replace zero_v3 normals there + * with automatically computed vectors. + */ +void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loopnors)[3]) +{ + mesh_set_custom_normals(mesh, r_custom_loopnors, false); +} + +/** + * Higher level functions hiding most of the code needed around call to + * #BKE_mesh_normals_loop_custom_from_vertices_set(). + * + * \param r_custom_vertnors: is not const, since code will replace zero_v3 normals there + * with automatically computed vectors. + */ +void BKE_mesh_set_custom_normals_from_vertices(Mesh *mesh, float (*r_custom_vertnors)[3]) +{ + mesh_set_custom_normals(mesh, r_custom_vertnors, true); +} + +/** + * Computes average per-vertex normals from given custom loop normals. + * + * \param clnors: The computed custom loop normals. + * \param r_vert_clnors: The (already allocated) array where to store averaged per-vertex normals. + */ +void BKE_mesh_normals_loop_to_vertex(const int numVerts, + const MLoop *mloops, + const int numLoops, + const float (*clnors)[3], + float (*r_vert_clnors)[3]) +{ + int *vert_loops_nbr = MEM_calloc_arrayN((size_t)numVerts, sizeof(*vert_loops_nbr), __func__); + + copy_vn_fl((float *)r_vert_clnors, 3 * numVerts, 0.0f); + + int i; + const MLoop *ml; + for (i = 0, ml = mloops; i < numLoops; i++, ml++) { + const uint v = ml->v; + + add_v3_v3(r_vert_clnors[v], clnors[i]); + vert_loops_nbr[v]++; + } + + for (i = 0; i < numVerts; i++) { + mul_v3_fl(r_vert_clnors[i], 1.0f / (float)vert_loops_nbr[i]); + } + + MEM_freeN(vert_loops_nbr); +} + +#undef LNOR_SPACE_TRIGO_THRESHOLD + +/** \} */ diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c index 011dd7e25ee..47d300dc0c2 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.c +++ b/source/blender/blenkernel/intern/mesh_runtime.c @@ -158,8 +158,12 @@ static void mesh_runtime_looptri_recalc_isolated(void *userdata) BKE_mesh_runtime_looptri_recalc(mesh); } -/* This is a ported copy of dm_getLoopTriArray(dm). */ -const MLoopTri *BKE_mesh_runtime_looptri_ensure(Mesh *mesh) +/** + * \note This function only fills a cache, and therefore the mesh argument can + * be considered logically const. Concurrent access is protected by a mutex. + * \note This is a ported copy of dm_getLoopTriArray(dm). + */ +const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh) { ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex; BLI_mutex_lock(mesh_eval_mutex); @@ -171,7 +175,7 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(Mesh *mesh) } else { /* Must isolate multithreaded tasks while holding a mutex lock. */ - BLI_task_isolate(mesh_runtime_looptri_recalc_isolated, mesh); + BLI_task_isolate(mesh_runtime_looptri_recalc_isolated, (void *)mesh); looptri = mesh->runtime.looptris.array; } diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index df84cf6607f..bfdbf844a26 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -1105,7 +1105,7 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_ &changed); if (changed) { - DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY_ALL_MODES); return true; } @@ -1183,7 +1183,7 @@ bool BKE_mesh_validate_material_indices(Mesh *me) } if (!is_valid) { - DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY_ALL_MODES); return true; } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 0f2f56f4f2b..3a7910d1a9f 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1320,7 +1320,7 @@ static ImBuf *movieclip_get_postprocessed_ibuf( clip->lastframe = framenr; real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]); - /* postprocess frame and put to cache if needed*/ + /* Post-process frame and put to cache if needed. */ if (need_postprocess) { ImBuf *tmpibuf = ibuf; ibuf = postprocess_frame(clip, user, tmpibuf, flag, postprocess_flag); @@ -2128,9 +2128,9 @@ GPUTexture *BKE_movieclip_get_gpu_texture(MovieClip *clip, MovieClipUser *cuser) void BKE_movieclip_free_gputexture(struct MovieClip *clip) { - /* number of gpu textures to keep around as cache + /* Number of gpu textures to keep around as cache. * We don't want to keep too many GPU textures for - * movie clips around, as they can be large.*/ + * movie clips around, as they can be large. */ const int MOVIECLIP_NUM_GPUTEXTURES = 1; while (BLI_listbase_count(&clip->runtime.gputextures) > MOVIECLIP_NUM_GPUTEXTURES) { diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 45ac20ef154..54f0da30a2b 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -994,7 +994,7 @@ static void multiresModifier_disp_run( } } - /*numGrids = dm->getNumGrids(dm);*/ /*UNUSED*/ + // numGrids = dm->getNumGrids(dm); /* UNUSED */ gridSize = dm->getGridSize(dm); gridData = dm->getGridData(dm); gridOffset = dm->getGridOffset(dm); @@ -1285,7 +1285,7 @@ DerivedMesh *multires_make_derived_from_derived( multires_set_tot_mdisps(me, mmd->totlvl); multiresModifier_ensure_external_read(me, mmd); - /*run displacement*/ + /* Run displacement. */ multiresModifier_disp_run(result, ob->data, dm, APPLY_DISPLACEMENTS, subGridData, mmd->totlvl); /* copy hidden elements for this level */ @@ -1514,7 +1514,7 @@ void multires_topology_changed(Mesh *me) * * Since the multires data files only contain displacement vectors without knowledge about * subdivision level some extra work is needed. Namely make is to all displacement grids have - * proper level and number of displacement vectors set. */ + * proper level and number of displacement vectors set. */ void multires_ensure_external_read(struct Mesh *mesh, int top_level) { if (!CustomData_external_test(&mesh->ldata, CD_MDISPS)) { diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c index 04ad78ec0de..bd52d70b223 100644 --- a/source/blender/blenkernel/intern/multires_reshape.c +++ b/source/blender/blenkernel/intern/multires_reshape.c @@ -235,7 +235,7 @@ void multiresModifier_subdivide_to_level(struct Object *object, /* Free original grids which makes it so smoothing with details thinks all the details were * added against base mesh's limit surface. This is similar behavior to as if we've done all - * displacement in sculpt mode at the old top level and then propagated to the new top level.*/ + * displacement in sculpt mode at the old top level and then propagated to the new top level. */ multires_reshape_free_original_grids(&reshape_context); if (ELEM(mode, MULTIRES_SUBDIVIDE_LINEAR, MULTIRES_SUBDIVIDE_SIMPLE)) { diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c index f10aae18142..aed8c3122a2 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.c +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c @@ -55,7 +55,7 @@ /* Surface refers to a simplified and lower-memory footprint representation of the limit surface. * * Used to store pre-calculated information which is expensive or impossible to evaluate when - * traversing the final limit surface. */ + * traversing the final limit surface. */ typedef struct SurfacePoint { float P[3]; @@ -1027,7 +1027,7 @@ static void converter_init(const MultiresReshapeSmoothContext *reshape_smooth_co converter->user_data = (void *)reshape_smooth_context; } -/* Create subdiv descriptor created for topology at a reshape level, */ +/* Create subdiv descriptor created for topology at a reshape level. */ static void reshape_subdiv_create(MultiresReshapeSmoothContext *reshape_smooth_context) { const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; @@ -1050,7 +1050,7 @@ typedef void(ReshapeSubdivCoarsePositionCb)( const Vertex *vertex, float r_P[3]); -/* Refine subdivision surface topology at a reshape level for new coarse vertices positions. */ +/* Refine subdivision surface topology at a reshape level for new coarse vertices positions. */ static void reshape_subdiv_refine(const MultiresReshapeSmoothContext *reshape_smooth_context, ReshapeSubdivCoarsePositionCb coarse_position_cb) { diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.c b/source/blender/blenkernel/intern/multires_unsubdivide.c index 02b9bb852d6..4210f26a694 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.c +++ b/source/blender/blenkernel/intern/multires_unsubdivide.c @@ -312,7 +312,7 @@ static bool unsubdivide_tag_disconnected_mesh_element(BMesh *bm, int *elem_id, i /* Also try from the different 4 vertices of a quad in the current * disconnected element ID. If a solution exists the search should return a valid solution from - * one of these vertices.*/ + * one of these vertices. */ BMFace *f, *init_face = NULL; BMVert *v; BMIter iter_a, iter_b; diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 92e21183acb..bf18765aa94 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1289,7 +1289,7 @@ void BKE_nlastrip_set_active(AnimData *adt, NlaStrip *strip) return; } - /* loop over tracks, deactivating*/ + /* Loop over tracks, deactivating. */ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { for (nls = nlt->strips.first; nls; nls = nls->next) { if (nls != strip) { @@ -1560,7 +1560,7 @@ bool BKE_nlatracks_have_animated_strips(ListBase *tracks) return false; } -/* Validate the NLA-Strips 'control' F-Curves based on the flags set*/ +/* Validate the NLA-Strips 'control' F-Curves based on the flags set. */ void BKE_nlastrip_validate_fcurves(NlaStrip *strip) { FCurve *fcu; diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index db18cecb5d3..e6635665567 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -875,7 +875,7 @@ void ntreeBlendReadLib(struct BlendLibReader *reader, struct bNodeTree *ntree) LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { /* Link ID Properties -- and copy this comment EXACTLY for easy finding - * of library blocks that implement this.*/ + * of library blocks that implement this. */ IDP_BlendReadLib(reader, node->prop); BLO_read_id_address(reader, lib, &node->id); @@ -2365,7 +2365,7 @@ static void nodeUnMuteLink(bNodeLink *link) link->tosock->flag |= SOCK_IN_USE; } -/* Upstream muting. Always happens when unmuting but checks when muting. O(n^2) algorithm.*/ +/* Upstream muting. Always happens when unmuting but checks when muting. O(n^2) algorithm. */ static void nodeMuteRerouteInputLinks(bNodeTree *ntree, bNode *node, const bool mute) { if (node->type != NODE_REROUTE) { @@ -2388,7 +2388,7 @@ static void nodeMuteRerouteInputLinks(bNodeTree *ntree, bNode *node, const bool } } -/* Downstream muting propagates when reaching reroute nodes. O(n^2) algorithm.*/ +/* Downstream muting propagates when reaching reroute nodes. O(n^2) algorithm. */ static void nodeMuteRerouteOutputLinks(bNodeTree *ntree, bNode *node, const bool mute) { if (node->type != NODE_REROUTE) { @@ -5054,6 +5054,11 @@ static void registerGeometryNodes() register_node_type_geo_collection_info(); register_node_type_geo_convex_hull(); register_node_type_geo_curve_length(); + register_node_type_geo_curve_primitive_bezier_segment(); + register_node_type_geo_curve_primitive_circle(); + register_node_type_geo_curve_primitive_quadratic_bezier(); + register_node_type_geo_curve_primitive_spiral(); + register_node_type_geo_curve_primitive_star(); register_node_type_geo_curve_to_mesh(); register_node_type_geo_curve_to_points(); register_node_type_geo_curve_resample(); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 8cfd75b015c..ff5d94d20b7 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2759,7 +2759,7 @@ Object *BKE_object_duplicate(Main *bmain, } if (!is_subprocess) { - /* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW.*/ + /* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */ BKE_libblock_relink_to_newid(&obn->id); #ifndef NDEBUG @@ -2854,7 +2854,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target) else { /* only on local objects because this causes indirect links * 'a -> b -> c', blend to point directly to a.blend - * when a.blend has a proxy that's linked into c.blend */ + * when a.blend has a proxy that's linked into `c.blend`. */ if (!ID_IS_LINKED(ob)) { id_lib_extern((ID *)dtar->id); } @@ -3212,12 +3212,11 @@ void BKE_object_to_mat3(Object *ob, float r_mat[3][3]) /* no parent */ { float smat[3][3]; float rmat[3][3]; - /*float q1[4];*/ - /* scale */ + /* Scale. */ BKE_object_scale_to_mat3(ob, smat); - /* rot */ + /* Rotation. */ BKE_object_rot_to_mat3(ob, rmat, true); mul_m3_m3m3(r_mat, rmat, smat); } @@ -3861,7 +3860,7 @@ void BKE_object_boundbox_flag(Object *ob, int flag, const bool set) } } -void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval) +void BKE_object_boundbox_calc_from_mesh(struct Object *ob, const struct Mesh *me_eval) { float min[3], max[3]; @@ -4170,7 +4169,7 @@ void BKE_object_foreach_display_point(Object *ob, void *user_data) { /* TODO: pointcloud and hair objects support */ - Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); float co[3]; if (mesh_eval != NULL) { @@ -4476,7 +4475,7 @@ Mesh *BKE_object_get_pre_modified_mesh(const Object *object) } /** - * Get a mesh which corresponds to very very original mesh from #Main. + * Get a mesh which corresponds to the very original mesh from #Main. * - For original objects it will be object->data. * - For evaluated objects it will be same mesh as corresponding original * object uses as data. @@ -5304,7 +5303,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) tot = 0; tree = BLI_kdtree_3d_new(totvert); - /* we don't how how many verts from the DM we can use */ + /* We don't how many verts from the DM we can use. */ for (i = 0; i < totvert; i++) { if (index[i] != ORIGINDEX_NONE) { float co[3]; diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 768fa9373c1..77969328365 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -335,14 +335,14 @@ static void make_child_duplis(const DupliContext *ctx, /** \name Internal Data Access Utilities * \{ */ -static Mesh *mesh_data_from_duplicator_object(Object *ob, - BMEditMesh **r_em, - const float (**r_vert_coords)[3], - const float (**r_vert_normals)[3]) +static const Mesh *mesh_data_from_duplicator_object(Object *ob, + BMEditMesh **r_em, + const float (**r_vert_coords)[3], + const float (**r_vert_normals)[3]) { /* Gather mesh info. */ BMEditMesh *em = BKE_editmesh_from_object(ob); - Mesh *me_eval; + const Mesh *me_eval; *r_em = nullptr; *r_vert_coords = nullptr; @@ -603,7 +603,7 @@ static void make_duplis_verts(const DupliContext *ctx) BMEditMesh *em = nullptr; const float(*vert_coords)[3] = nullptr; const float(*vert_normals)[3] = nullptr; - Mesh *me_eval = mesh_data_from_duplicator_object( + const Mesh *me_eval = mesh_data_from_duplicator_object( parent, &em, &vert_coords, use_rotation ? &vert_normals : nullptr); if (em == nullptr && me_eval == nullptr) { return; @@ -1151,7 +1151,7 @@ static void make_duplis_faces(const DupliContext *ctx) /* Gather mesh info. */ BMEditMesh *em = nullptr; const float(*vert_coords)[3] = nullptr; - Mesh *me_eval = mesh_data_from_duplicator_object(parent, &em, &vert_coords, nullptr); + const Mesh *me_eval = mesh_data_from_duplicator_object(parent, &em, &vert_coords, nullptr); if (em == nullptr && me_eval == nullptr) { return; } diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index b1afd968bdc..ab247ef5507 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -224,7 +224,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o case OB_SURF: case OB_FONT: { bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); - BKE_displist_make_curveTypes(depsgraph, scene, ob, for_render, false); + BKE_displist_make_curveTypes(depsgraph, scene, ob, for_render); break; } diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 9d53dad8d03..2e7152302c7 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -248,7 +248,7 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float if (oc->_do_normals) { ocr->normal[0] = BILERP(oc->_N_x); - ocr->normal[1] = oc->_N_y /*BILERP(oc->_N_y) (MEM01)*/; + ocr->normal[1] = oc->_N_y /* BILERP(oc->_N_y) (MEM01) */; ocr->normal[2] = BILERP(oc->_N_z); } @@ -347,7 +347,7 @@ void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u } if (oc->_do_normals) { ocr->normal[0] = INTERP(oc->_N_x); - ocr->normal[1] = oc->_N_y /*INTERP(oc->_N_y) (MEM01)*/; + ocr->normal[1] = oc->_N_y /* INTERP(oc->_N_y) (MEM01) */; ocr->normal[2] = INTERP(oc->_N_z); } if (oc->_do_chop) { @@ -1052,7 +1052,7 @@ void BKE_ocean_free_data(struct Ocean *oc) fftw_destroy_plan(oc->_N_x_plan); fftw_destroy_plan(oc->_N_z_plan); MEM_freeN(oc->_N_x); - /*fftwf_free(oc->_N_y); (MEM01)*/ + /* fftwf_free(oc->_N_y); (MEM01) */ MEM_freeN(oc->_N_z); } @@ -1437,9 +1437,9 @@ void BKE_ocean_bake(struct Ocean *o, rgb_to_rgba_unit_alpha(&ibuf_disp->rect_float[4 * (res_x * y + x)], ocr.disp); if (o->_do_jacobian) { - /* TODO, cleanup unused code - campbell */ + /* TODO: cleanup unused code - campbell */ - float /*r, */ /* UNUSED */ pr = 0.0f, foam_result; + float /* r, */ /* UNUSED */ pr = 0.0f, foam_result; float neg_disp, neg_eplus; ocr.foam = BKE_ocean_jminus_to_foam(ocr.Jminus, och->foam_coverage); @@ -1449,9 +1449,9 @@ void BKE_ocean_bake(struct Ocean *o, pr = prev_foam[res_x * y + x]; } - /* r = BLI_rng_get_float(rng); */ /* UNUSED */ /* randomly reduce foam */ + // r = BLI_rng_get_float(rng); /* UNUSED */ /* randomly reduce foam */ - /* pr = pr * och->foam_fade; */ /* overall fade */ + // pr = pr * och->foam_fade; /* overall fade */ /* Remember ocean coord sys is Y up! * break up the foam where height (Y) is low (wave valley), @@ -1475,7 +1475,7 @@ void BKE_ocean_bake(struct Ocean *o, prev_foam[res_x * y + x] = foam_result; - /*foam_result = min_ff(foam_result, 1.0f); */ + // foam_result = min_ff(foam_result, 1.0f); value_to_rgba_unit_alpha(&ibuf_foam->rect_float[4 * (res_x * y + x)], foam_result); diff --git a/source/blender/blenkernel/intern/ocean_intern.h b/source/blender/blenkernel/intern/ocean_intern.h index b55b211fa33..4ebd03789af 100644 --- a/source/blender/blenkernel/intern/ocean_intern.h +++ b/source/blender/blenkernel/intern/ocean_intern.h @@ -99,7 +99,7 @@ typedef struct Ocean { double *_N_x; /* init w sim w via plan? */ /* all member of this array has same values, * so convert this array to a float to reduce memory usage (MEM01). */ - /*float * _N_y; */ + // float * _N_y; double _N_y; /* sim w ********* can be rearranged? */ double *_N_z; /* init w sim w via plan? */ double *_disp_x; /* init w sim w via plan? */ diff --git a/source/blender/blenkernel/intern/ocean_spectrum.c b/source/blender/blenkernel/intern/ocean_spectrum.c index 1f7cc56f1a9..7ed70234baf 100644 --- a/source/blender/blenkernel/intern/ocean_spectrum.c +++ b/source/blender/blenkernel/intern/ocean_spectrum.c @@ -122,7 +122,7 @@ static float jonswap(const Ocean *oc, const float k2) float val = alpha_beta_spectrum(m_alpha, beta, GRAVITY, omega, m_peakomega); - /* Peak sharpening */ + /* Peak sharpening. */ val *= peak_sharpen(m_omega, m_peakomega, m_gamma); return val; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 3494630e1fa..a7c6dc2deb9 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1810,7 +1810,7 @@ void BKE_sculpt_color_layer_create_if_needed(struct Object *object) CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert); BKE_mesh_update_customdata_pointers(orig_me, true); - DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY_ALL_MODES); } /** \warning Expects a fully evaluated depsgraph. */ diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 021121034f1..d386967bf8b 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2462,7 +2462,7 @@ int do_guides(Depsgraph *depsgraph, (int)(data->strength * guidetime * 100.0f), 100)); } - else { /* curve size*/ + else { /* Curve size. */ if (cu->flag & CU_PATH_RADIUS) { mul_v3_fl(vec_to_point, radius); } diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index 6e0965650d3..2231731287d 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -785,7 +785,7 @@ static void do_twist(const ParticleChildModifierContext *modifier_ctx, return; } if (part->twist == 0.0f) { - /* No twist along the strand. */ + /* No twist along the strand. */ return; } /* Dependent on whether it's threaded update or not, curve comes diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 13f0cb28428..1fd99bb2cbd 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -142,7 +142,7 @@ static void distribute_grid(Mesh *mesh, ParticleSystem *psys) size[(axis + 1) % 3] = (int)ceil(delta[(axis + 1) % 3] / d); size[(axis + 2) % 3] = (int)ceil(delta[(axis + 2) % 3] / d); - /* float errors grrr.. */ + /* float errors grrr. */ size[(axis + 1) % 3] = MIN2(size[(axis + 1) % 3], res); size[(axis + 2) % 3] = MIN2(size[(axis + 2) % 3], res); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index d236dbbf101..c35f703b072 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -250,7 +250,7 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) if (psys->particles) { totsaved = MIN2(psys->totpart, totpart); - /*save old pars*/ + /* Save old pars. */ if (totsaved) { memcpy(newpars, psys->particles, totsaved * sizeof(ParticleData)); @@ -607,8 +607,8 @@ void init_particle(ParticleSimulationData *sim, ParticleData *pa) pa->time = part->sta + (part->end - part->sta) * birth_time; pa->hair_index = 0; - /* we can't reset to -1 anymore since we've figured out correct index in distribute_particles */ - /* usage other than straight after distribute has to handle this index by itself - jahka*/ + /* We can't reset to -1 anymore since we've figured out correct index in #distribute_particles + * usage other than straight after distribute has to handle this index by itself - jahka. */ // pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we don't have a derived mesh face */ } @@ -840,7 +840,7 @@ void psys_get_birth_coords( copy_v3_v3(state->co, loc); - /* boids don't get any initial velocity */ + /* boids don't get any initial velocity. */ zero_v3(state->vel); /* boids store direction in ave */ @@ -1473,7 +1473,7 @@ static void integrate_particle( force_func(forcedata, states + i, force, impulse); - /* force to acceleration*/ + /* Force to acceleration. */ mul_v3_v3fl(acceleration, force, 1.0f / pa_mass); if (external_acceleration) { @@ -1920,7 +1920,7 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa } } - /* Artificial buoyancy force in negative gravity direction */ + /* Artificial buoyancy force in negative gravity direction. */ if (fluid->buoyancy > 0.0f && gravity) { madd_v3_v3fl(force, gravity, fluid->buoyancy * (density - rest_density)); } @@ -2095,7 +2095,7 @@ static void sphclassical_force_cb(void *sphdata_v, } } - /* Artificial buoyancy force in negative gravity direction */ + /* Artificial buoyancy force in negative gravity direction. */ if (fluid->buoyancy > 0.0f && gravity) { madd_v3_v3fl(force, gravity, fluid->buoyancy * (pa->sphdensity - rest_density)); } @@ -2226,7 +2226,7 @@ static void sph_integrate(ParticleSimulationData *sim, sphdata->pass = 0; // sphdata.element_size and sphdata.flow are set in the callback. - /* restore previous state and treat gravity & effectors as external acceleration*/ + /* Restore previous state and treat gravity & effectors as external acceleration. */ sub_v3_v3v3(effector_acceleration, pa->state.vel, pa->prev_state.vel); mul_v3_fl(effector_acceleration, 1.0f / dtime); @@ -3001,7 +3001,7 @@ static int collision_response(ParticleSimulationData *sim, /* get back to global coordinates */ add_v3_v3(v1_tan, vc_tan); - /* convert to angular velocity*/ + /* Convert to angular velocity. */ cross_v3_v3v3(ave, vr_tan, pce->nor); mul_v3_fl(ave, 1.0f / MAX2(pa->size, 0.001f)); @@ -3369,7 +3369,7 @@ static void hair_create_input_mesh(ParticleSimulationData *sim, /* XXX placeholder for more flexible future hair settings */ hair_radius = part->size; - /* make vgroup for pin roots etc.. */ + /* Make vgroup for pin roots etc. */ hair_index = 1; LOOP_PARTICLES { @@ -3927,7 +3927,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) pa->alive = PARS_DYING; } else if (birthtime <= cfra && birthtime >= psys->cfra) { - /* particle is born some time between this and last step*/ + /* Particle is born some time between this and last step. */ reset_particle(sim, pa, dfra * timestep, cfra); pa->alive = PARS_ALIVE; pa->state.time = cfra - birthtime; @@ -3936,7 +3936,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) /* nothing to be done when particle is dead */ } - /* only reset unborn particles if they're shown or if the particle is born soon*/ + /* Only reset unborn particles if they're shown or if the particle is born soon. */ if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN || (cfra + psys->pointcache->step > pa->time))) { reset_particle(sim, pa, dtime, cfra); @@ -4104,7 +4104,7 @@ static void update_children(ParticleSimulationData *sim, const bool use_render_p psys_free_children(sim->psys); } } -/* updates cached particles' alive & other flags etc..*/ +/* Updates cached particles' alive & other flags etc. */ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_render_params) { ParticleSystem *psys = sim->psys; diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 9f316ec60c0..0d84022da77 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -2985,7 +2985,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m } } -bool pbvh_has_mask(PBVH *pbvh) +bool pbvh_has_mask(const PBVH *pbvh) { switch (pbvh->type) { case PBVH_GRIDS: diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 09e4ad93baa..c2483b265a5 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -180,7 +180,7 @@ static BMVert *bm_vert_hash_lookup_chain(GHash *deleted_verts, BMVert *v) while (true) { BMVert **v_next_p = (BMVert **)BLI_ghash_lookup_p(deleted_verts, v); if (v_next_p == NULL) { - /* not remapped*/ + /* Not remapped. */ return v; } if (*v_next_p == NULL) { @@ -2316,7 +2316,7 @@ static void pbvh_bmesh_verify(PBVH *pbvh) vert_count++; } - /* if totvert differs from number of verts inside the hash. hash-totvert is checked above */ + /* If totvert differs from number of verts inside the hash. hash-totvert is checked above. */ BLI_assert(vert_count == pbvh->bm->totvert); # endif diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index be206f8a642..a05eb6962ce 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2632,7 +2632,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) } #endif - /*if (!G.relbase_valid) return; */ /* save blend file before using pointcache */ + // if (!G.relbase_valid) return; /* Save blend file before using pointcache. */ /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */ switch (mode) { @@ -2659,8 +2659,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) ptcache_filename_ext_append(pid, ext, 0, false, 0); while ((de = readdir(dir)) != NULL) { - if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ - if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */ + if (strstr(de->d_name, ext)) { /* Do we have the right extension? */ + if (STREQLEN(filename, de->d_name, len)) { /* Do we have the right prefix. */ if (mode == PTCACHE_CLEAR_ALL) { pid->cache->last_exact = MIN2(pid->cache->startframe, 0); BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); @@ -2695,7 +2695,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) PTCacheMem *link = NULL; if (mode == PTCACHE_CLEAR_ALL) { - /*we want startframe if the cache starts before zero*/ + /* We want startframe if the cache starts before zero. */ pid->cache->last_exact = MIN2(pid->cache->startframe, 0); for (; pm; pm = pm->next) { ptcache_mem_clear(pm); @@ -2856,8 +2856,8 @@ void BKE_ptcache_id_time( ptcache_filename_ext_append(pid, ext, 0, false, 0); while ((de = readdir(dir)) != NULL) { - if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ - if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */ + if (strstr(de->d_name, ext)) { /* Do we have the right extension? */ + if (STREQLEN(filename, de->d_name, len)) { /* Do we have the right prefix. */ /* read the number of the file */ const int frame = ptcache_frame_from_filename(de->d_name, ext); @@ -3038,7 +3038,7 @@ void BKE_ptcache_remove(void) if (FILENAME_IS_CURRPAR(de->d_name)) { /* do nothing */ } - else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/ + else if (strstr(de->d_name, PTCACHE_EXT)) { /* Do we have the right extension? */ BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); BLI_delete(path_full, false, false); } @@ -3050,7 +3050,7 @@ void BKE_ptcache_remove(void) closedir(dir); } else { - rmdir = 0; /* path doesn't exist */ + rmdir = 0; /* Path doesn't exist. */ } if (rmdir) { @@ -3569,8 +3569,8 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c BLI_strncpy(pid->cache->name, name_dst, sizeof(pid->cache->name)); while ((de = readdir(dir)) != NULL) { - if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ - if (STREQLEN(old_filename, de->d_name, len)) { /* do we have the right prefix */ + if (strstr(de->d_name, ext)) { /* Do we have the right extension? */ + if (STREQLEN(old_filename, de->d_name, len)) { /* Do we have the right prefix. */ /* read the number of the file */ const int frame = ptcache_frame_from_filename(de->d_name, ext); @@ -3589,7 +3589,7 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c void BKE_ptcache_load_external(PTCacheID *pid) { - /*todo*/ + /* TODO: */ PointCache *cache = pid->cache; int len; /* store the length of the string */ int info = 0; @@ -3626,8 +3626,8 @@ void BKE_ptcache_load_external(PTCacheID *pid) } while ((de = readdir(dir)) != NULL) { - if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ - if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */ + if (strstr(de->d_name, ext)) { /* Do we have the right extension? */ + if (STREQLEN(filename, de->d_name, len)) { /* Do we have the right prefix. */ /* read the number of the file */ const int frame = ptcache_frame_from_filename(de->d_name, ext); diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 21b86aa8148..2d4cce4b953 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -668,7 +668,7 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) radius = max_fff(size[0], size[1], size[2]) * 0.5f; } - /* calculate volume as appropriate */ + /* Calculate volume as appropriate. */ switch (rbo->shape) { case RB_SHAPE_BOX: volume = size[0] * size[1] * size[2]; @@ -744,10 +744,10 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3]) * (i.e. Object pivot is centralized in boundbox) * - boundbox gives full width */ - /* XXX: all dimensions are auto-determined now... later can add stored settings for this */ + /* XXX: all dimensions are auto-determined now... later can add stored settings for this. */ BKE_object_dimensions_get(ob, size); - /* calculate volume as appropriate */ + /* Calculate volume as appropriate. */ switch (rbo->shape) { case RB_SHAPE_BOX: case RB_SHAPE_SPHERE: diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 41f70db3fba..84741038164 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -228,7 +228,10 @@ static void scene_init_data(ID *id) /* Curve Profile */ scene->toolsettings->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE); + + /* Sequencer */ scene->toolsettings->sequencer_tool_settings = SEQ_tool_settings_init(); + scene->toolsettings->snap_flag |= SCE_SNAP_SEQ; for (size_t i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) { scene->orientation_slots[i].index_custom = -1; @@ -2013,7 +2016,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) bmain, NULL, sce_copy->master_collection, duplicate_flags, LIB_ID_DUPLICATE_IS_SUBPROCESS); if (!is_subprocess) { - /* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW.*/ + /* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */ BKE_libblock_relink_to_newid(&sce_copy->id); #ifndef NDEBUG @@ -3379,7 +3382,7 @@ static bool depsgraph_key_compare(const void *key_a_v, const void *key_b_v) { const DepsgraphKey *key_a = key_a_v; const DepsgraphKey *key_b = key_b_v; - /* TODO(sergey): Compare rest of */ + /* TODO(sergey): Compare rest of. */ return !(key_a->view_layer == key_b->view_layer); } diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 7a5892baaf6..608317933f5 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -1703,9 +1703,9 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) BLO_read_list(reader, &sconsole->scrollback); BLO_read_list(reader, &sconsole->history); - /* comma expressions, (e.g. expr1, expr2, expr3) evaluate each expression, + /* Comma expressions, (e.g. expr1, expr2, expr3) evaluate each expression, * from left to right. the right-most expression sets the result of the comma - * expression as a whole*/ + * expression as a whole. */ LISTBASE_FOREACH_MUTABLE (ConsoleLine *, cl, &sconsole->history) { BLO_read_data_address(reader, &cl->line); if (cl->line) { diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c index 60f0b744e59..b537bdc5479 100644 --- a/source/blender/blenkernel/intern/shader_fx.c +++ b/source/blender/blenkernel/intern/shader_fx.c @@ -58,9 +58,9 @@ static ShaderFxTypeInfo *shader_fx_types[NUM_SHADER_FX_TYPES] = {NULL}; /* Methods - Evaluation Loops, etc. */ /* check if exist grease pencil effects */ -bool BKE_shaderfx_has_gpencil(Object *ob) +bool BKE_shaderfx_has_gpencil(const Object *ob) { - ShaderFxData *fx; + const ShaderFxData *fx; for (fx = ob->shader_fx.first; fx; fx = fx->next) { const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); if (fxi->type == eShaderFxType_GpencilType) { diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index ae39b200b56..aeb8133974e 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -546,7 +546,7 @@ static void shrinkwrap_calc_normal_projection_cb_ex(void *__restrict userdata, } if (calc->vert != NULL && calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) { - /* calc->vert contains verts from evaluated mesh. */ + /* calc->vert contains verts from evaluated mesh. */ /* These coordinates are deformed by vertexCos only for normal projection * (to get correct normals) for other cases calc->verts contains undeformed coordinates and * vertexCos should be used */ diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index fcc1afbc59b..9d871777c61 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -109,11 +109,11 @@ typedef struct ReferenceVert { } ReferenceVert; typedef struct ReferenceState { - float com[3]; /* center of mass*/ - ReferenceVert *ivert; /* list of initial values */ + float com[3]; /* Center of mass. */ + ReferenceVert *ivert; /* List of initial values. */ } ReferenceState; -/*private scratch pad for caching and other data only needed when alive*/ +/* Private scratch pad for caching and other data only needed when alive. */ typedef struct SBScratch { GHash *colliderhash; short needstobuildcollider; @@ -150,11 +150,11 @@ typedef struct SB_thread_context { #define BSF_INTERSECT 1 /* edge intersects collider face */ /* private definitions for bodypoint states */ -#define SBF_DOFUZZY 1 /* Bodypoint do fuzzy */ -#define SBF_OUTOFCOLLISION 2 /* Bodypoint does not collide */ +#define SBF_DOFUZZY 1 /* Bodypoint do fuzzy. */ +#define SBF_OUTOFCOLLISION 2 /* Bodypoint does not collide. */ -#define BFF_INTERSECT 1 /* collider edge intrudes face */ -#define BFF_CLOSEVERT 2 /* collider vertex repulses face */ +#define BFF_INTERSECT 1 /* collider edge intrudes face. */ +#define BFF_CLOSEVERT 2 /* collider vertex repulses face. */ /* humm .. this should be calculated from sb parameters and sizes. */ static float SoftHeunTol = 1.0f; @@ -162,9 +162,9 @@ static float SoftHeunTol = 1.0f; /* local prototypes */ static void free_softbody_intern(SoftBody *sb); -/*+++ frame based timing +++*/ +/*+++ frame based timing +++ */ -/*physical unit of force is [kg * m / sec^2]*/ +/* Physical unit of force is `kg * m / sec^2`. */ /** * Since unit of g is [m/sec^2] and F = mass * g we re-scale unit mass of node to 1 gram @@ -207,7 +207,7 @@ static float sb_time_scale(Object *ob) } /*--- frame based timing ---*/ -/* helper functions for everything is animatable jow_go_for2_5 +++++++*/ +/* helper functions for everything is animatable jow_go_for2_5 +++++++ */ /* introducing them here, because i know: steps in properties ( at frame timing ) * will cause unwanted responses of the softbody system (which does inter frame calculations ) * so first 'cure' would be: interpolate linear in time .. @@ -217,7 +217,7 @@ static float sb_time_scale(Object *ob) */ /* animate sb->maxgoal, sb->mingoal */ -static float _final_goal(Object *ob, BodyPoint *bp) /*jow_go_for2_5 */ +static float _final_goal(Object *ob, BodyPoint *bp) /* jow_go_for2_5 */ { float f = -1999.99f; if (ob) { @@ -235,7 +235,7 @@ static float _final_goal(Object *ob, BodyPoint *bp) /*jow_go_for2_5 */ } } CLOG_ERROR(&LOG, "sb or bp == NULL"); - return f; /*using crude but spot able values some times helps debuggin */ + return f; /* Using crude but spot able values some times helps debugging. */ } static float _final_mass(Object *ob, BodyPoint *bp) @@ -251,7 +251,7 @@ static float _final_mass(Object *ob, BodyPoint *bp) } /* helper functions for everything is animateble jow_go_for2_5 ------*/ -/*+++ collider caching and dicing +++*/ +/* +++ collider caching and dicing +++ */ /* * for each target object/face the axis aligned bounding box (AABB) is stored @@ -311,7 +311,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob) /* blow it up with forcefield ranges */ hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft); - /* alloc and copy verts*/ + /* Allocate and copy verts. */ pccd_M->mvert = MEM_dupallocN(cmd->xnew); /* note that xnew coords are already in global space, */ /* determine the ortho BB */ @@ -328,7 +328,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob) pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull); pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull); } - /* alloc and copy faces*/ + /* Allocate and copy faces. */ pccd_M->tri = MEM_dupallocN(cmd->tri); /* OBBs for idea1 */ @@ -401,7 +401,7 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M) MEM_freeN((void *)pccd_M->mprevvert); } pccd_M->mprevvert = pccd_M->mvert; - /* alloc and copy verts*/ + /* Allocate and copy verts. */ pccd_M->mvert = MEM_dupallocN(cmd->xnew); /* note that xnew coords are already in global space, */ /* determine the ortho BB */ @@ -598,7 +598,7 @@ static int count_mesh_quads(Mesh *me) static void add_mesh_quad_diag_springs(Object *ob) { Mesh *me = ob->data; - /*BodyPoint *bp;*/ /*UNUSED*/ + // BodyPoint *bp; /* UNUSED */ int a; if (ob->soft) { @@ -618,7 +618,7 @@ static void add_mesh_quad_diag_springs(Object *ob) /* fill the tail */ a = 0; bs = &ob->soft->bspring[ob->soft->totspring]; - /*bp= ob->soft->bpoint; */ /*UNUSED*/ + // bp = ob->soft->bpoint; /* UNUSED */ for (a = me->totpoly; a > 0; a--, mp++) { if (mp->totloop == 4) { bs->v1 = mloop[mp->loopstart + 0].v; @@ -640,7 +640,7 @@ static void add_mesh_quad_diag_springs(Object *ob) static void add_2nd_order_roller(Object *ob, float UNUSED(stiffness), int *counter, int addsprings) { - /*assume we have a softbody*/ + /* Assume we have a softbody. */ SoftBody *sb = ob->soft; /* is supposed to be there */ BodyPoint *bp, *bpo; BodySpring *bs, *bs2, *bs3 = NULL; @@ -654,7 +654,7 @@ static void add_2nd_order_roller(Object *ob, float UNUSED(stiffness), int *count bs3 = ob->soft->bspring + ob->soft->totspring; } for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) { - /*scan for neighborhood*/ + /* Scan for neighborhood. */ bpo = NULL; v0 = (sb->totpoint - a); for (b = bp->nofsprings; b > 0; b--) { @@ -678,7 +678,7 @@ static void add_2nd_order_roller(Object *ob, float UNUSED(stiffness), int *count for (c = bpo->nofsprings; c > 0; c--) { bs2 = sb->bspring + bpo->springs[c - 1]; if ((bs2->v1 != notthis) && (bs2->v1 > v0)) { - (*counter)++; /*hit */ + (*counter)++; /* hit */ if (addsprings) { bs3->v1 = v0; bs3->v2 = bs2->v1; @@ -698,7 +698,7 @@ static void add_2nd_order_roller(Object *ob, float UNUSED(stiffness), int *count } } } - /*scan for neighborhood done*/ + /* Scan for neighborhood done. */ } } @@ -772,8 +772,8 @@ static void build_bps_springlist(Object *ob) if (((sb->totpoint - a) == bs->v2)) { add_bp_springlist(bp, sb->totspring - b); } - } /*for springs*/ - } /*for bp*/ + } /* For springs. */ + } /* For bp. */ } static void calculate_collision_balls(Object *ob) @@ -825,7 +825,7 @@ static void calculate_collision_balls(Object *ob) else { bp->colball = 0; } - } /*for bp*/ + } /* For bp. */ } /* creates new softbody if didn't exist yet, makes new points and springs arrays */ @@ -905,7 +905,7 @@ static void free_scratch(SoftBody *sb) if (sb->scratch->colliderhash) { BLI_ghash_free(sb->scratch->colliderhash, NULL, - (GHashValFreeFP)ccd_mesh_free); /*this hoepfully will free all caches*/ + (GHashValFreeFP)ccd_mesh_free); /* This hopefully will free all caches. */ sb->scratch->colliderhash = NULL; } if (sb->scratch->bodyface) { @@ -976,7 +976,7 @@ static void free_softbody_intern(SoftBody *sb) * since that would only valid for 'slow' moving collision targets and dito particles */ -/* +++ dependency information functions*/ +/* +++ dependency information functions. */ /** * \note collection overrides scene when not NULL. @@ -990,9 +990,9 @@ static int query_external_colliders(Depsgraph *depsgraph, Collection *collection return (numobjects != 0); } -/* --- dependency information functions*/ +/* --- dependency information functions. */ -/* +++ the aabb "force" section*/ +/* +++ the aabb "force" section. */ static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), struct Object *vertexowner, float UNUSED(time)) @@ -1036,7 +1036,7 @@ static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), deflected = 2; } else { - /*aye that should be cached*/ + /* Aye that should be cached. */ CLOG_ERROR(&LOG, "missing cache error"); BLI_ghashIterator_step(ihash); continue; @@ -1048,9 +1048,9 @@ static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), BLI_ghashIterator_free(ihash); return deflected; } -/* --- the aabb section*/ +/* --- the aabb section. */ -/* +++ the face external section*/ +/* +++ the face external section. */ static int sb_detect_face_pointCached(const float face_v1[3], const float face_v2[3], const float face_v3[3], @@ -1104,13 +1104,13 @@ static int sb_detect_face_pointCached(const float face_v1[3], } } else { - /*aye that should be cached*/ + /* Aye that should be cached. */ CLOG_ERROR(&LOG, "missing cache error"); BLI_ghashIterator_step(ihash); continue; } - /* use mesh*/ + /* Use mesh. */ if (mvert) { while (a) { copy_v3_v3(nv1, mvert[a - 1].co); @@ -1118,7 +1118,7 @@ static int sb_detect_face_pointCached(const float face_v1[3], mul_v3_fl(nv1, time); madd_v3_v3fl(nv1, mprevvert[a - 1].co, 1.0f - time); } - /* origin to face_v2*/ + /* Origin to face_v2. */ sub_v3_v3(nv1, face_v2); facedist = dot_v3v3(nv1, d_nvect); if (fabsf(facedist) < outerfacethickness) { @@ -1139,7 +1139,7 @@ static int sb_detect_face_pointCached(const float face_v1[3], } } a--; - } /* while (a)*/ + } /* while (a) */ } /* if (mvert) */ } /* if (ob->pd && ob->pd->deflect) */ BLI_ghashIterator_step(ihash); @@ -1201,13 +1201,13 @@ static int sb_detect_face_collisionCached(const float face_v1[3], } } else { - /*aye that should be cached*/ + /* Aye that should be cached. */ CLOG_ERROR(&LOG, "missing cache error"); BLI_ghashIterator_step(ihash); continue; } - /* use mesh*/ + /* Use mesh. */ while (a--) { if ((aabbmax[0] < mima->minx) || (aabbmin[0] > mima->maxx) || (aabbmax[1] < mima->miny) || (aabbmin[1] > mima->maxy) || @@ -1235,7 +1235,7 @@ static int sb_detect_face_collisionCached(const float face_v1[3], } } - /* switch origin to be nv2*/ + /* Switch origin to be nv2. */ sub_v3_v3v3(edge1, nv1, nv2); sub_v3_v3v3(edge2, nv3, nv2); cross_v3_v3v3(d_nvect, edge2, edge1); @@ -1272,7 +1272,7 @@ static void scan_for_ext_face_forces(Object *ob, float timenow) bf = sb->scratch->bodyface; for (a = 0; a < sb->scratch->totface; a++, bf++) { bf->ext_force[0] = bf->ext_force[1] = bf->ext_force[2] = 0.0f; - /*+++edges intruding*/ + /*+++edges intruding. */ bf->flag &= ~BFF_INTERSECT; zero_v3(feedback); if (sb_detect_face_collisionCached(sb->bpoint[bf->v1].pos, @@ -1289,9 +1289,9 @@ static void scan_for_ext_face_forces(Object *ob, float timenow) bf->flag |= BFF_INTERSECT; choke = min_ff(max_ff(damp, choke), 1.0f); } - /*---edges intruding*/ + /*---edges intruding. */ - /*+++ close vertices*/ + /*+++ close vertices. */ if ((bf->flag & BFF_INTERSECT) == 0) { bf->flag &= ~BFF_CLOSEVERT; tune = -1.0f; @@ -1311,7 +1311,7 @@ static void scan_for_ext_face_forces(Object *ob, float timenow) choke = min_ff(max_ff(damp, choke), 1.0f); } } - /*--- close vertices*/ + /*--- close vertices. */ } bf = sb->scratch->bodyface; for (a = 0; a < sb->scratch->totface; a++, bf++) { @@ -1324,9 +1324,9 @@ static void scan_for_ext_face_forces(Object *ob, float timenow) } } -/* --- the face external section*/ +/* --- the face external section. */ -/* +++ the spring external section*/ +/* +++ the spring external section. */ static int sb_detect_edge_collisionCached(const float edge_v1[3], const float edge_v2[3], @@ -1377,13 +1377,13 @@ static int sb_detect_edge_collisionCached(const float edge_v1[3], } } else { - /*aye that should be cached*/ + /* Aye that should be cached. */ CLOG_ERROR(&LOG, "missing cache error"); BLI_ghashIterator_step(ihash); continue; } - /* use mesh*/ + /* Use mesh. */ while (a--) { if ((aabbmax[0] < mima->minx) || (aabbmin[0] > mima->maxx) || (aabbmax[1] < mima->miny) || (aabbmin[1] > mima->maxy) || @@ -1411,7 +1411,7 @@ static int sb_detect_edge_collisionCached(const float edge_v1[3], } } - /* switch origin to be nv2*/ + /* Switch origin to be nv2. */ sub_v3_v3v3(edge1, nv1, nv2); sub_v3_v3v3(edge2, nv3, nv2); @@ -1469,12 +1469,12 @@ static void _scan_for_ext_spring_forces( } /* ---- springs colliding */ - /* +++ springs seeing wind ... n stuff depending on their orientation*/ - /* note we don't use sb->mediafrict but use sb->aeroedge for magnitude of effect*/ + /* +++ springs seeing wind ... n stuff depending on their orientation. */ + /* NOTE: we don't use `sb->mediafrict` but use `sb->aeroedge` for magnitude of effect. */ if (sb->aeroedge) { float vel[3], sp[3], pr[3], force[3]; float f, windfactor = 0.25f; - /*see if we have wind*/ + /* See if we have wind. */ if (effectors) { EffectedPoint epoint; float speed[3] = {0.0f, 0.0f, 0.0f}; @@ -1543,7 +1543,7 @@ static void sb_sfesf_threads_run(struct Depsgraph *depsgraph, /* figure the number of threads while preventing pretty pointless threading overhead */ totthread = BKE_scene_num_threads(scene); - /* what if we got zillions of CPUs running but less to spread*/ + /* What if we got zillions of CPUs running but less to spread. */ while ((totsprings / totthread < lowsprings) && (totthread > 1)) { totthread--; } @@ -1590,7 +1590,7 @@ static void sb_sfesf_threads_run(struct Depsgraph *depsgraph, BKE_effectors_free(effectors); } -/* --- the spring external section*/ +/* --- the spring external section. */ static int choose_winner( float *w, float *pos, float *a, float *b, float *c, float *ca, float *cb, float *cc) @@ -1683,7 +1683,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], } } else { - /*aye that should be cached*/ + /* Aye that should be cached. */ CLOG_ERROR(&LOG, "missing cache error"); BLI_ghashIterator_step(ihash); continue; @@ -1697,7 +1697,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], fa *= fa; fa = 1.0f / fa; avel[0] = avel[1] = avel[2] = 0.0f; - /* use mesh*/ + /* Use mesh. */ while (a--) { if ((opco[0] < mima->minx) || (opco[0] > mima->maxx) || (opco[1] < mima->miny) || (opco[1] > mima->maxy) || (opco[2] < mima->minz) || (opco[2] > mima->maxz)) { @@ -1733,7 +1733,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], } } - /* switch origin to be nv2*/ + /* Switch origin to be nv2. */ sub_v3_v3v3(edge1, nv1, nv2); sub_v3_v3v3(edge2, nv3, nv2); /* Abuse dv1 to have vertex in question at *origin* of triangle. */ @@ -2068,7 +2068,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, bp->force[1] += -ks * (auxvect[1]); bp->force[2] += -ks * (auxvect[2]); - /* calculate damping forces generated by goals*/ + /* Calculate damping forces generated by goals. */ sub_v3_v3v3(velgoal, bp->origS, bp->origE); kd = sb->goalfrict * sb_fric_force_scale(ob); add_v3_v3v3(auxvect, velgoal, bp->vec); @@ -2113,7 +2113,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint - bp, &epoint); BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, NULL, speed); - /* apply forcefield*/ + /* Apply force-field. */ mul_v3_fl(force, fieldfactor * eval_sb_fric_force_scale); add_v3_v3(bp->force, force); @@ -2125,7 +2125,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, /* now we'll have nice centrifugal effect for vortex */ } else { - /* BP friction in media (not) moving*/ + /* BP friction in media (not) moving. */ float kd = sb->mediafrict * sb_fric_force_scale(ob); /* assume it to be proportional to actual velocity */ bp->force[0] -= bp->vec[0] * kd; @@ -2160,7 +2160,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, /* +++springs */ iks = 1.0f / (1.0f - sb->inspring) - 1.0f; /* inner spring constants function */ if (ob->softflag & OB_SB_EDGES) { - if (sb->bspring) { /* spring list exists at all ? */ + if (sb->bspring) { /* Spring list exists at all? */ int b; BodySpring *bs; for (b = bp->nofsprings; b > 0; b--) { @@ -2173,13 +2173,13 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, } // sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, float forcetime) sb_spring_force(ob, ilast - bb, bs, iks, forcetime); - } /* loop springs */ - } /* existing spring list */ - } /*any edges*/ + } /* loop springs. */ + } /* existing spring list. */ + } /* Any edges. */ /* ---springs */ - } /*omit on snap */ - } /*loop all bp's*/ - return 0; /*done fine*/ + } /* Omit on snap. */ + } /* Loop all bp's. */ + return 0; /* Done fine. */ } static void *exec_softbody_calc_forces(void *data) @@ -2220,7 +2220,7 @@ static void sb_cf_threads_run(Scene *scene, /* figure the number of threads while preventing pretty pointless threading overhead */ totthread = BKE_scene_num_threads(scene); - /* what if we got zillions of CPUs running but less to spread*/ + /* What if we got zillions of CPUs running but less to spread. */ while ((totpoint / totthread < lowpoints) && (totthread > 1)) { totthread--; } @@ -2275,11 +2275,11 @@ static void softbody_calc_forces( * this will ruin adaptive stepsize AKA heun! (BM) */ SoftBody *sb = ob->soft; /* is supposed to be there */ - /*BodyPoint *bproot;*/ /* UNUSED */ - /* float gravity; */ /* UNUSED */ - /* float iks; */ + // BodyPoint *bproot; /* UNUSED */ + // float gravity; /* UNUSED */ + // float iks; float fieldfactor = -1.0f, windfactor = 0.25; - int do_deflector /*, do_selfcollision*/, do_springcollision, do_aero; + int do_deflector /*, do_selfcollision */, do_springcollision, do_aero; /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */ @@ -2292,8 +2292,8 @@ static void softbody_calc_forces( (ob->softflag & OB_SB_EDGECOLL); do_aero = ((sb->aeroedge) && (ob->softflag & OB_SB_EDGES)); - /* iks = 1.0f/(1.0f-sb->inspring)-1.0f; */ /* inner spring constants function */ /* UNUSED */ - /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */ + // iks = 1.0f / (1.0f - sb->inspring) - 1.0f; /* Inner spring constants function. */ /* UNUSED */ + // bproot = sb->bpoint; /* Need this for proper spring addressing. */ /* UNUSED */ if (do_springcollision || do_aero) { sb_sfesf_threads_run(depsgraph, scene, ob, timenow, sb->totspring, NULL); @@ -2344,7 +2344,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float * aabbmin[0] = aabbmin[1] = aabbmin[2] = 1e20f; aabbmax[0] = aabbmax[1] = aabbmax[2] = -1e20f; - /* old one with homogeneous masses */ + /* old one with homogeneous masses */ /* claim a minimum mass for vertex */ #if 0 if (sb->nodemass > 0.009999f) { @@ -2489,7 +2489,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float * /* used by heun when it overshoots */ static void softbody_restore_prev_step(Object *ob) { - SoftBody *sb = ob->soft; /* is supposed to be there*/ + SoftBody *sb = ob->soft; /* is supposed to be there. */ BodyPoint *bp; int a; @@ -2502,7 +2502,7 @@ static void softbody_restore_prev_step(Object *ob) #if 0 static void softbody_store_step(Object *ob) { - SoftBody *sb = ob->soft; /* is supposed to be there*/ + SoftBody *sb = ob->soft; /* is supposed to be there. */ BodyPoint *bp; int a; @@ -2515,7 +2515,7 @@ static void softbody_store_step(Object *ob) /* used by predictors and correctors */ static void softbody_store_state(Object *ob, float *ppos, float *pvel) { - SoftBody *sb = ob->soft; /* is supposed to be there*/ + SoftBody *sb = ob->soft; /* is supposed to be there. */ BodyPoint *bp; int a; float *pp = ppos, *pv = pvel; @@ -2533,7 +2533,7 @@ static void softbody_store_state(Object *ob, float *ppos, float *pvel) /* used by predictors and correctors */ static void softbody_retrieve_state(Object *ob, float *ppos, float *pvel) { - SoftBody *sb = ob->soft; /* is supposed to be there*/ + SoftBody *sb = ob->soft; /* is supposed to be there. */ BodyPoint *bp; int a; float *pp = ppos, *pv = pvel; @@ -2551,7 +2551,7 @@ static void softbody_retrieve_state(Object *ob, float *ppos, float *pvel) /* used by predictors and correctors */ static void softbody_swap_state(Object *ob, float *ppos, float *pvel) { - SoftBody *sb = ob->soft; /* is supposed to be there*/ + SoftBody *sb = ob->soft; /* is supposed to be there. */ BodyPoint *bp; int a; float *pp = ppos, *pv = pvel; @@ -2773,7 +2773,7 @@ static void mesh_faces_to_scratch(Object *ob) MLoopTri *looptri, *lt; BodyFace *bodyface; int a; - /* alloc and copy faces*/ + /* Allocate and copy faces. */ sb->scratch->totface = poly_to_tri_count(me->totpoly, me->totloop); looptri = lt = MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__); @@ -3000,8 +3000,8 @@ static void curve_surf_to_softbody(Object *ob) bp = sb->bpoint; bs = sb->bspring; - /* weights from bpoints, same code used as for mesh vertices */ - /* if ((ob->softflag & OB_SB_GOAL) && sb->vertgroup) 2.4x hack*/ + /* Weights from bpoints, same code used as for mesh vertices. */ + /* if ((ob->softflag & OB_SB_GOAL) && sb->vertgroup) 2.4x hack. */ /* new! take the weights from curve vertex anyhow */ if (ob->softflag & OB_SB_GOAL) { setgoal = 1; @@ -3022,10 +3022,10 @@ static void curve_surf_to_softbody(Object *ob) if (setgoal) { bp->goal *= bezt->weight; - /* all three triples */ + /* All three triples. */ (bp + 1)->goal = bp->goal; (bp + 2)->goal = bp->goal; - /*do not collide handles */ + /* Do not collide handles. */ (bp + 1)->loc_flag |= SBF_OUTOFCOLLISION; (bp + 2)->loc_flag |= SBF_OUTOFCOLLISION; } @@ -3137,7 +3137,7 @@ SoftBody *sbNew(void) sb->inspring = 0.5f; sb->infrict = 0.5f; - /*todo backward file compat should copy inspring to inpush while reading old files*/ + /* TODO: backward file compat should copy `inspring` to `inpush` while reading old files. */ sb->inpush = 0.5f; sb->colball = 0.49f; @@ -3150,7 +3150,7 @@ SoftBody *sbNew(void) sb->choke = 3; sb_new_scratch(sb); - /*todo backward file compat should set sb->shearstiff = 1.0f while reading old files*/ + /* TODO: backward file compat should set `sb->shearstiff = 1.0f` while reading old files. */ sb->shearstiff = 1.0f; sb->solverflags |= SBSO_OLDERR; @@ -3205,7 +3205,7 @@ void sbObjectToSoftbody(Object *ob) free_softbody_intern(ob->soft); } -static bool object_has_edges(Object *ob) +static bool object_has_edges(const Object *ob) { if (ob->type == OB_MESH) { return ((Mesh *)ob->data)->totedge; @@ -3311,7 +3311,7 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int for (a = 0, bp = sb->bpoint; a < numVerts; a++, bp++) { copy_v3_v3(bp->pos, vertexCos[a]); - mul_m4_v3(ob->obmat, bp->pos); /* yep, sofbody is global coords*/ + mul_m4_v3(ob->obmat, bp->pos); /* Yep, soft-body is global coords. */ copy_v3_v3(bp->origS, bp->pos); copy_v3_v3(bp->origE, bp->pos); copy_v3_v3(bp->origT, bp->pos); @@ -3493,18 +3493,18 @@ static void softbody_step( else if (sb->solver_ID == 2) { /* do semi "fake" implicit euler */ /* removed */ - } /*SOLVER SELECT*/ + } /* SOLVER SELECT */ else if (sb->solver_ID == 4) { /* do semi "fake" implicit euler */ - } /*SOLVER SELECT*/ + } /* SOLVER SELECT */ else if (sb->solver_ID == 3) { /* do "stupid" semi "fake" implicit euler */ /* removed */ - } /*SOLVER SELECT*/ + } /* SOLVER SELECT */ else { CLOG_ERROR(&LOG, "softbody no valid solver ID!"); - } /*SOLVER SELECT*/ + } /* SOLVER SELECT */ if (sb->plastic) { apply_spring_memory(ob); } diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc index 85fb9730e83..76d046337c0 100644 --- a/source/blender/blenkernel/intern/spline_nurbs.cc +++ b/source/blender/blenkernel/intern/spline_nurbs.cc @@ -45,7 +45,7 @@ void NURBSpline::copy_data(Spline &dst) const nurbs.positions_ = positions_; nurbs.weights_ = weights_; nurbs.knots_ = knots_; - nurbs.knots_dirty_ = false; + nurbs.knots_dirty_ = knots_dirty_; nurbs.radii_ = radii_; nurbs.tilts_ = tilts_; } diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c index 4ca6f93b014..8b672b2cb49 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -63,7 +63,7 @@ void subdiv_ccg_average_faces_boundaries_and_corners(SubdivCCG *subdiv_ccg, /** \name Generally useful internal helpers * \{ */ -/* Number of floats in per-vertex elements. */ +/* Number of floats in per-vertex elements. */ static int num_element_float_get(const SubdivCCG *subdiv_ccg) { /* We always have 3 floats for coordinate. */ @@ -1116,7 +1116,7 @@ typedef struct AverageGridsCornerData { SubdivCCG *subdiv_ccg; CCGKey *key; - /* Optional lookup table. Maps task range index to index in subdiv_ccg->adjacent_vertices*/ + /* Optional lookup table. Maps task range index to index in `subdiv_ccg->adjacent_vertices`. */ const int *adjacent_vert_index_map; } AverageGridsCornerData; @@ -1489,7 +1489,7 @@ BLI_INLINE SubdivCCGCoord coord_at_next_col(const SubdivCCG *subdiv_ccg, return result; } -/* For the input coordinate which is at the boundary of the grid do one step inside. */ +/* For the input coordinate which is at the boundary of the grid do one step inside. */ static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord) diff --git a/source/blender/blenkernel/intern/subdiv_eval.c b/source/blender/blenkernel/intern/subdiv_eval.c index 201d308e096..693827f99ac 100644 --- a/source/blender/blenkernel/intern/subdiv_eval.c +++ b/source/blender/blenkernel/intern/subdiv_eval.c @@ -282,7 +282,7 @@ static void buffer_apply_offset(void **buffer, const int offset) *buffer = ((unsigned char *)*buffer) + offset; } -/* Write given number of floats to the beginning of given buffer. */ +/* Write given number of floats to the beginning of given buffer. */ static void buffer_write_float_value(void **buffer, const float *values_buffer, int num_values) { memcpy(*buffer, values_buffer, sizeof(float) * num_values); diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c index 4400e9c976f..061c196df2a 100644 --- a/source/blender/blenkernel/intern/subdiv_foreach.c +++ b/source/blender/blenkernel/intern/subdiv_foreach.c @@ -1749,7 +1749,7 @@ static void subdiv_foreach_vertices_of_loose_edges_task(void *__restrict userdat /* Subdivision vertices which corresponds to edge's v1 and v2. */ const int subdiv_v1_index = ctx->vertices_corner_offset + coarse_edge->v1; const int subdiv_v2_index = ctx->vertices_corner_offset + coarse_edge->v2; - /* First subdivided inner vertex of the edge. */ + /* First subdivided inner vertex of the edge. */ const int subdiv_start_vertex = ctx->vertices_edge_offset + coarse_edge_index * num_subdiv_vertices_per_coarse_edge; /* Perform interpolation. */ diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 23eccbfba9b..0dbfeaaaadb 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -580,16 +580,16 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss, #endif MVert *mvert = dm->getVertArray(dm); MEdge *medge = dm->getEdgeArray(dm); - /* MFace *mface = dm->getTessFaceArray(dm); */ /* UNUSED */ + // MFace *mface = dm->getTessFaceArray(dm); /* UNUSED */ MVert *mv; MEdge *me; MLoop *mloop = dm->getLoopArray(dm), *ml; MPoly *mpoly = dm->getPolyArray(dm), *mp; - /*MFace *mf;*/ /*UNUSED*/ + // MFace *mf; /* UNUSED */ int totvert = dm->getNumVerts(dm); int totedge = dm->getNumEdges(dm); - /*int totface = dm->getNumTessFaces(dm);*/ /*UNUSED*/ - /*int totpoly = dm->getNumFaces(dm);*/ /*UNUSED*/ + // int totface = dm->getNumTessFaces(dm); /* UNUSED */ + // int totpoly = dm->getNumFaces(dm); /* UNUSED */ int i, j; int *index; @@ -641,10 +641,10 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss, fVerts[j] = POINTER_FROM_UINT(ml->v); } - /* this is very bad, means mesh is internally inconsistent. + /* This is very bad, means mesh is internally inconsistent. * it is not really possible to continue without modifying * other parts of code significantly to handle missing faces. - * since this really shouldn't even be possible we just bail.*/ + * since this really shouldn't even be possible we just bail. */ if (ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), mp->totloop, fVerts, &f) == eCCGError_InvalidValue) { static int hasGivenError = 0; @@ -1008,11 +1008,11 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) int gridFaces = gridSideEdges * gridSideEdges; int i; CCGFace *f; - /*int numVerts;*/ + // int numVerts; int offset; int grid; int x, y; - /*int lastface = ccgSubSurf_getNumFaces(ss) - 1;*/ /*UNUSED*/ + // int lastface = ccgSubSurf_getNumFaces(ss) - 1; /* UNUSED */ DMFlagMat *faceFlags = ccgdm->faceFlags; memset(mf, 0, sizeof(*mf)); @@ -1023,7 +1023,7 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) i = ccgdm->reverseFaceMap[faceNum]; f = ccgdm->faceMap[i].face; - /*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/ + // numVerts = ccgSubSurf_getFaceNumVerts(f); /* UNUSED */ offset = faceNum - ccgdm->faceMap[i].startFace; grid = offset / gridFaces; @@ -1781,7 +1781,7 @@ static void ccgdm_create_grids(DerivedMesh *dm) numGrids = ccgDM_getNumGrids(dm); numFaces = ccgSubSurf_getNumFaces(ss); - /*gridSize = ccgDM_getGridSize(dm);*/ /*UNUSED*/ + // gridSize = ccgDM_getGridSize(dm); /* UNUSED */ /* compute offset into grid array for each face */ gridOffset = MEM_mallocN(sizeof(int) * numFaces, "ccgdm.gridOffset"); @@ -2089,7 +2089,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm, vertidx[s] = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(v)); } - /*I think this is for interpolating the center vert?*/ + /* I think this is for interpolating the center vert? */ w2 = w; // + numVerts*(g2_wid-1) * (g2_wid-1); //numVerts*((g2_wid-1) * g2_wid+g2_wid-1); DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2, numVerts, vertNum); if (vertOrigIndex) { @@ -2099,7 +2099,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm, vertNum++; - /*interpolate per-vert data*/ + /* Interpolate per-vert data. */ for (s = 0; s < numVerts; s++) { for (x = 1; x < gridFaces; x++) { w2 = w + s * numVerts * g2_wid * g2_wid + x * numVerts; @@ -2114,7 +2114,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm, } } - /*interpolate per-vert data*/ + /* Interpolate per-vert data. */ for (s = 0; s < numVerts; s++) { for (y = 1; y < gridFaces; y++) { for (x = 1; x < gridFaces; x++) { @@ -2138,7 +2138,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm, } for (s = 0; s < numVerts; s++) { - /*interpolate per-face data*/ + /* Interpolate per-face data. */ for (y = 0; y < gridFaces; y++) { for (x = 0; x < gridFaces; x++) { w2 = w + s * numVerts * g2_wid * g2_wid + (y * g2_wid + x) * numVerts; @@ -2161,10 +2161,10 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm, &dm->loopData, &ccgdm->dm.loopData, loopidx, w2, NULL, numVerts, loopindex2); loopindex2++; - /*copy over poly data, e.g. mtexpoly*/ + /* Copy over poly data, e.g. mtexpoly. */ CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1); - /*set original index data*/ + /* Set original index data. */ if (faceOrigIndex) { /* reference the index in 'polyOrigIndex' */ *faceOrigIndex = faceNum; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 27f5593c2ca..74845e3f1b9 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -781,12 +781,12 @@ static void txt_curs_sel(Text *text, TextLine ***linep, int **charp) *charp = &text->selc; } -bool txt_cursor_is_line_start(Text *text) +bool txt_cursor_is_line_start(const Text *text) { return (text->selc == 0); } -bool txt_cursor_is_line_end(Text *text) +bool txt_cursor_is_line_end(const Text *text) { return (text->selc == text->sell->len); } @@ -1239,7 +1239,7 @@ void txt_order_cursors(Text *text, const bool reverse) } } -bool txt_has_sel(Text *text) +bool txt_has_sel(const Text *text) { return ((text->curl != text->sell) || (text->curc != text->selc)); } diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index 46589a578a8..3dff750edfb 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -1381,7 +1381,7 @@ ImBuf *BKE_tracking_stabilize_frame( return ibuf; } - /* Allocate frame for stabilization result, copy alpha mode and colorspace. */ + /* Allocate frame for stabilization result, copy alpha mode and colorspace. */ ibuf_flags = 0; if (ibuf->rect) { ibuf_flags |= IB_rect; diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index 377802f1af7..14dd286a315 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -368,10 +368,10 @@ void BKE_undosys_stack_init_from_context(UndoStack *ustack, bContext *C) } /* name optional */ -bool BKE_undosys_stack_has_undo(UndoStack *ustack, const char *name) +bool BKE_undosys_stack_has_undo(const UndoStack *ustack, const char *name) { if (name) { - UndoStep *us = BLI_rfindstring(&ustack->steps, name, offsetof(UndoStep, name)); + const UndoStep *us = BLI_rfindstring(&ustack->steps, name, offsetof(UndoStep, name)); return us && us->prev; } diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index c2fb5ef4238..290b880934e 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -744,10 +744,10 @@ static const char *unit_find_str(const char *str, const char *substr, bool case_ * * "1m1cm+2mm" - Original value. * "1*1#1*0.01#+2*0.001#" - Replace numbers. - * "1*1+1*0.01 +2*0.001 " - Add add signs if ( + - * / | & ~ < > ^ ! = % ) not found in between. + * "1*1+1*0.01 +2*0.001 " - Add plus signs if ( + - * / | & ~ < > ^ ! = % ) not found in between. */ -/* Not too strict, (+ - * /) are most common. */ +/* Not too strict, (+ - * /) are most common. */ static bool ch_is_op(char op) { switch (op) { @@ -917,7 +917,7 @@ static int unit_scale_str(char *str, return 0; } - /* XXX - investigate, does not respect len_max properly. */ + /* XXX - investigate, does not respect len_max properly. */ char *str_found = (char *)unit_find_str(str, replace_str, case_sensitive); if (str_found == NULL) { diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 5fc55aad6a2..272ecc71833 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -1224,7 +1224,7 @@ const VolumeGrid *BKE_volume_grid_active_get_for_read(const Volume *volume) return BKE_volume_grid_get_for_read(volume, index); } -/* Tries to find a grid with the given name. Make sure that that the volume has been loaded. */ +/* Tries to find a grid with the given name. Make sure that the volume has been loaded. */ const VolumeGrid *BKE_volume_grid_find_for_read(const Volume *volume, const char *name) { int num_grids = BKE_volume_num_grids(volume); diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index be67b2370e3..533107b2bf6 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -105,8 +105,8 @@ static void workspace_blend_read_data(BlendDataReader *reader, ID *id) BLO_read_list(reader, &workspace->tools); LISTBASE_FOREACH (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) { - /* parent pointer does not belong to workspace data and is therefore restored in lib_link step - * of window manager.*/ + /* Parent pointer does not belong to workspace data and is therefore restored in lib_link step + * of window manager. */ BLO_read_data_address(reader, &relation->value); } diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index 71b5a74ddf7..3e13ba602a4 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -39,13 +39,13 @@ struct AnimationEvalContext; typedef struct NlaEvalStrip { struct NlaEvalStrip *next, *prev; - NlaTrack *track; /* track that this strip belongs to */ - NlaStrip *strip; /* strip that's being used */ + NlaTrack *track; /* Track that this strip belongs to. */ + NlaStrip *strip; /* Strip that's being used. */ - short track_index; /* the index of the track within the list */ - short strip_mode; /* which end of the strip are we looking at */ + short track_index; /* The index of the track within the list. */ + short strip_mode; /* Which end of the strip are we looking at. */ - float strip_time; /* time at which which strip is being evaluated */ + float strip_time; /* Time at which this strip is being evaluated. */ } NlaEvalStrip; /* NlaEvalStrip->strip_mode */ |