diff options
Diffstat (limited to 'source/blender/blenkernel')
68 files changed, 3145 insertions, 1770 deletions
diff --git a/source/blender/blenkernel/BKE_addon.h b/source/blender/blenkernel/BKE_addon.h new file mode 100644 index 00000000000..eafaec3e605 --- /dev/null +++ b/source/blender/blenkernel/BKE_addon.h @@ -0,0 +1,42 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BKE_ADDON_H__ +#define __BKE_ADDON_H__ + +#include "RNA_types.h" + +typedef struct bAddonPrefType { + /* type info */ + char idname[64]; // best keep the same size as BKE_ST_MAXNAME + + /* RNA integration */ + ExtensionRNA ext; +} bAddonPrefType; + +bAddonPrefType *BKE_addon_pref_type_find(const char *idname, int quiet); +void BKE_addon_pref_type_add(bAddonPrefType *apt); +void BKE_addon_pref_type_remove(bAddonPrefType *apt); + +void BKE_addon_pref_type_init(void); +void BKE_addon_pref_type_free(void); + +#endif /* __BKE_ADDON_H__ */ diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 11759a82e60..10528f1b270 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 265 -#define BLENDER_SUBVERSION 3 +#define BLENDER_SUBVERSION 5 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index cbffb6c0cea..248fe9c8968 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -99,6 +99,7 @@ float BKE_brush_unprojected_radius_get(const struct Scene *scene, struct Brush * void BKE_brush_unprojected_radius_set(struct Scene *scene, struct Brush *brush, float value); float BKE_brush_alpha_get(const struct Scene *scene, struct Brush *brush); +void BKE_brush_alpha_set(Scene *scene, struct Brush *brush, float alpha); float BKE_brush_weight_get(const Scene *scene, struct Brush *brush); void BKE_brush_weight_set(const Scene *scene, struct Brush *brush, float value); diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 79e75127763..c79dc62bb61 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -108,8 +108,8 @@ typedef struct bConstraintTypeInfo { } bConstraintTypeInfo; /* Function Prototypes for bConstraintTypeInfo's */ -bConstraintTypeInfo *constraint_get_typeinfo(struct bConstraint *con); -bConstraintTypeInfo *get_constraint_typeinfo(int type); +bConstraintTypeInfo *BKE_constraint_get_typeinfo(struct bConstraint *con); +bConstraintTypeInfo *BKE_get_constraint_typeinfo(int type); /* ---------------------------------------------------------------------------- */ /* Useful macros for testing various common flag combinations */ @@ -120,38 +120,38 @@ bConstraintTypeInfo *get_constraint_typeinfo(int type); /* ---------------------------------------------------------------------------- */ /* Constraint function prototypes */ -void unique_constraint_name(struct bConstraint *con, struct ListBase *list); +void BKE_unique_constraint_name(struct bConstraint *con, struct ListBase *list); -void free_constraints(struct ListBase *list); -void copy_constraints(struct ListBase *dst, const struct ListBase *src, int do_extern); -void relink_constraints(struct ListBase *list); -void id_loop_constraints(struct ListBase *list, ConstraintIDFunc func, void *userdata); -void free_constraint_data(struct bConstraint *con); +void BKE_free_constraints(struct ListBase *list); +void BKE_copy_constraints(struct ListBase *dst, const struct ListBase *src, int do_extern); +void BKE_relink_constraints(struct ListBase *list); +void BKE_id_loop_constraints(struct ListBase *list, ConstraintIDFunc func, void *userdata); +void BKE_free_constraint_data(struct bConstraint *con); /* Constraint API function prototypes */ -struct bConstraint *constraints_get_active(struct ListBase *list); -void constraints_set_active(ListBase *list, struct bConstraint *con); -struct bConstraint *constraints_findByName(struct ListBase *list, const char *name); - -struct bConstraint *add_ob_constraint(struct Object *ob, const char *name, short type); -struct bConstraint *add_pose_constraint(struct Object *ob, struct bPoseChannel *pchan, const char *name, short type); +struct bConstraint *BKE_constraints_get_active(struct ListBase *list); +void BKE_constraints_set_active(ListBase *list, struct bConstraint *con); +struct bConstraint *BKE_constraints_findByName(struct ListBase *list, const char *name); + +struct bConstraint *BKE_add_ob_constraint(struct Object *ob, const char *name, short type); +struct bConstraint *BKE_add_pose_constraint(struct Object *ob, struct bPoseChannel *pchan, const char *name, short type); -int remove_constraint(ListBase *list, struct bConstraint *con); -void remove_constraints_type(ListBase *list, short type, short last_only); +int BKE_remove_constraint(ListBase *list, struct bConstraint *con); +void BKE_remove_constraints_type(ListBase *list, short type, short last_only); /* Constraints + Proxies function prototypes */ -void extract_proxylocal_constraints(struct ListBase *dst, struct ListBase *src); -short proxylocked_constraints_owner(struct Object *ob, struct bPoseChannel *pchan); +void BKE_extract_proxylocal_constraints(struct ListBase *dst, struct ListBase *src); +short BKE_proxylocked_constraints_owner(struct Object *ob, struct bPoseChannel *pchan); /* Constraint Evaluation function prototypes */ -struct bConstraintOb *constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype); -void constraints_clear_evalob(struct bConstraintOb *cob); +struct bConstraintOb *BKE_constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype); +void BKE_constraints_clear_evalob(struct bConstraintOb *cob); -void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to); +void BKE_constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to); -void get_constraint_target_matrix(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime); -void get_constraint_targets_for_solving(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime); -void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime); +void BKE_get_constraint_target_matrix(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime); +void BKE_get_constraint_targets_for_solving(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime); +void BKE_solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 8306da71432..ab27421b383 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -56,6 +56,9 @@ void defvert_remove_group(struct MDeformVert *dvert, struct void defvert_clear(struct MDeformVert *dvert); int defvert_find_shared(const struct MDeformVert *dvert_a, const struct MDeformVert *dvert_b); +void BKE_defvert_array_free(struct MDeformVert *dvert, int totvert); +void BKE_defvert_array_copy(struct MDeformVert *dst, const struct MDeformVert *src, int totvert); + float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup); float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup); diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 758a2a8a2e8..6b986cdceda 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -83,7 +83,7 @@ void BKE_displist_elem_free(DispList *dl); DispList *BKE_displist_find_or_create(struct ListBase *lb, int type); DispList *BKE_displist_find(struct ListBase *lb, int type); void BKE_displist_normals_add(struct ListBase *lb); -void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface); +void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface, int *tottri); void BKE_displist_free(struct ListBase *lb); int BKE_displist_has_faces(struct ListBase *lb); diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index a9f6a61a655..ad3e4bb2251 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -315,6 +315,8 @@ __attribute__((nonnull)) * the actual struct IDProperty struct either.*/ void IDP_FreeProperty(struct IDProperty *prop); +void IDP_ClearProperty(IDProperty *prop); + /** Unlinks any struct IDProperty<->ID linkage that might be going on.*/ void IDP_UnlinkProperty(struct IDProperty *prop); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 1f9630d9fce..499609932d1 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -60,8 +60,10 @@ int BKE_imbuf_alpha_test(struct ImBuf *ibuf); int BKE_imbuf_write_stamp(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf); int BKE_imbuf_write(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf); int BKE_imbuf_write_as(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf, const short is_copy); -void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short use_frames); -int BKE_add_image_extension(char *string, const char imtype); +void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const struct ImageFormatData *im_format, const short use_ext, const short use_frames); +void BKE_makepicstring_from_type(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short use_frames); +int BKE_add_image_extension(char *string, const struct ImageFormatData *im_format); +int BKE_add_image_extension_from_type(char *string, const char imtype); char BKE_ftype_to_imtype(const int ftype); int BKE_imtype_to_ftype(const char imtype); diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index d7d75b4c4c9..a159cbb13d4 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -59,7 +59,7 @@ void key_curve_position_weights(float t, float data[4], int type); void key_curve_tangent_weights(float t, float data[4], int type); void key_curve_normal_weights(float t, float data[4], int type); -float *do_ob_key(struct Scene *scene, struct Object *ob); +float *BKE_key_evaluate_object(struct Scene *scene, struct Object *ob, int *r_totelem); struct Key *BKE_key_from_object(struct Object *ob); struct KeyBlock *BKE_keyblock_from_object(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 320ced67a2f..db9f1228f76 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -162,8 +162,6 @@ void BKE_mesh_from_nurbs(struct Object *ob); void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase, int **orco_index_ptr); void BKE_mesh_from_curve(struct Scene *scene, struct Object *ob); -void free_dverts(struct MDeformVert *dvert, int totvert); -void copy_dverts(struct MDeformVert *dst, const struct MDeformVert *src, int totvert); void BKE_mesh_delete_material_index(struct Mesh *me, short index); void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth); void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b8f168cbdea..0a2f757b38e 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -557,6 +557,7 @@ struct ShadeResult; #define SH_NODE_BSDF_REFRACTION 173 #define SH_NODE_TANGENT 174 #define SH_NODE_NORMAL_MAP 175 +#define SH_NODE_HAIR_INFO 176 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h index 603cb1f22a6..9dcbb41c7dc 100644 --- a/source/blender/blenkernel/BKE_packedFile.h +++ b/source/blender/blenkernel/BKE_packedFile.h @@ -48,6 +48,7 @@ struct PackedFile *newPackedFile(struct ReportList *reports, const char *filenam struct PackedFile *newPackedFileMemory(void *mem, int memlen); void packAll(struct Main *bmain, struct ReportList *reports); +void packLibraries(struct Main *bmain, struct ReportList *reports); /* unpack */ char *unpackFile(struct ReportList *reports, const char *abs_name, const char *local_name, struct PackedFile *pf, int how); @@ -55,6 +56,7 @@ int unpackVFont(struct ReportList *reports, struct VFont *vfont, int how); int unpackSound(struct Main *bmain, struct ReportList *reports, struct bSound *sound, int how); int unpackImage(struct ReportList *reports, struct Image *ima, int how); void unpackAll(struct Main *bmain, struct ReportList *reports, int how); +int unpackLibraries(struct Main *bmain, struct ReportList *reports); int writePackedFile(struct ReportList *reports, const char *filename, struct PackedFile *pf, int guimode); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index c452c177143..0a4a7f75e25 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -33,6 +33,7 @@ */ struct bContext; +struct BMesh; struct Brush; struct MDisps; struct MeshElemMap; @@ -92,6 +93,12 @@ typedef struct SculptSession { /* Mesh connectivity */ const struct MeshElemMap *pmap; + /* BMesh for dynamic topology sculpting */ + struct BMesh *bm; + int bm_smooth_shading; + /* Undo/redo log for dynamic topology sculpting */ + struct BMLog *bm_log; + /* PBVH acceleration structure */ struct PBVH *pbvh; int show_diffuse_color; @@ -121,5 +128,6 @@ typedef struct SculptSession { void free_sculptsession(struct Object *ob); void free_sculptsession_deformMats(struct SculptSession *ss); +void sculptsession_bm_to_me(struct Object *ob, int reorder); #endif diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 302de593963..709db7e4570 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -18,8 +18,8 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifndef __BLI_PBVH_H__ -#define __BLI_PBVH_H__ +#ifndef __BKE_PBVH_H__ +#define __BKE_PBVH_H__ /** \file BKE_pbvh.h * \ingroup bke @@ -27,13 +27,18 @@ */ #include "BLI_bitmap.h" +#include "BLI_ghash.h" +#include "BLI_utildefines.h" + +/* Needed for BMesh functions used in the PBVH iterator macro */ +#include "bmesh.h" struct CCGElem; struct CCGKey; struct CustomData; struct DMFlagMat; struct DMGridAdjacency; -struct ListBase; +struct GHash; struct MFace; struct MVert; struct PBVH; @@ -49,32 +54,35 @@ typedef struct { /* Callbacks */ /* returns 1 if the search should continue from this node, 0 otherwise */ -typedef int (*BLI_pbvh_SearchCallback)(PBVHNode *node, void *data); +typedef int (*BKE_pbvh_SearchCallback)(PBVHNode *node, void *data); -typedef void (*BLI_pbvh_HitCallback)(PBVHNode *node, void *data); -typedef void (*BLI_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *tmin); +typedef void (*BKE_pbvh_HitCallback)(PBVHNode *node, void *data); +typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *tmin); /* Building */ -PBVH *BLI_pbvh_new(void); -void BLI_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert *verts, +PBVH *BKE_pbvh_new(void); +void BKE_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert *verts, int totface, int totvert, struct CustomData *vdata); -void BLI_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems, +void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems, struct DMGridAdjacency *gridadj, int totgrid, struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats, unsigned int **grid_hidden); -void BLI_pbvh_free(PBVH *bvh); +void BKE_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, int smooth_shading, + struct BMLog *log); + +void BKE_pbvh_free(PBVH *bvh); /* Hierarchical Search in the BVH, two methods: * - for each hit calling a callback * - gather nodes in an array (easy to multithread) */ -void BLI_pbvh_search_callback(PBVH *bvh, - BLI_pbvh_SearchCallback scb, void *search_data, - BLI_pbvh_HitCallback hcb, void *hit_data); +void BKE_pbvh_search_callback(PBVH *bvh, + BKE_pbvh_SearchCallback scb, void *search_data, + BKE_pbvh_HitCallback hcb, void *hit_data); -void BLI_pbvh_search_gather(PBVH *bvh, - BLI_pbvh_SearchCallback scb, void *search_data, +void BKE_pbvh_search_gather(PBVH *bvh, + BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot); /* Raycast @@ -82,33 +90,45 @@ void BLI_pbvh_search_gather(PBVH *bvh, * it's up to the callback to find the primitive within the leaves that is * hit first */ -void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data, +void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data, const float ray_start[3], const float ray_normal[3], int original); -int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], +int BKE_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco, const float ray_start[3], const float ray_normal[3], float *dist); /* Drawing */ -void BLI_pbvh_node_draw(PBVHNode *node, void *data); -void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], - int (*setMaterial)(int, void *attribs)); +void BKE_pbvh_node_draw(PBVHNode *node, void *data); +void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], + int (*setMaterial)(int, void *attribs), int wireframe); /* PBVH Access */ typedef enum { PBVH_FACES, PBVH_GRIDS, + PBVH_BMESH } PBVHType; -PBVHType BLI_pbvh_type(const PBVH *bvh); +PBVHType BKE_pbvh_type(const PBVH *bvh); /* multires hidden data, only valid for type == PBVH_GRIDS */ -unsigned int **BLI_pbvh_grid_hidden(const PBVH *bvh); +unsigned int **BKE_pbvh_grid_hidden(const PBVH *bvh); /* multires level, only valid for type == PBVH_GRIDS */ -void BLI_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key); +void BKE_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key); + +/* Only valid for type == PBVH_BMESH */ +BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh); +void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size); + +typedef enum { + PBVH_Subdivide = 1, + PBVH_Collapse = 2, +} PBVHTopologyUpdateMode; +int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, + const float center[3], float radius); /* Node Access */ @@ -122,45 +142,60 @@ typedef enum { PBVH_UpdateRedraw = 32, PBVH_RebuildDrawBuffers = 64, - PBVH_FullyHidden = 128 + PBVH_FullyHidden = 128, + + PBVH_UpdateTopology = 256, } PBVHNodeFlags; -void BLI_pbvh_node_mark_update(PBVHNode *node); -void BLI_pbvh_node_mark_rebuild_draw(PBVHNode *node); -void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden); +void BKE_pbvh_node_mark_update(PBVHNode *node); +void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node); +void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden); +void BKE_pbvh_node_mark_topology_update(PBVHNode *node); -void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, +void BKE_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int *totgrid, int *maxgrid, int *gridsize, struct CCGElem ***grid_elems, struct DMGridAdjacency **gridadj); -void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, +void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *totvert); -void BLI_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, +void BKE_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, int **vert_indices, struct MVert **verts); -void BLI_pbvh_node_get_BB(PBVHNode * node, float bb_min[3], float bb_max[3]); -void BLI_pbvh_node_get_original_BB(PBVHNode * node, float bb_min[3], float bb_max[3]); +void BKE_pbvh_node_get_BB(PBVHNode * node, float bb_min[3], float bb_max[3]); +void BKE_pbvh_node_get_original_BB(PBVHNode * node, float bb_min[3], float bb_max[3]); -float BLI_pbvh_node_get_tmin(PBVHNode *node); +float BKE_pbvh_node_get_tmin(PBVHNode *node); /* test if AABB is at least partially inside the planes' volume */ -int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data); +int BKE_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data); /* test if AABB is at least partially outside the planes' volume */ -int BLI_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data); +int BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data); + +struct GHash *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node); +struct GHash *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node); +void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node); +void BKE_pbvh_bmesh_after_stroke(PBVH *bvh); /* Update Normals/Bounding Box/Draw Buffers/Redraw and clear flags */ -void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]); -void BLI_pbvh_redraw_BB(PBVH * bvh, float bb_min[3], float bb_max[3]); -void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface); -void BLI_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems, +void BKE_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]); +void BKE_pbvh_redraw_BB(PBVH * bvh, float bb_min[3], float bb_max[3]); +void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface); +void BKE_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems, struct DMGridAdjacency *gridadj, void **gridfaces, struct DMFlagMat *flagmats, unsigned int **grid_hidden); -/* vertex deformer */ -float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3]; -void BLI_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3]); -int BLI_pbvh_isDeformed(struct PBVH *pbvh); +/* Layer displacement */ + +/* Get the node's displacement layer, creating it if necessary */ +float *BKE_pbvh_node_layer_disp_get(PBVH *pbvh, PBVHNode *node); +/* If the node has a displacement layer, free it and set to null */ +void BKE_pbvh_node_layer_disp_free(PBVHNode *node); + +/* vertex deformer */ +float (*BKE_pbvh_get_vertCos(struct PBVH *pbvh))[3]; +void BKE_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3]); +int BKE_pbvh_isDeformed(struct PBVH *pbvh); /* Vertex Iterator */ @@ -197,9 +232,15 @@ typedef struct PBVHVertexIter { int *vert_indices; float *vmask; + /* bmesh */ + struct GHashIterator bm_unique_verts; + struct GHashIterator bm_other_verts; + struct CustomData *bm_vdata; + /* result: these are all computed in the macro, but we assume * that compiler optimization's will skip the ones we don't use */ struct MVert *mvert; + struct BMVert *bm_vert; float *co; short *no; float *fno; @@ -213,7 +254,7 @@ typedef struct PBVHVertexIter { void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mode); -#define BLI_pbvh_vertex_iter_begin(bvh, node, vi, mode) \ +#define BKE_pbvh_vertex_iter_begin(bvh, node, vi, mode) \ pbvh_vertex_iter_init(bvh, node, &vi, mode); \ \ for (vi.i = 0, vi.g = 0; vi.g < vi.totgrid; vi.g++) { \ @@ -241,7 +282,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, continue; \ } \ } \ - else { \ + else if (vi.mverts) { \ vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \ if (mode == PBVH_ITER_UNIQUE && vi.mvert->flag & ME_HIDE) \ continue; \ @@ -250,21 +291,39 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, if (vi.vmask) \ vi.mask = &vi.vmask[vi.vert_indices[vi.gx]]; \ } \ - -#define BLI_pbvh_vertex_iter_end \ + else { \ + if (!BLI_ghashIterator_isDone(&vi.bm_unique_verts)) {\ + vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_unique_verts); \ + BLI_ghashIterator_step(&vi.bm_unique_verts); \ + } \ + else { \ + vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_other_verts); \ + BLI_ghashIterator_step(&vi.bm_other_verts); \ + } \ + if (mode == PBVH_ITER_UNIQUE && \ + BM_elem_flag_test(vi.bm_vert, BM_ELEM_HIDDEN)) \ + continue; \ + vi.co = vi.bm_vert->co; \ + vi.fno = vi.bm_vert->no; \ + vi.mask = CustomData_bmesh_get(vi.bm_vdata, \ + vi.bm_vert->head.data, \ + CD_PAINT_MASK); \ + } + +#define BKE_pbvh_vertex_iter_end \ } \ } \ } -void BLI_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count); -void BLI_pbvh_node_free_proxies(PBVHNode *node); -PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node); -void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes, int *totnode); +void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count); +void BKE_pbvh_node_free_proxies(PBVHNode *node); +PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node); +void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes, int *totnode); -//void BLI_pbvh_node_BB_reset(PBVHNode *node); -//void BLI_pbvh_node_BB_expand(PBVHNode *node, float co[3]); +//void BKE_pbvh_node_BB_reset(PBVHNode *node); +//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]); void pbvh_show_diffuse_color_set(PBVH *bvh, int show_diffuse_color); -#endif /* __BLI_PBVH_H__ */ +#endif /* __BKE_PBVH_H__ */ diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 8aa08beec57..3c6f886b59a 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -46,6 +46,7 @@ struct bContext; struct bContextDataResult; struct bScreen; struct uiLayout; +struct uiList; struct uiMenuItem; struct wmKeyConfig; struct wmNotifier; @@ -181,6 +182,23 @@ typedef struct PanelType { ExtensionRNA ext; } PanelType; +/* uilist types */ + +/* draw an item in the uiList */ +typedef void (*uiListDrawItemFunc)(struct uiList *, struct bContext *, struct uiLayout *, struct PointerRNA *, + struct PointerRNA *, int, struct PointerRNA *, const char *, int); + +typedef struct uiListType { + struct uiListType *next, *prev; + + char idname[BKE_ST_MAXNAME]; /* unique name */ + + uiListDrawItemFunc draw_item; + + /* RNA integration */ + ExtensionRNA ext; +} uiListType; + /* header types */ typedef struct HeaderType { diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index d1332ba937e..61d82e6c604 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -121,7 +121,8 @@ typedef struct ShrinkwrapCalcData { } ShrinkwrapCalcData; -void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts); +void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, + float (*vertexCos)[3], int numVerts); /* * This function casts a ray in the given BVHTree.. but it takes into consideration the space_transform, that is: @@ -130,9 +131,12 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object * then the input (vert, dir, BVHTreeRayHit) must be defined in ob1 coordinates space * and the BVHTree must be built in ob2 coordinate space. * - * Thus it provides an easy way to cast the same ray across several trees (where each tree was built on its own coords space) + * Thus it provides an easy way to cast the same ray across several trees + * (where each tree was built on its own coords space) */ -int normal_projection_project_vertex(char options, const float *vert, const float *dir, const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); +int normal_projection_project_vertex(char options, const float vert[3], const float dir[3], + const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, void *userdata); /* * NULL initializers to local data @@ -142,6 +146,4 @@ int normal_projection_project_vertex(char options, const float *vert, const floa #define NULL_BVHTreeRayHit {NULL, } #define NULL_BVHTreeNearest {0, } - -#endif - +#endif /* __BKE_SHRINKWRAP_H__ */ diff --git a/source/blender/blenkernel/BKE_suggestions.h b/source/blender/blenkernel/BKE_suggestions.h index 9b61d9141fb..c36a2d61968 100644 --- a/source/blender/blenkernel/BKE_suggestions.h +++ b/source/blender/blenkernel/BKE_suggestions.h @@ -75,7 +75,7 @@ short texttool_text_is_active(Text *text); /* Suggestions */ void texttool_suggest_add(const char *name, char type); -void texttool_suggest_prefix(const char *prefix); +void texttool_suggest_prefix(const char *prefix, const int prefix_len); void texttool_suggest_clear(void); SuggItem *texttool_suggest_first(void); SuggItem *texttool_suggest_last(void); diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index accac8694a9..1e3dd426efa 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -106,6 +106,7 @@ int text_check_delim(const char ch); int text_check_digit(const char ch); int text_check_identifier(const char ch); int text_check_whitespace(const char ch); +int text_find_identifier_start(const char *str, int i); enum { TXT_MOVE_LINE_UP = -1, diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 7a11bdb1f39..23f23acad6b 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -58,6 +58,7 @@ set(SRC intern/CCGSubSurf.c intern/DerivedMesh.c intern/action.c + intern/addon.c intern/anim.c intern/anim_sys.c intern/armature.c @@ -123,6 +124,7 @@ set(SRC intern/particle.c intern/particle_system.c intern/pbvh.c + intern/pbvh_bmesh.c intern/pointcache.c intern/property.c intern/report.c @@ -152,6 +154,7 @@ set(SRC BKE_DerivedMesh.h BKE_action.h + BKE_addon.h BKE_anim.h BKE_animsys.h BKE_armature.h @@ -242,6 +245,7 @@ set(SRC depsgraph_private.h nla_private.h intern/CCGSubSurf.h + intern/pbvh_intern.h ) add_definitions(-DGLEW_STATIC) @@ -255,7 +259,7 @@ endif() if(WITH_BULLET) list(APPEND INC_SYS - ../../../extern/bullet2/src + ${BULLET_INCLUDE_DIRS} ) add_definitions(-DUSE_BULLET) endif() diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 2dc01513149..ec8d37e1ae3 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1340,6 +1340,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); int has_multires = mmd != NULL, multires_applied = 0; int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt; + int sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm); const int draw_flag = ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) | (scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0)); @@ -1407,7 +1408,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos if (!modifier_isEnabled(scene, md, required_mode)) continue; if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; - if (mti->type == eModifierTypeType_OnlyDeform) { + if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) { if (!deformedVerts) deformedVerts = mesh_getVertexCos(me, &numVerts); @@ -1465,9 +1466,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos modifier_setError(md, "Modifier requires original data, bad stack position"); continue; } - if (sculpt_mode && (!has_multires || multires_applied)) { + if (sculpt_mode && + (!has_multires || multires_applied || ob->sculpt->bm)) + { int unsupported = 0; + if (sculpt_dyntopo) + unsupported = TRUE; + if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM) unsupported |= mti->type != eModifierTypeType_OnlyDeform; @@ -2310,20 +2316,19 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em) static void make_vertexcosnos__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]) { - float *vec = userData; - - vec += 6 * index; + DMCoNo *co_no = &((DMCoNo *)userData)[index]; /* check if we've been here before (normal should not be 0) */ - if (vec[3] || vec[4] || vec[5]) return; + if (!is_zero_v3(co_no->no)) { + return; + } - copy_v3_v3(vec, co); - vec += 3; + copy_v3_v3(co_no->co, co); if (no_f) { - copy_v3_v3(vec, no_f); + copy_v3_v3(co_no->no, no_f); } else { - normal_short_to_float_v3(vec, no_s); + normal_short_to_float_v3(co_no->no, no_s); } } diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 83d1538ecbe..63e12dfb99d 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -543,7 +543,7 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, int copycon) for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) { /* TODO: rename this argument... */ if (copycon) { - copy_constraints(&listb, &pchan->constraints, TRUE); // copy_constraints NULLs listb + BKE_copy_constraints(&listb, &pchan->constraints, TRUE); // BKE_copy_constraints NULLs listb pchan->constraints = listb; pchan->mpath = NULL; /* motion paths should not get copied yet... */ } @@ -621,7 +621,7 @@ void BKE_pose_channel_free(bPoseChannel *pchan) pchan->mpath = NULL; } - free_constraints(&pchan->constraints); + BKE_free_constraints(&pchan->constraints); if (pchan->prop) { IDP_FreeProperty(pchan->prop); @@ -711,7 +711,7 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f pchan->iklinweight = pchan_from->iklinweight; /* constraints */ - copy_constraints(&pchan->constraints, &pchan_from->constraints, TRUE); + BKE_copy_constraints(&pchan->constraints, &pchan_from->constraints, TRUE); /* id-properties */ if (pchan->prop) { diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c new file mode 100644 index 00000000000..7f475cd4732 --- /dev/null +++ b/source/blender/blenkernel/intern/addon.c @@ -0,0 +1,85 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stddef.h> +#include <stdlib.h> + +#include "BLI_utildefines.h" +#include "BLI_ghash.h" +#include "BLI_string.h" + +#include "BKE_addon.h" /* own include */ + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "BLF_translation.h" + +#include "MEM_guardedalloc.h" + +static GHash *global_addonpreftype_hash = NULL; + + +bAddonPrefType *BKE_addon_pref_type_find(const char *idname, int quiet) +{ + if (idname[0]) { + bAddonPrefType *apt; + + apt = BLI_ghash_lookup(global_addonpreftype_hash, idname); + if (apt) { + return apt; + } + + if (!quiet) { + printf("search for unknown addon-pref '%s'\n", idname); + } + } + else { + if (!quiet) { + printf("search for empty addon-pref"); + } + } + + return NULL; +} + +void BKE_addon_pref_type_add(bAddonPrefType *apt) +{ + BLI_ghash_insert(global_addonpreftype_hash, (void *)apt->idname, apt); +} + +void BKE_addon_pref_type_remove(bAddonPrefType *apt) +{ + BLI_ghash_remove(global_addonpreftype_hash, (void *)apt->idname, NULL, (GHashValFreeFP)MEM_freeN); +} + +void BKE_addon_pref_type_init(void) +{ + BLI_assert(global_addonpreftype_hash == NULL); + global_addonpreftype_hash = BLI_ghash_str_new(__func__); +} + +void BKE_addon_pref_type_free(void) +{ + BLI_ghash_free(global_addonpreftype_hash, NULL, (GHashValFreeFP)MEM_freeN); + global_addonpreftype_hash = NULL; +} diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 9155d67dc36..ad14dee168a 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1620,15 +1620,16 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected * 2. copy proxy-pchan's constraints on-to new * 3. add extracted local constraints back on top * - * Note for copy_constraints: when copying constraints, disable 'do_extern' otherwise - * we get the libs direct linked in this blend. */ - extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints); - copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE); + * Note for BKE_copy_constraints: when copying constraints, disable 'do_extern' otherwise + * we get the libs direct linked in this blend. + */ + BKE_extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints); + BKE_copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE); BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints); /* constraints - set target ob pointer to own object */ for (con = pchanw.constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -2426,15 +2427,15 @@ void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float /* prepare PoseChannel for Constraint solving * - makes a copy of matrix, and creates temporary struct to use */ - cob = constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE); + cob = BKE_constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE); /* Solve PoseChannel's Constraints */ - solve_constraints(&pchan->constraints, cob, ctime); /* ctime doesnt alter objects */ + BKE_solve_constraints(&pchan->constraints, cob, ctime); /* ctime doesnt alter objects */ /* cleanup after Constraint Solving * - applies matrix back to pchan, and frees temporary struct used */ - constraints_clear_evalob(cob); + BKE_constraints_clear_evalob(cob); /* prevent constraints breaking a chain */ if (pchan->bone->flag & BONE_CONNECTED) { diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 5c0856bc95b..11ae242023c 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -387,6 +387,7 @@ void BKE_userdef_free(void) wmKeyMap *km; wmKeyMapItem *kmi; wmKeyMapDiffItem *kmdi; + bAddon *addon, *addon_next; for (km = U.user_keymaps.first; km; km = km->next) { for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) { @@ -407,11 +408,19 @@ void BKE_userdef_free(void) BLI_freelistN(&km->items); } + for (addon = U.addons.first; addon; addon = addon_next) { + addon_next = addon->next; + if (addon->prop) { + IDP_FreeProperty(addon->prop); + MEM_freeN(addon->prop); + } + MEM_freeN(addon); + } + BLI_freelistN(&U.uistyles); BLI_freelistN(&U.uifonts); BLI_freelistN(&U.themes); BLI_freelistN(&U.user_keymaps); - BLI_freelistN(&U.addons); } /* handle changes in settings that need recalc */ diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index 0495e729937..fc83b24da5b 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -65,8 +65,8 @@ void printfGlyph(bmGlyph * glyph) printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved); } -#define MAX2(x,y) ((x) > (y) ? (x) : (y)) -#define MAX3(x,y,z) MAX2(MAX2((x), (y)), (z)) +#define MAX2(x, y) ((x) > (y) ? (x) : (y)) +#define MAX3(x, y, z) (MAX2(MAX2((x), (y)), (z))) void calcAlpha(ImBuf * ibuf) { diff --git a/source/blender/blenkernel/intern/booleanops_mesh.c b/source/blender/blenkernel/intern/booleanops_mesh.c index 461b945282f..f53a89fccfd 100644 --- a/source/blender/blenkernel/intern/booleanops_mesh.c +++ b/source/blender/blenkernel/intern/booleanops_mesh.c @@ -56,7 +56,7 @@ CSG_DestroyBlenderMeshInternals( CSG_MeshDescriptor *mesh ) { /* Free face and vertex iterators. */ - FreeMeshDescriptors(&(mesh->m_face_iterator),&(mesh->m_vertex_iterator)); + FreeMeshDescriptors(&(mesh->m_face_iterator), &(mesh->m_vertex_iterator)); } @@ -138,7 +138,7 @@ CSG_AddMeshToBlender( if (mesh == NULL) return 0; if (mesh->base == NULL) return 0; - invert_m4_m4(inv_mat,mesh->base->object->obmat); + invert_m4_m4(inv_mat, mesh->base->object->obmat); /* Create a new blender mesh object - using 'base' as * a template for the new object. */ @@ -191,7 +191,7 @@ CSG_PerformOp( default : op_type = e_csg_intersection; } - output->m_descriptor = CSG_DescibeOperands(bool_op,mesh1->m_descriptor,mesh2->m_descriptor); + output->m_descriptor = CSG_DescibeOperands(bool_op, mesh1->m_descriptor, mesh2->m_descriptor); output->base = mesh1->base; if (output->m_descriptor.user_face_vertex_data_size) { @@ -228,8 +228,8 @@ CSG_PerformOp( /* get the ouput mesh descriptors. */ - CSG_OutputFaceDescriptor(bool_op,&(output->m_face_iterator)); - CSG_OutputVertexDescriptor(bool_op,&(output->m_vertex_iterator)); + CSG_OutputFaceDescriptor(bool_op, &(output->m_face_iterator)); + CSG_OutputVertexDescriptor(bool_op, &(output->m_vertex_iterator)); output->m_destroy_func = CSG_DestroyCSGMeshInternals; return 1; @@ -242,20 +242,20 @@ NewBooleanMeshTest( int op_type ) { - CSG_MeshDescriptor m1,m2,output; - CSG_MeshDescriptor output2,output3; + CSG_MeshDescriptor m1, m2, output; + CSG_MeshDescriptor output2, output3; - if (!MakeCSGMeshFromBlenderBase(base,&m1)) { + if (!MakeCSGMeshFromBlenderBase(base, &m1)) { return 0; } - if (!MakeCSGMeshFromBlenderBase(base_select,&m2)) { + if (!MakeCSGMeshFromBlenderBase(base_select, &m2)) { return 0; } - CSG_PerformOp(&m1,&m2,1,&output); - CSG_PerformOp(&m1,&m2,2,&output2); - CSG_PerformOp(&m1,&m2,3,&output3); + CSG_PerformOp(&m1, &m2, 1, &output); + CSG_PerformOp(&m1, &m2, 2, &output2); + CSG_PerformOp(&m1, &m2, 3, &output3); if (!CSG_AddMeshToBlender(&output)) { return 0; diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 0d44f5cad6f..6db1052d6bd 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -603,8 +603,11 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int case ID_LI: { Library *lib = (Library *)id; - if (rewrite_path_fixed(lib->name, visit_cb, absbase, bpath_user_data)) { - BKE_library_filepath_set(lib, lib->name); + /* keep packedfile paths always relative to the blend */ + if (lib->packedfile == NULL) { + if (rewrite_path_fixed(lib->name, visit_cb, absbase, bpath_user_data)) { + BKE_library_filepath_set(lib, lib->name); + } } break; } diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 405b1efb25d..aeb0407b37f 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -29,29 +29,16 @@ * \ingroup bke */ - -#include <math.h> -#include <string.h> - #include "MEM_guardedalloc.h" #include "DNA_brush_types.h" -#include "DNA_color_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" -#include "DNA_userdef_types.h" -#include "DNA_windowmanager_types.h" - -#include "WM_types.h" - -#include "RNA_access.h" #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_rand.h" -#include "BLI_utildefines.h" -#include "BKE_blender.h" #include "BKE_brush.h" #include "BKE_colortools.h" #include "BKE_global.h" @@ -66,7 +53,6 @@ #include "IMB_imbuf_types.h" #include "RE_render_ext.h" /* externtex */ -#include "RE_shader_ext.h" static void brush_defaults(Brush *brush) { @@ -696,7 +682,7 @@ float BKE_brush_unprojected_radius_get(const Scene *scene, Brush *brush) brush->unprojected_radius; } -static void brush_alpha_set(Scene *scene, Brush *brush, float alpha) +void BKE_brush_alpha_set(Scene *scene, Brush *brush, float alpha) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; @@ -754,315 +740,6 @@ void BKE_brush_scale_size(int *r_brush_size, (*r_brush_size) = (int)((float)(*r_brush_size) * scale); } -/* Brush Painting */ - -typedef struct BrushPainterCache { - short enabled; - - int size; /* size override, if 0 uses 2*BKE_brush_size_get(brush) */ - short flt; /* need float imbuf? */ - short texonly; /* no alpha, color or fallof, only texture in imbuf */ - - int lastsize; - float lastalpha; - float lastjitter; - - ImBuf *ibuf; - ImBuf *texibuf; - ImBuf *maskibuf; -} BrushPainterCache; - -struct BrushPainter { - Scene *scene; - Brush *brush; - - float lastmousepos[2]; /* mouse position of last paint call */ - - float accumdistance; /* accumulated distance of brush since last paint op */ - float lastpaintpos[2]; /* position of last paint op */ - float startpaintpos[2]; /* position of first paint */ - - double accumtime; /* accumulated time since last paint op (airbrush) */ - double lasttime; /* time of last update */ - - float lastpressure; - - short firsttouch; /* first paint op */ - - float startsize; - float startalpha; - float startjitter; - float startspacing; - - BrushPainterCache cache; -}; - -BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush) -{ - BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter"); - - painter->brush = brush; - painter->scene = scene; - painter->firsttouch = 1; - painter->cache.lastsize = -1; /* force ibuf create in refresh */ - - painter->startsize = BKE_brush_size_get(scene, brush); - painter->startalpha = BKE_brush_alpha_get(scene, brush); - painter->startjitter = brush->jitter; - painter->startspacing = brush->spacing; - - return painter; -} - -void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size) -{ - if ((painter->cache.flt != flt) || (painter->cache.size != size) || - ((painter->cache.texonly != texonly) && texonly)) - { - if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf); - if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf); - painter->cache.ibuf = painter->cache.maskibuf = NULL; - painter->cache.lastsize = -1; /* force ibuf create in refresh */ - } - - if (painter->cache.flt != flt) { - if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf); - painter->cache.texibuf = NULL; - painter->cache.lastsize = -1; /* force ibuf create in refresh */ - } - - painter->cache.size = size; - painter->cache.flt = flt; - painter->cache.texonly = texonly; - painter->cache.enabled = 1; -} - -void BKE_brush_painter_free(BrushPainter *painter) -{ - Brush *brush = painter->brush; - - BKE_brush_size_set(painter->scene, brush, painter->startsize); - brush_alpha_set(painter->scene, brush, painter->startalpha); - brush->jitter = painter->startjitter; - brush->spacing = painter->startspacing; - - if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf); - if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf); - if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf); - MEM_freeN(painter); -} - -static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, - int x, int y, int w, int h, int xt, int yt, - const float pos[2]) -{ - Scene *scene = painter->scene; - Brush *brush = painter->brush; - ImBuf *ibuf, *maskibuf, *texibuf; - float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4]; - unsigned char *b, *m, *t, *ot = NULL; - int dotexold, origx = x, origy = y; - const int radius = BKE_brush_size_get(painter->scene, brush); - - xoff = -radius + 0.5f; - yoff = -radius + 0.5f; - xoff += (int)pos[0] - (int)painter->startpaintpos[0]; - yoff += (int)pos[1] - (int)painter->startpaintpos[1]; - - ibuf = painter->cache.ibuf; - texibuf = painter->cache.texibuf; - maskibuf = painter->cache.maskibuf; - - dotexold = (oldtexibuf != NULL); - - /* not sure if it's actually needed or it's a mistake in coords/sizes - * calculation in brush_painter_fixed_tex_partial_update(), but without this - * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */ - w = min_ii(w, ibuf->x); - h = min_ii(h, ibuf->y); - - if (painter->cache.flt) { - for (; y < h; y++) { - bf = ibuf->rect_float + (y * ibuf->x + origx) * 4; - tf = texibuf->rect_float + (y * texibuf->x + origx) * 4; - mf = maskibuf->rect_float + (y * maskibuf->x + origx) * 4; - - if (dotexold) - otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + xt) * 4; - - for (x = origx; x < w; x++, bf += 4, mf += 4, tf += 4) { - if (dotexold) { - copy_v3_v3(tf, otf); - tf[3] = otf[3]; - otf += 4; - } - else { - xy[0] = x + xoff; - xy[1] = y + yoff; - - BKE_brush_sample_tex(scene, brush, xy, tf, 0); - } - - bf[0] = tf[0] * mf[0]; - bf[1] = tf[1] * mf[1]; - bf[2] = tf[2] * mf[2]; - bf[3] = tf[3] * mf[3]; - } - } - } - else { - for (; y < h; y++) { - b = (unsigned char *)ibuf->rect + (y * ibuf->x + origx) * 4; - t = (unsigned char *)texibuf->rect + (y * texibuf->x + origx) * 4; - m = (unsigned char *)maskibuf->rect + (y * maskibuf->x + origx) * 4; - - if (dotexold) - ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + xt) * 4; - - for (x = origx; x < w; x++, b += 4, m += 4, t += 4) { - if (dotexold) { - t[0] = ot[0]; - t[1] = ot[1]; - t[2] = ot[2]; - t[3] = ot[3]; - ot += 4; - } - else { - xy[0] = x + xoff; - xy[1] = y + yoff; - - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); - rgba_float_to_uchar(t, rgba); - } - - b[0] = t[0] * m[0] / 255; - b[1] = t[1] * m[1] / 255; - b[2] = t[2] * m[2] / 255; - b[3] = t[3] * m[3] / 255; - } - } - } -} - -static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, const float pos[2]) -{ - const Scene *scene = painter->scene; - Brush *brush = painter->brush; - BrushPainterCache *cache = &painter->cache; - ImBuf *oldtexibuf, *ibuf; - int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2; - const int diameter = 2 * BKE_brush_size_get(scene, brush); - - imbflag = (cache->flt) ? IB_rectfloat : IB_rect; - if (!cache->ibuf) - cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag); - ibuf = cache->ibuf; - - oldtexibuf = cache->texibuf; - cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag); - - if (oldtexibuf) { - srcx = srcy = 0; - destx = (int)painter->lastpaintpos[0] - (int)pos[0]; - desty = (int)painter->lastpaintpos[1] - (int)pos[1]; - w = oldtexibuf->x; - h = oldtexibuf->y; - - IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h); - } - else { - srcx = srcy = 0; - destx = desty = 0; - w = h = 0; - } - - x1 = destx; - y1 = desty; - x2 = destx + w; - y2 = desty + h; - - /* blend existing texture in new position */ - if ((x1 < x2) && (y1 < y2)) - brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos); - - if (oldtexibuf) - IMB_freeImBuf(oldtexibuf); - - /* sample texture in new areas */ - if ((0 < x1) && (0 < ibuf->y)) - brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos); - if ((x2 < ibuf->x) && (0 < ibuf->y)) - brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos); - if ((x1 < x2) && (0 < y1)) - brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos); - if ((x1 < x2) && (y2 < ibuf->y)) - brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos); -} - -static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction) -{ - const Scene *scene = painter->scene; - Brush *brush = painter->brush; - BrushPainterCache *cache = &painter->cache; - MTex *mtex = &brush->mtex; - int size; - short flt; - const int diameter = 2 * BKE_brush_size_get(scene, brush); - const float alpha = BKE_brush_alpha_get(scene, brush); - - if (diameter != cache->lastsize || - alpha != cache->lastalpha || - brush->jitter != cache->lastjitter) - { - if (cache->ibuf) { - IMB_freeImBuf(cache->ibuf); - cache->ibuf = NULL; - } - if (cache->maskibuf) { - IMB_freeImBuf(cache->maskibuf); - cache->maskibuf = NULL; - } - - flt = cache->flt; - size = (cache->size) ? cache->size : diameter; - - if (brush->flag & BRUSH_FIXED_TEX) { - BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction); - brush_painter_fixed_tex_partial_update(painter, pos); - } - else - BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction); - - cache->lastsize = diameter; - cache->lastalpha = alpha; - cache->lastjitter = brush->jitter; - } - else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) { - int dx = (int)painter->lastpaintpos[0] - (int)pos[0]; - int dy = (int)painter->lastpaintpos[1] - (int)pos[1]; - - if ((dx != 0) || (dy != 0)) - brush_painter_fixed_tex_partial_update(painter, pos); - } -} - -void BKE_brush_painter_break_stroke(BrushPainter *painter) -{ - painter->firsttouch = 1; -} - -static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure) -{ - if (BKE_brush_use_alpha_pressure(painter->scene, brush)) - brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure)); - if (BKE_brush_use_size_pressure(painter->scene, brush)) - BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure)); - if (brush->flag & BRUSH_JITTER_PRESSURE) - brush->jitter = max_ff(0.0f, painter->startjitter * pressure); - if (brush->flag & BRUSH_SPACING_PRESSURE) - brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure)); -} - void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], float jitterpos[2]) { int use_jitter = brush->jitter != 0; @@ -1090,165 +767,6 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], } } -int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure, - void *user, int use_color_correction) -{ - Scene *scene = painter->scene; - Brush *brush = painter->brush; - int totpaintops = 0; - - if (pressure == 0.0f) { - if (painter->lastpressure) // XXX - hack, operator misses - pressure = painter->lastpressure; - else - pressure = 1.0f; /* zero pressure == not using tablet */ - } - if (painter->firsttouch) { - /* paint exactly once on first touch */ - painter->startpaintpos[0] = pos[0]; - painter->startpaintpos[1] = pos[1]; - - brush_pressure_apply(painter, brush, pressure); - if (painter->cache.enabled) - brush_painter_refresh_cache(painter, pos, use_color_correction); - totpaintops += func(user, painter->cache.ibuf, pos, pos); - - painter->lasttime = time; - painter->firsttouch = 0; - painter->lastpaintpos[0] = pos[0]; - painter->lastpaintpos[1] = pos[1]; - } -#if 0 - else if (painter->brush->flag & BRUSH_AIRBRUSH) { - float spacing, step, paintpos[2], dmousepos[2], len; - double starttime, curtime = time; - - /* compute brush spacing adapted to brush size */ - spacing = brush->rate; //radius*brush->spacing*0.01f; - - /* setup starting time, direction vector and accumulated time */ - starttime = painter->accumtime; - sub_v2_v2v2(dmousepos, pos, painter->lastmousepos); - len = normalize_v2(dmousepos); - painter->accumtime += curtime - painter->lasttime; - - /* do paint op over unpainted time distance */ - while (painter->accumtime >= spacing) { - step = (spacing - starttime) * len; - paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step; - paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step; - - if (painter->cache.enabled) - brush_painter_refresh_cache(painter); - totpaintops += func(user, painter->cache.ibuf, - painter->lastpaintpos, paintpos); - - painter->lastpaintpos[0] = paintpos[0]; - painter->lastpaintpos[1] = paintpos[1]; - painter->accumtime -= spacing; - starttime -= spacing; - } - - painter->lasttime = curtime; - } -#endif - else { - float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2]; - float t, len, press; - const int radius = BKE_brush_size_get(scene, brush); - - /* compute brush spacing adapted to brush radius, spacing may depend - * on pressure, so update it */ - brush_pressure_apply(painter, brush, painter->lastpressure); - spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f; - - /* setup starting distance, direction vector and accumulated distance */ - startdistance = painter->accumdistance; - sub_v2_v2v2(dmousepos, pos, painter->lastmousepos); - len = normalize_v2(dmousepos); - painter->accumdistance += len; - - if (brush->flag & BRUSH_SPACE) { - /* do paint op over unpainted distance */ - while ((len > 0.0f) && (painter->accumdistance >= spacing)) { - step = spacing - startdistance; - paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step; - paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step; - - t = step / len; - press = (1.0f - t) * painter->lastpressure + t * pressure; - brush_pressure_apply(painter, brush, press); - spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f; - - BKE_brush_jitter_pos(scene, brush, paintpos, finalpos); - - if (painter->cache.enabled) - brush_painter_refresh_cache(painter, finalpos, use_color_correction); - - totpaintops += - func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos); - - painter->lastpaintpos[0] = paintpos[0]; - painter->lastpaintpos[1] = paintpos[1]; - painter->accumdistance -= spacing; - startdistance -= spacing; - } - } - else { - BKE_brush_jitter_pos(scene, brush, pos, finalpos); - - if (painter->cache.enabled) - brush_painter_refresh_cache(painter, finalpos, use_color_correction); - - totpaintops += func(user, painter->cache.ibuf, pos, finalpos); - - painter->lastpaintpos[0] = pos[0]; - painter->lastpaintpos[1] = pos[1]; - painter->accumdistance = 0; - } - - /* do airbrush paint ops, based on the number of paint ops left over - * from regular painting. this is a temporary solution until we have - * accurate time stamps for mouse move events */ - if (brush->flag & BRUSH_AIRBRUSH) { - double curtime = time; - double painttime = brush->rate * totpaintops; - - painter->accumtime += curtime - painter->lasttime; - if (painter->accumtime <= painttime) - painter->accumtime = 0.0; - else - painter->accumtime -= painttime; - - while (painter->accumtime >= (double)brush->rate) { - brush_pressure_apply(painter, brush, pressure); - - BKE_brush_jitter_pos(scene, brush, pos, finalpos); - - if (painter->cache.enabled) - brush_painter_refresh_cache(painter, finalpos, use_color_correction); - - totpaintops += - func(user, painter->cache.ibuf, painter->lastmousepos, finalpos); - painter->accumtime -= (double)brush->rate; - } - - painter->lasttime = curtime; - } - } - - painter->lastmousepos[0] = pos[0]; - painter->lastmousepos[1] = pos[1]; - painter->lastpressure = pressure; - - brush_alpha_set(scene, brush, painter->startalpha); - BKE_brush_size_set(scene, brush, painter->startsize); - brush->jitter = painter->startjitter; - brush->spacing = painter->startspacing; - - return totpaintops; -} - /* Uses the brush curve control to find a strength value between 0 and 1 */ float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len) { @@ -1275,48 +793,6 @@ float BKE_brush_curve_strength(Brush *br, float p, const float len) return curvemapping_evaluateF(br->curve, 0, p); } -/* TODO: should probably be unified with BrushPainter stuff? */ -unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side) -{ - unsigned int *texcache = NULL; - MTex *mtex = &br->mtex; - TexResult texres = {0}; - int hasrgb, ix, iy; - int side = half_side * 2; - - if (mtex->tex) { - float x, y, step = 2.0 / side, co[3]; - - texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); - - /*do normalized cannonical view coords for texture*/ - for (y = -1.0, iy = 0; iy < side; iy++, y += step) { - for (x = -1.0, ix = 0; ix < side; ix++, x += step) { - co[0] = x; - co[1] = y; - co[2] = 0.0f; - - /* This is copied from displace modifier code */ - hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres); - - /* if the texture gave an RGB value, we assume it didn't give a valid - * intensity, so calculate one (formula from do_material_tex). - * if the texture didn't give an RGB value, copy the intensity across - */ - if (hasrgb & TEX_RGB) - texres.tin = rgb_to_grayscale(&texres.tr); - - ((char *)texcache)[(iy * side + ix) * 4] = - ((char *)texcache)[(iy * side + ix) * 4 + 1] = - ((char *)texcache)[(iy * side + ix) * 4 + 2] = - ((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f); - } - } - } - - return texcache; -} - /**** Radial Control ****/ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br) { diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 61d0936d41d..51890851ebc 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -262,6 +262,17 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) cddm->pbvh_draw = can_pbvh_draw(ob, dm); } + /* Sculpting on a BMesh (dynamic-topology) gets a special PBVH */ + if (!cddm->pbvh && ob->sculpt->bm) { + cddm->pbvh = BKE_pbvh_new(); + cddm->pbvh_draw = TRUE; + + BKE_pbvh_build_bmesh(cddm->pbvh, ob->sculpt->bm, + ob->sculpt->bm_smooth_shading, + ob->sculpt->bm_log); + } + + /* always build pbvh from original mesh, and only use it for drawing if * this derivedmesh is just original mesh. it's the multires subsurf dm * that this is actually for, to support a pbvh on a modified mesh */ @@ -270,14 +281,14 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) Mesh *me = ob->data; int deformed = 0; - cddm->pbvh = BLI_pbvh_new(); + cddm->pbvh = BKE_pbvh_new(); cddm->pbvh_draw = can_pbvh_draw(ob, dm); pbvh_show_diffuse_color_set(cddm->pbvh, ob->sculpt->show_diffuse_color); BKE_mesh_tessface_ensure(me); - BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert, + BKE_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert, me->totface, me->totvert, &me->vdata); deformed = ss->modifiers_active || me->key; @@ -290,7 +301,7 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) totvert = deformdm->getNumVerts(deformdm); vertCos = MEM_callocN(3 * totvert * sizeof(float), "cdDM_getPBVH vertCos"); deformdm->getVertCos(deformdm, vertCos); - BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos); + BKE_pbvh_apply_vertCos(cddm->pbvh, vertCos); MEM_freeN(vertCos); } } @@ -310,7 +321,7 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm) face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); - BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors); + BKE_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors); } static void cdDM_drawVerts(DerivedMesh *dm) @@ -414,6 +425,14 @@ static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges MVert *mvert = cddm->mvert; MEdge *medge = cddm->medge; int i; + + if (cddm->pbvh && cddm->pbvh_draw && + BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) + { + BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, TRUE); + + return; + } if (GPU_buffer_legacy(dm)) { DEBUG_VBO("Using legacy code. cdDM_drawEdges\n"); @@ -530,7 +549,8 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, if (dm->numTessFaceData) { float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL); - BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, setMaterial); + BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, + setMaterial, FALSE); glShadeModel(GL_FLAT); } @@ -664,8 +684,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, } else { if (nors) { - nors += 3; continue; + nors += 3; } + continue; } } else if (drawParamsMapped) { @@ -673,8 +694,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, } else { if (nors) { - nors += 3; continue; + nors += 3; } + continue; } } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index f1d73c7777a..fdd7dc94979 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -1153,7 +1153,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) if ( !mface[i].v4 ) continue; - spring = ( ClothSpring *) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); + spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); if (!spring) { cloth_free_errorsprings(cloth, edgehash, edgelist); diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index f0043d9fa77..60bf67e19e3 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -528,7 +528,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned /* extend array */ if (*numobj >= *maxobj) { *maxobj *= 2; - *objs= MEM_reallocN(*objs, sizeof(Object*)*(*maxobj)); + *objs= MEM_reallocN(*objs, sizeof(Object *)*(*maxobj)); } (*objs)[*numobj] = ob; @@ -740,7 +740,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo /* move object to position (step) in time */ for (i = 0; i < numcollobj; i++) { Object *collob= collobjs[i]; - CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision); + CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision); if (!collmd->bvhtree) continue; @@ -760,7 +760,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo // check all collision objects for (i = 0; i < numcollobj; i++) { Object *collob= collobjs[i]; - CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision); + CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision); BVHTreeOverlap *overlap = NULL; unsigned int result = 0; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index c3aab22fe5a..1a25def3829 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -96,7 +96,7 @@ /* -------------- Naming -------------- */ /* Find the first available, non-duplicate name for a given constraint */ -void unique_constraint_name(bConstraint *con, ListBase *list) +void BKE_unique_constraint_name(bConstraint *con, ListBase *list) { BLI_uniquename(list, con, "Const", '.', offsetof(bConstraint, name), sizeof(con->name)); } @@ -105,7 +105,7 @@ void unique_constraint_name(bConstraint *con, ListBase *list) /* package an object/bone for use in constraint evaluation */ /* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */ -bConstraintOb *constraints_make_evalob(Scene *scene, Object *ob, void *subdata, short datatype) +bConstraintOb *BKE_constraints_make_evalob(Scene *scene, Object *ob, void *subdata, short datatype) { bConstraintOb *cob; @@ -169,7 +169,7 @@ bConstraintOb *constraints_make_evalob(Scene *scene, Object *ob, void *subdata, } /* cleanup after constraint evaluation */ -void constraints_clear_evalob(bConstraintOb *cob) +void BKE_constraints_clear_evalob(bConstraintOb *cob) { float delta[4][4], imat[4][4]; @@ -219,7 +219,7 @@ void constraints_clear_evalob(bConstraintOb *cob) * of a matrix from one space to another for constraint evaluation. * For now, this is only implemented for Objects and PoseChannels. */ -void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to) +void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to) { float diff_mat[4][4]; float imat[4][4]; @@ -242,7 +242,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4 /* use pose-space as stepping stone for other spaces... */ if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ - constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); } } break; @@ -278,7 +278,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4 /* use pose-space as stepping stone for other spaces */ if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ - constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); } } break; @@ -293,7 +293,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4 /* use pose-space as stepping stone for other spaces */ if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) { /* call self with slightly different values */ - constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); } } break; @@ -499,7 +499,7 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m /* Case OBJECT */ if (!strlen(substring)) { copy_m4_m4(mat, ob->obmat); - constraint_mat_convertspace(ob, NULL, mat, from, to); + BKE_constraint_mat_convertspace(ob, NULL, mat, from, to); } /* Case VERTEXGROUP */ /* Current method just takes the average location of all the points in the @@ -512,11 +512,11 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m */ else if (ob->type == OB_MESH) { contarget_get_mesh_mat(ob, substring, mat); - constraint_mat_convertspace(ob, NULL, mat, from, to); + BKE_constraint_mat_convertspace(ob, NULL, mat, from, to); } else if (ob->type == OB_LATTICE) { contarget_get_lattice_mat(ob, substring, mat); - constraint_mat_convertspace(ob, NULL, mat, from, to); + BKE_constraint_mat_convertspace(ob, NULL, mat, from, to); } /* Case BONE */ else { @@ -549,7 +549,7 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m copy_m4_m4(mat, ob->obmat); /* convert matrix space as required */ - constraint_mat_convertspace(ob, pchan, mat, from, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, from, to); } } @@ -4211,7 +4211,7 @@ static void constraints_init_typeinfo(void) /* This function should be used for getting the appropriate type-info when only * a constraint type is known */ -bConstraintTypeInfo *get_constraint_typeinfo(int type) +bConstraintTypeInfo *BKE_get_constraint_typeinfo(int type) { /* initialize the type-info list? */ if (CTI_INIT) { @@ -4236,11 +4236,11 @@ bConstraintTypeInfo *get_constraint_typeinfo(int type) /* This function should always be used to get the appropriate type-info, as it * has checks which prevent segfaults in some weird cases. */ -bConstraintTypeInfo *constraint_get_typeinfo(bConstraint *con) +bConstraintTypeInfo *BKE_constraint_get_typeinfo(bConstraint *con) { /* only return typeinfo for valid constraints */ if (con) - return get_constraint_typeinfo(con->type); + return BKE_get_constraint_typeinfo(con->type); else return NULL; } @@ -4252,7 +4252,7 @@ bConstraintTypeInfo *constraint_get_typeinfo(bConstraint *con) /* ---------- Data Management ------- */ -/* helper function for free_constraint_data() - unlinks references */ +/* helper function for BKE_free_constraint_data() - unlinks references */ static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short isReference, void *UNUSED(userData)) { if (*idpoin && isReference) @@ -4263,10 +4263,10 @@ static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short isRe * be sure to run BIK_clear_data() when freeing an IK constraint, * unless DAG_scene_sort is called. */ -void free_constraint_data(bConstraint *con) +void BKE_free_constraint_data(bConstraint *con) { if (con->data) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); if (cti) { /* perform any special freeing constraint may have */ @@ -4284,13 +4284,13 @@ void free_constraint_data(bConstraint *con) } /* Free all constraints from a constraint-stack */ -void free_constraints(ListBase *list) +void BKE_free_constraints(ListBase *list) { bConstraint *con; /* Free constraint data and also any extra data */ for (con = list->first; con; con = con->next) - free_constraint_data(con); + BKE_free_constraint_data(con); /* Free the whole list */ BLI_freelistN(list); @@ -4298,10 +4298,10 @@ void free_constraints(ListBase *list) /* Remove the specified constraint from the given constraint stack */ -int remove_constraint(ListBase *list, bConstraint *con) +int BKE_remove_constraint(ListBase *list, bConstraint *con) { if (con) { - free_constraint_data(con); + BKE_free_constraint_data(con); BLI_freelinkN(list, con); return 1; } @@ -4310,7 +4310,7 @@ int remove_constraint(ListBase *list, bConstraint *con) } /* Remove all the constraints of the specified type from the given constraint stack */ -void remove_constraints_type(ListBase *list, short type, short last_only) +void BKE_remove_constraints_type(ListBase *list, short type, short last_only) { bConstraint *con, *conp; @@ -4322,7 +4322,7 @@ void remove_constraints_type(ListBase *list, short type, short last_only) conp = con->prev; if (con->type == type) { - remove_constraint(list, con); + BKE_remove_constraint(list, con); if (last_only) return; } @@ -4335,7 +4335,7 @@ void remove_constraints_type(ListBase *list, short type, short last_only) static bConstraint *add_new_constraint_internal(const char *name, short type) { bConstraint *con = MEM_callocN(sizeof(bConstraint), "Constraint"); - bConstraintTypeInfo *cti = get_constraint_typeinfo(type); + bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(type); const char *newName; /* Set up a generic constraint datablock */ @@ -4385,17 +4385,17 @@ static bConstraint *add_new_constraint(Object *ob, bPoseChannel *pchan, const ch * (otherwise unique-naming code will fail, since it assumes element exists in list) */ BLI_addtail(list, con); - unique_constraint_name(con, list); + BKE_unique_constraint_name(con, list); /* if the target list is a list on some PoseChannel belonging to a proxy-protected * Armature layer, we must tag newly added constraints with a flag which allows them * to persist after proxy syncing has been done */ - if (proxylocked_constraints_owner(ob, pchan)) + if (BKE_proxylocked_constraints_owner(ob, pchan)) con->flag |= CONSTRAINT_PROXY_LOCAL; /* make this constraint the active one */ - constraints_set_active(list, con); + BKE_constraints_set_active(list, con); } /* set type+owner specific immutable settings */ @@ -4419,7 +4419,7 @@ static bConstraint *add_new_constraint(Object *ob, bPoseChannel *pchan, const ch /* ......... */ /* Add new constraint for the given bone */ -bConstraint *add_pose_constraint(Object *ob, bPoseChannel *pchan, const char *name, short type) +bConstraint *BKE_add_pose_constraint(Object *ob, bPoseChannel *pchan, const char *name, short type) { if (pchan == NULL) return NULL; @@ -4428,14 +4428,14 @@ bConstraint *add_pose_constraint(Object *ob, bPoseChannel *pchan, const char *na } /* Add new constraint for the given object */ -bConstraint *add_ob_constraint(Object *ob, const char *name, short type) +bConstraint *BKE_add_ob_constraint(Object *ob, const char *name, short type) { return add_new_constraint(ob, NULL, name, type); } /* ......... */ -/* helper for relink_constraints() - call ID_NEW() on every ID reference the constraint has */ +/* helper for BKE_relink_constraints() - call ID_NEW() on every ID reference the constraint has */ static void con_relink_id_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED(isReference), void *UNUSED(userdata)) { /* ID_NEW() expects a struct with inline "id" member as first @@ -4449,20 +4449,20 @@ static void con_relink_id_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED } /* Reassign links that constraints have to other data (called during file loading?) */ -void relink_constraints(ListBase *conlist) +void BKE_relink_constraints(ListBase *conlist) { /* just a wrapper around ID-loop for just calling ID_NEW() on all ID refs */ - id_loop_constraints(conlist, con_relink_id_cb, NULL); + BKE_id_loop_constraints(conlist, con_relink_id_cb, NULL); } /* Run the given callback on all ID-blocks in list of constraints */ -void id_loop_constraints(ListBase *conlist, ConstraintIDFunc func, void *userdata) +void BKE_id_loop_constraints(ListBase *conlist, ConstraintIDFunc func, void *userdata) { bConstraint *con; for (con = conlist->first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); if (cti) { if (cti->id_looper) @@ -4473,14 +4473,14 @@ void id_loop_constraints(ListBase *conlist, ConstraintIDFunc func, void *userdat /* ......... */ -/* helper for copy_constraints(), to be used for making sure that ID's are valid */ +/* helper for BKE_copy_constraints(), to be used for making sure that ID's are valid */ static void con_extern_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED(isReference), void *UNUSED(userData)) { if (*idpoin && (*idpoin)->lib) id_lib_extern(*idpoin); } -/* helper for copy_constraints(), to be used for making sure that usercounts of copied ID's are fixed up */ +/* helper for BKE_copy_constraints(), to be used for making sure that usercounts of copied ID's are fixed up */ static void con_fix_copied_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short isReference, void *UNUSED(userData)) { /* increment usercount if this is a reference type */ @@ -4489,7 +4489,7 @@ static void con_fix_copied_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short } /* duplicate all of the constraints in a constraint stack */ -void copy_constraints(ListBase *dst, const ListBase *src, int do_extern) +void BKE_copy_constraints(ListBase *dst, const ListBase *src, int do_extern) { bConstraint *con, *srccon; @@ -4497,7 +4497,7 @@ void copy_constraints(ListBase *dst, const ListBase *src, int do_extern) BLI_duplicatelist(dst, src); for (con = dst->first, srccon = src->first; con && srccon; srccon = srccon->next, con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); /* make a new copy of the constraint's data */ con->data = MEM_dupallocN(con->data); @@ -4524,13 +4524,13 @@ void copy_constraints(ListBase *dst, const ListBase *src, int do_extern) /* ......... */ -bConstraint *constraints_findByName(ListBase *list, const char *name) +bConstraint *BKE_constraints_findByName(ListBase *list, const char *name) { return BLI_findstring(list, name, offsetof(bConstraint, name)); } /* finds the 'active' constraint in a constraint stack */ -bConstraint *constraints_get_active(ListBase *list) +bConstraint *BKE_constraints_get_active(ListBase *list) { bConstraint *con; @@ -4547,7 +4547,7 @@ bConstraint *constraints_get_active(ListBase *list) } /* Set the given constraint as the active one (clearing all the others) */ -void constraints_set_active(ListBase *list, bConstraint *con) +void BKE_constraints_set_active(ListBase *list, bConstraint *con) { bConstraint *c; @@ -4564,7 +4564,7 @@ void constraints_set_active(ListBase *list, bConstraint *con) /* -------- Constraints and Proxies ------- */ /* Rescue all constraints tagged as being CONSTRAINT_PROXY_LOCAL (i.e. added to bone that's proxy-synced in this file) */ -void extract_proxylocal_constraints(ListBase *dst, ListBase *src) +void BKE_extract_proxylocal_constraints(ListBase *dst, ListBase *src) { bConstraint *con, *next; @@ -4581,7 +4581,7 @@ void extract_proxylocal_constraints(ListBase *dst, ListBase *src) } /* Returns if the owner of the constraint is proxy-protected */ -short proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan) +short BKE_proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan) { /* Currently, constraints can only be on object or bone level */ if (ob && ob->proxy) { @@ -4610,9 +4610,9 @@ short proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan) * None of the actual calculations of the matrices should be done here! Also, this function is * not to be used by any new constraints, particularly any that have multiple targets. */ -void get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime) +void BKE_get_constraint_target_matrix(Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintOb *cob; bConstraintTarget *ct; @@ -4657,10 +4657,8 @@ void get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n, cti->get_constraint_targets(con, &targets); /* only calculate the target matrix on the first target */ - ct = (bConstraintTarget *)targets.first; - while (ct && n-- > 0) - ct = ct->next; - + ct = (bConstraintTarget *)BLI_findlink(&targets, index); + if (ct) { if (cti->get_target_matrix) cti->get_target_matrix(con, cob, ct, ctime); @@ -4679,9 +4677,9 @@ void get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n, } /* Get the list of targets required for solving a constraint */ -void get_constraint_targets_for_solving(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime) +void BKE_get_constraint_targets_for_solving(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); if (cti && cti->get_constraint_targets) { bConstraintTarget *ct; @@ -4711,10 +4709,10 @@ void get_constraint_targets_for_solving(bConstraint *con, bConstraintOb *cob, Li /* This function is called whenever constraints need to be evaluated. Currently, all * constraints that can be evaluated are everytime this gets run. * - * constraints_make_evalob and constraints_clear_evalob should be called before and + * BKE_constraints_make_evalob and BKE_constraints_clear_evalob should be called before and * after running this function, to sort out cob */ -void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime) +void BKE_solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime) { bConstraint *con; float oldmat[4][4]; @@ -4726,7 +4724,7 @@ void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime) /* loop over available constraints, solving and blending them */ for (con = conlist->first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; /* these we can skip completely (invalid constraints...) */ @@ -4746,10 +4744,10 @@ void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime) copy_m4_m4(oldmat, cob->matrix); /* move owner matrix into right space */ - constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace); + BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace); /* prepare targets for constraint solving */ - get_constraint_targets_for_solving(con, cob, &targets, ctime); + BKE_get_constraint_targets_for_solving(con, cob, &targets, ctime); /* Solve the constraint and put result in cob->matrix */ cti->evaluate_constraint(con, cob, &targets); @@ -4764,7 +4762,7 @@ void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime) /* move owner back into worldspace for next constraint/other business */ if ((con->flag & CONSTRAINT_SPACEONCE) == 0) - constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD); + BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD); /* Interpolate the enforcement, to blend result of constraint into final owner transform * - all this happens in worldspace to prevent any weirdness creeping in ([#26014] and [#25725]), diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 7009f1235c9..a45afa5e69a 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -29,6 +29,7 @@ #include <string.h> +#include <stdlib.h> #include <stddef.h> #include "MEM_guardedalloc.h" @@ -327,10 +328,13 @@ static void *ctx_data_pointer_get(const bContext *C, const char *member) { bContextDataResult result; - if (C && ctx_data_get((bContext *)C, member, &result) == 1) + if (C && ctx_data_get((bContext *)C, member, &result) == 1) { + BLI_assert(result.type == CTX_DATA_TYPE_POINTER); return result.ptr.data; - - return NULL; + } + else { + return NULL; + } } static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer) @@ -343,6 +347,7 @@ static int ctx_data_pointer_verify(const bContext *C, const char *member, void * return 1; } else if (ctx_data_get((bContext *)C, member, &result) == 1) { + BLI_assert(result.type == CTX_DATA_TYPE_POINTER); *pointer = result.ptr.data; return 1; } @@ -357,6 +362,7 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa bContextDataResult result; if (ctx_data_get((bContext *)C, member, &result) == 1) { + BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION); *list = result.list; return 1; } @@ -371,10 +377,13 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member) { bContextDataResult result; - if (ctx_data_get((bContext *)C, member, &result) == 1) + if (ctx_data_get((bContext *)C, member, &result) == 1) { + BLI_assert(result.type == CTX_DATA_TYPE_POINTER); return result.ptr; - else + } + else { return PointerRNA_NULL; + } } PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type) @@ -399,6 +408,7 @@ ListBase CTX_data_collection_get(const bContext *C, const char *member) bContextDataResult result; if (ctx_data_get((bContext *)C, member, &result) == 1) { + BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION); return result.list; } else { diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 7c13ca388e0..cea92d53916 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -34,6 +34,7 @@ #include <math.h> #include <ctype.h> #include <stdlib.h> +#include <stddef.h> #include "MEM_guardedalloc.h" @@ -337,37 +338,12 @@ void defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int flip bDeformGroup *defgroup_find_name(Object *ob, const char *name) { - /* return a pointer to the deform group with this name - * or return NULL otherwise. - */ - bDeformGroup *curdef; - - for (curdef = ob->defbase.first; curdef; curdef = curdef->next) { - if (!strcmp(curdef->name, name)) { - return curdef; - } - } - return NULL; + return BLI_findstring(&ob->defbase, name, offsetof(bDeformGroup, name)); } int defgroup_name_index(Object *ob, const char *name) { - /* Return the location of the named deform group within the list of - * deform groups. This function is a combination of BLI_findlink and - * defgroup_find_name. The other two could be called instead, but that - * require looping over the vertexgroups twice. - */ - bDeformGroup *curdef; - int def_nr; - - if (name && name[0] != '\0') { - for (curdef = ob->defbase.first, def_nr = 0; curdef; curdef = curdef->next, def_nr++) { - if (!strcmp(curdef->name, name)) - return def_nr; - } - } - - return -1; + return (name) ? BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)) : -1; } /* note, must be freed */ @@ -810,3 +786,43 @@ int defvert_find_shared(const MDeformVert *dvert_a, const MDeformVert *dvert_b) return -1; } + +/* -------------------------------------------------------------------- */ +/* Defvert Array functions */ + +void BKE_defvert_array_copy(MDeformVert *dst, const MDeformVert *src, int copycount) +{ + /* Assumes dst is already set up */ + int i; + + if (!src || !dst) + return; + + memcpy(dst, src, copycount * sizeof(MDeformVert)); + + for (i = 0; i < copycount; i++) { + if (src[i].dw) { + dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * src[i].totweight, "copy_deformWeight"); + memcpy(dst[i].dw, src[i].dw, sizeof(MDeformWeight) * src[i].totweight); + } + } + +} + +void BKE_defvert_array_free(MDeformVert *dvert, int totvert) +{ + /* Instead of freeing the verts directly, + * call this function to delete any special + * vert data */ + int i; + + if (!dvert) + return; + + /* Free any special data from the verts */ + for (i = 0; i < totvert; i++) { + if (dvert[i].dw) MEM_freeN(dvert[i].dw); + } + MEM_freeN(dvert); +} + diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 6ba140fcec1..42389564ec0 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -472,7 +472,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -754,7 +754,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O /* object constraints */ for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -2295,7 +2295,7 @@ static void dag_object_time_update_flags(Object *ob) if (ob->constraints.first) { bConstraint *con; for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -2738,7 +2738,7 @@ static void dag_id_flush_update(Scene *sce, ID *id) for (obt = bmain->object.first; obt; obt = obt->id.next) { bConstraint *con; for (con = obt->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { @@ -3030,7 +3030,7 @@ void DAG_pose_sort(Object *ob) addtoroot = 0; } for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 083cb02fd3d..71e9daaee6b 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -225,29 +225,48 @@ void BKE_displist_normals_add(ListBase *lb) } } -void BKE_displist_count(ListBase *lb, int *totvert, int *totface) +void BKE_displist_count(ListBase *lb, int *totvert, int *totface, int *tottri) { DispList *dl; - dl = lb->first; - while (dl) { + for (dl = lb->first; dl; dl = dl->next) { + int vert_tot = 0; + int face_tot = 0; + int tri_tot = 0; + switch (dl->type) { case DL_SURF: - *totvert += dl->nr * dl->parts; - *totface += (dl->nr - 1) * (dl->parts - 1); + { + vert_tot = dl->nr * dl->parts; + face_tot = (dl->nr - 1) * (dl->parts - 1); + tri_tot = face_tot * 2; break; + } case DL_INDEX3: + { + vert_tot = dl->nr; + face_tot = dl->parts; + tri_tot = face_tot; + break; + } case DL_INDEX4: - *totvert += dl->nr; - *totface += dl->parts; + { + vert_tot = dl->nr; + face_tot = dl->parts; + tri_tot = face_tot * 2; break; + } case DL_POLY: case DL_SEGM: - *totvert += dl->nr * dl->parts; + { + vert_tot = dl->nr * dl->parts; break; + } } - dl = dl->next; + *totvert += vert_tot; + *totface += face_tot; + *tottri += tri_tot; } } @@ -487,7 +506,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, int flipnormal) } /* XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { */ - if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES))) { + if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES))) { if (tot) { dlnew = MEM_callocN(sizeof(DispList), "filldisplist"); dlnew->type = DL_INDEX3; @@ -780,7 +799,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl required_mode |= eModifierMode_Editmode; if (cu->editnurb == NULL) { - keyVerts = do_ob_key(scene, ob); + keyVerts = BKE_key_evaluate_object(scene, ob, &numVerts); if (keyVerts) { /* split coords from key data, the latter also includes @@ -789,7 +808,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl * shape key modifier yet. */ deformedVerts = BKE_curve_keyVertexCos_get(cu, nurb, keyVerts); originalVerts = MEM_dupallocN(deformedVerts); - numVerts = BKE_nurbList_verts_count(nurb); + BLI_assert(BKE_nurbList_verts_count(nurb) == numVerts); } } diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index e32f8d53b7d..fff51ab2a59 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -529,7 +529,7 @@ static int subframe_updateObject(Scene *scene, Object *ob, int flags, float fram /* also update constraint targets */ for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; if (cti && cti->get_constraint_targets) { @@ -2689,7 +2689,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filenam if (format == R_IMF_IMTYPE_OPENEXR) format = R_IMF_IMTYPE_PNG; #endif BLI_strncpy(output_file, filename, sizeof(output_file)); - BKE_add_image_extension(output_file, format); + BKE_add_image_extension_from_type(output_file, format); /* Validate output file path */ BLI_path_abs(output_file, G.main->name); @@ -2839,7 +2839,9 @@ static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats) /* * Get material diffuse color and alpha (including linked textures) in given coordinates */ -static void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, const float volume_co[3], const float surface_co[3], int faceIndex, short isQuad, DerivedMesh *orcoDm) +static void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, + const float volume_co[3], const float surface_co[3], + int faceIndex, short isQuad, DerivedMesh *orcoDm) { Material *mat = bMats->mat; MFace *mface = orcoDm->getTessFaceArray(orcoDm); diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 480ff23f100..1c43b418a1c 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -113,8 +113,13 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em) #define USE_TESSFACE_SPEEDUP BMesh *bm = em->bm; - BMLoop *(*looptris)[3] = NULL; - BLI_array_declare(looptris); + + /* this assumes all faces can be scan-filled, which isn't always true, + * worst case we over alloc a little which is acceptable */ + const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); + const int looptris_tot_prev_alloc = em->looptris ? (MEM_allocN_len(em->looptris) / sizeof(*em->looptris)) : 0; + + BMLoop *(*looptris)[3]; BMIter iter; BMFace *efa; BMLoop *l; @@ -135,17 +140,16 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em) #else /* this means no reallocs for quad dominant models, for */ - if ( (em->looptris != NULL) && - (em->tottri != 0) && - /* (totrti <= bm->totface * 2) would be fine for all quads, - * but in case there are some ngons, still re-use the array */ - (em->tottri <= bm->totface * 3)) + if ((em->looptris != NULL) && + /* (em->tottri >= looptris_tot)) */ + /* check against alloc'd size incase we over alloc'd a little */ + ((looptris_tot_prev_alloc >= looptris_tot) && (looptris_tot_prev_alloc <= looptris_tot * 2))) { looptris = em->looptris; } else { if (em->looptris) MEM_freeN(em->looptris); - BLI_array_reserve(looptris, bm->totface); + looptris = MEM_mallocN(sizeof(*looptris) * looptris_tot, __func__); } #endif @@ -163,20 +167,16 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em) else if (efa->len == 3) { #if 0 int j; - BLI_array_grow_one(looptris); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) { looptris[i][j] = l; } i += 1; #else /* more cryptic but faster */ - BLI_array_grow_one(looptris); - { - BMLoop **l_ptr = looptris[i++]; - l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); - l_ptr[1] = l = l->next; - l_ptr[2] = l->next; - } + BMLoop **l_ptr = looptris[i++]; + l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); + l_ptr[1] = l = l->next; + l_ptr[2] = l->next; #endif } else if (efa->len == 4) { @@ -199,15 +199,12 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em) i += 1; #else /* more cryptic but faster */ - BLI_array_grow_items(looptris, 2); - { - BMLoop **l_ptr_a = looptris[i++]; - BMLoop **l_ptr_b = looptris[i++]; - (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa)); - (l_ptr_a[1] = l = l->next); - (l_ptr_a[2] = l_ptr_b[1] = l = l->next); - ( l_ptr_b[2] = l->next); - } + BMLoop **l_ptr_a = looptris[i++]; + BMLoop **l_ptr_b = looptris[i++]; + (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa)); + (l_ptr_a[1] = l = l->next); + (l_ptr_a[2] = l_ptr_b[1] = l = l->next); + ( l_ptr_b[2] = l->next); #endif } @@ -250,9 +247,10 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em) BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert); totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no); - BLI_array_grow_items(looptris, totfilltri); + BLI_assert(totfilltri <= efa->len - 2); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { + BMLoop **l_ptr = looptris[i++]; BMLoop *l1 = sf_tri->v1->tmp.p; BMLoop *l2 = sf_tri->v2->tmp.p; BMLoop *l3 = sf_tri->v3->tmp.p; @@ -261,10 +259,9 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em) if (BM_elem_index_get(l2) > BM_elem_index_get(l3)) { SWAP(BMLoop *, l2, l3); } if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop *, l1, l2); } - looptris[i][0] = l1; - looptris[i][1] = l2; - looptris[i][2] = l3; - i += 1; + l_ptr[0] = l1; + l_ptr[1] = l2; + l_ptr[2] = l3; } BLI_scanfill_end(&sf_ctx); @@ -274,6 +271,8 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em) em->tottri = i; em->looptris = looptris; + BLI_assert(em->tottri <= looptris_tot); + #undef USE_TESSFACE_SPEEDUP } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 5e01773cab9..23f3a3ad3fd 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -859,7 +859,7 @@ void testhandles_fcurve(FCurve *fcu, const short use_handle) short flag = 0; /* flag is initialized as selection status - * of beztriple control-points (labelled 0,1,2) + * of beztriple control-points (labelled 0, 1, 2) */ if (bezt->f2 & SELECT) flag |= (1 << 1); // == 2 if (use_handle == FALSE) { @@ -1192,7 +1192,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) /* extract transform just like how the constraints do it! */ copy_m4_m4(mat, pchan->pose_mat); - constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); /* ... and from that, we get our transform */ copy_v3_v3(tmp_loc, mat[3]); @@ -1217,7 +1217,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) /* extract transform just like how the constraints do it! */ copy_m4_m4(mat, ob->obmat); - constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL); + BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL); /* ... and from that, we get our transform */ copy_v3_v3(tmp_loc, mat[3]); @@ -1288,7 +1288,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { /* just like how the constraints do it! */ copy_m4_m4(mat, pchan->pose_mat); - constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); } else { /* specially calculate local matrix, since chan_mat is not valid @@ -1315,7 +1315,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { /* just like how the constraints do it! */ copy_m4_m4(mat, ob->obmat); - constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL); + BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL); } else { /* transforms to matrix */ @@ -2022,12 +2022,12 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime } else { /* bezier interpolation */ - /* v1,v2 are the first keyframe and its 2nd handle */ + /* (v1, v2) are the first keyframe and its 2nd handle */ v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; v2[0] = prevbezt->vec[2][0]; v2[1] = prevbezt->vec[2][1]; - /* v3,v4 are the last keyframe's 1st handle + the last keyframe */ + /* (v3, v4) are the last keyframe's 1st handle + the last keyframe */ v3[0] = bezt->vec[0][0]; v3[1] = bezt->vec[0][1]; v4[0] = bezt->vec[1][0]; diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 5dd0f08dc71..3be47668fb5 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -815,6 +815,13 @@ void IDP_FreeProperty(IDProperty *prop) } } +void IDP_ClearProperty(IDProperty *prop) +{ + IDP_FreeProperty(prop); + prop->data.pointer = NULL; + prop->len = prop->totallen = 0; +} + /* Unlinks any IDProperty<->ID linkage that might be going on. * note: currently unused.*/ void IDP_UnlinkProperty(IDProperty *prop) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f3cdf11d664..dbc423f98b3 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -312,10 +312,6 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame) break; ibuf->index = index; - if (ima->flag & IMA_CM_PREDIVIDE) - ibuf->flags |= IB_cm_predivide; - else - ibuf->flags &= ~IB_cm_predivide; /* this function accepts (link == NULL) */ BLI_insertlinkbefore(&ima->ibufs, link, ibuf); @@ -552,6 +548,26 @@ int BKE_image_scale(Image *image, int width, int height) return (ibuf != NULL); } +static void image_init_color_management(Image *ima) +{ + ImBuf *ibuf; + char name[FILE_MAX]; + + BKE_image_user_file_path(NULL, ima, name); + + /* will set input color space to image format default's */ + ibuf = IMB_loadiffname(name, IB_test | IB_alphamode_detect, ima->colorspace_settings.name); + + if (ibuf) { + if (ibuf->flags & IB_alphamode_premul) + ima->alpha_mode = IMA_ALPHA_PREMUL; + else + ima->alpha_mode = IMA_ALPHA_STRAIGHT; + + IMB_freeImBuf(ibuf); + } +} + Image *BKE_image_load(const char *filepath) { Image *ima; @@ -579,6 +595,8 @@ Image *BKE_image_load(const char *filepath) if (BLI_testextensie_array(filepath, imb_ext_movie)) ima->source = IMA_SRC_MOVIE; + image_init_color_management(ima); + return ima; } @@ -666,7 +684,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char /* both byte and float buffers are filling in sRGB space, need to linearize float buffer after BKE_image_buf_fill* functions */ IMB_buffer_float_from_float(rect_float, rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, - ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); + TRUE, ibuf->x, ibuf->y, ibuf->x, ibuf->x); } return ibuf; @@ -1119,6 +1137,8 @@ char BKE_imtype_valid_depths(const char imtype) return R_IMF_CHAN_DEPTH_10; case R_IMF_IMTYPE_JP2: return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16; + case R_IMF_IMTYPE_PNG: + return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_16; /* most formats are 8bit only */ default: return R_IMF_CHAN_DEPTH_8; @@ -1165,9 +1185,10 @@ char BKE_imtype_from_arg(const char *imtype_arg) else return R_IMF_IMTYPE_INVALID; } -int BKE_add_image_extension(char *string, const char imtype) +static int do_add_image_extension(char *string, const char imtype, const ImageFormatData *im_format) { const char *extension = NULL; + (void)im_format; /* may be unused, depends on build options */ if (imtype == R_IMF_IMTYPE_IRIS) { if (!BLI_testextensie(string, ".rgb")) @@ -1232,8 +1253,22 @@ int BKE_add_image_extension(char *string, const char imtype) } #ifdef WITH_OPENJPEG else if (imtype == R_IMF_IMTYPE_JP2) { - if (!BLI_testextensie(string, ".jp2")) - extension = ".jp2"; + if (im_format) { + if (im_format->jp2_codec == R_IMF_JP2_CODEC_JP2) { + if (!BLI_testextensie(string, ".jp2")) + extension = ".jp2"; + } + else if (im_format->jp2_codec == R_IMF_JP2_CODEC_J2K) { + if (!BLI_testextensie(string, ".j2c")) + extension = ".j2c"; + } + else + BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec"); + } + else { + if (!BLI_testextensie(string, ".jp2")) + extension = ".jp2"; + } } #endif else { // R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90, R_IMF_IMTYPE_QUICKTIME etc @@ -1259,11 +1294,22 @@ int BKE_add_image_extension(char *string, const char imtype) } } +int BKE_add_image_extension(char *string, const ImageFormatData *im_format) +{ + return do_add_image_extension(string, im_format->imtype, im_format); +} + +int BKE_add_image_extension_from_type(char *string, const char imtype) +{ + return do_add_image_extension(string, imtype, NULL); +} + void BKE_imformat_defaults(ImageFormatData *im_format) { memset(im_format, 0, sizeof(*im_format)); im_format->planes = R_IMF_PLANES_RGB; im_format->imtype = R_IMF_IMTYPE_PNG; + im_format->depth = R_IMF_CHAN_DEPTH_8; im_format->quality = 90; im_format->compress = 90; @@ -1288,9 +1334,13 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i im_format->imtype = R_IMF_IMTYPE_RADHDR; #endif - else if (ftype == PNG) + else if (ftype == PNG) { im_format->imtype = R_IMF_IMTYPE_PNG; + if (custom_flags & PNG_16BIT) + im_format->depth = R_IMF_CHAN_DEPTH_16; + } + #ifdef WITH_DDS else if (ftype == DDS) im_format->imtype = R_IMF_IMTYPE_DDS; @@ -1351,6 +1401,13 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i if (ftype & JP2_CINE_48FPS) im_format->jp2_flag |= R_IMF_JP2_FLAG_CINE_48; } + + if (ftype & JP2_JP2) + im_format->jp2_codec = R_IMF_JP2_CODEC_JP2; + else if (ftype & JP2_J2K) + im_format->jp2_codec = R_IMF_JP2_CODEC_J2K; + else + BLI_assert(!"Unsupported jp2 codec was specified in file type"); } #endif @@ -1815,8 +1872,12 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) { ibuf->ftype = PNG; - if (imtype == R_IMF_IMTYPE_PNG) + if (imtype == R_IMF_IMTYPE_PNG) { + if (imf->depth == R_IMF_CHAN_DEPTH_16) + ibuf->ftype |= PNG_16BIT; + ibuf->ftype |= compress; + } } #ifdef WITH_DDS @@ -1906,6 +1967,13 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) if (imf->jp2_flag & R_IMF_JP2_FLAG_CINE_48) ibuf->ftype |= JP2_CINE_48FPS; } + + if (imf->jp2_codec == R_IMF_JP2_CODEC_JP2) + ibuf->ftype |= JP2_JP2; + else if (imf->jp2_codec == R_IMF_JP2_CODEC_J2K) + ibuf->ftype |= JP2_J2K; + else + BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec"); } #endif else { @@ -1956,7 +2024,8 @@ int BKE_imbuf_write_stamp(Scene *scene, struct Object *camera, ImBuf *ibuf, cons } -void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short use_frames) +static void do_makepicstring(char *string, const char *base, const char *relbase, int frame, const char imtype, + const ImageFormatData *im_format, const short use_ext, const short use_frames) { if (string == NULL) return; BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */ @@ -1966,8 +2035,17 @@ void BKE_makepicstring(char *string, const char *base, const char *relbase, int BLI_path_frame(string, frame, 4); if (use_ext) - BKE_add_image_extension(string, imtype); + do_add_image_extension(string, imtype, im_format); +} +void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const ImageFormatData *im_format, const short use_ext, const short use_frames) +{ + do_makepicstring(string, base, relbase, frame, im_format->imtype, im_format, use_ext, use_frames); +} + +void BKE_makepicstring_from_type(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short use_frames) +{ + do_makepicstring(string, base, relbase, frame, imtype, NULL, use_ext, use_frames); } /* used by sequencer too */ @@ -2284,7 +2362,7 @@ void BKE_image_backup_render(Scene *scene, Image *ima) static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) { const char *colorspace = ima->colorspace_settings.name; - int predivide = ima->flag & IMA_CM_PREDIVIDE; + int predivide = ima->alpha_mode == IMA_ALPHA_PREMUL; ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y); @@ -2316,6 +2394,18 @@ static void image_initialize_after_load(Image *ima, ImBuf *ibuf) } +static int imbuf_alpha_flags_for_image(Image *ima) +{ + int flag = 0; + + if (ima->flag & IMA_IGNORE_ALPHA) + flag |= IB_ignore_alpha; + else if (ima->alpha_mode == IMA_ALPHA_PREMUL) + flag |= IB_alphamode_premul; + + return flag; +} + static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) { struct ImBuf *ibuf; @@ -2330,8 +2420,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) BKE_image_user_file_path(iuser, ima, name); flag = IB_rect | IB_multilayer; - if (ima->flag & IMA_DO_PREMUL) - flag |= IB_premul; + flag |= imbuf_alpha_flags_for_image(ima); /* read ibuf */ ibuf = IMB_loadiffname(name, flag, ima->colorspace_settings.name); @@ -2490,15 +2579,14 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) /* is there a PackedFile with this image ? */ if (ima->packedfile) { flag = IB_rect | IB_multilayer; - if (ima->flag & IMA_DO_PREMUL) flag |= IB_premul; + flag |= imbuf_alpha_flags_for_image(ima); ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data, ima->packedfile->size, flag, ima->colorspace_settings.name, "<packed data>"); } else { flag = IB_rect | IB_multilayer | IB_metadata; - if (ima->flag & IMA_DO_PREMUL) - flag |= IB_premul; + flag |= imbuf_alpha_flags_for_image(ima); /* get the right string */ BKE_image_user_frame_calc(iuser, cfra, 0); @@ -2718,15 +2806,6 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ ibuf->dither = dither; - if (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) { - ibuf->flags |= IB_cm_predivide; - ima->flag |= IMA_CM_PREDIVIDE; - } - else { - ibuf->flags &= ~IB_cm_predivide; - ima->flag &= ~IMA_CM_PREDIVIDE; - } - ima->ok = IMA_OK_LOADED; return ibuf; diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index ad95f09826a..ccc57a24540 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -1300,13 +1300,13 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int } /* returns key coordinates (+ tilt) when key applied, NULL otherwise */ -float *do_ob_key(Scene *scene, Object *ob) +float *BKE_key_evaluate_object(Scene *scene, Object *ob, int *r_totelem) { Key *key = BKE_key_from_object(ob); KeyBlock *actkb = BKE_keyblock_from_object(ob); char *out; int tot = 0, size = 0; - + if (key == NULL || key->block.first == NULL) return NULL; @@ -1344,7 +1344,7 @@ float *do_ob_key(Scene *scene, Object *ob) return NULL; /* allocate array */ - out = MEM_callocN(size, "do_ob_key out"); + out = MEM_callocN(size, "BKE_key_evaluate_object out"); /* prevent python from screwing this up? anyhoo, the from pointer could be dropped */ key->from = (ID *)ob->data; @@ -1383,6 +1383,9 @@ float *do_ob_key(Scene *scene, Object *ob) else if (ob->type == OB_SURF) do_curve_key(scene, ob, key, out, tot); } + if (r_totelem) { + *r_totelem = tot; + } return (float *)out; } @@ -1732,7 +1735,7 @@ void BKE_key_convert_to_mesh(KeyBlock *kb, Mesh *me) } /************************* vert coords ************************/ -float (*BKE_key_convert_to_vertcos(Object * ob, KeyBlock * kb))[3] +float (*BKE_key_convert_to_vertcos(Object *ob, KeyBlock *kb))[3] { float (*vertCos)[3], *co; float *fp = kb->data; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index d98188d8a6f..fa01e9fd933 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -88,7 +88,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) /* vertex weight groups are just freed all for now */ if (lt->dvert) { - free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw); + BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw); lt->dvert = NULL; } @@ -209,7 +209,7 @@ Lattice *BKE_lattice_copy(Lattice *lt) if (lt->dvert) { int tot = lt->pntsu * lt->pntsv * lt->pntsw; ltn->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert"); - copy_dverts(ltn->dvert, lt->dvert, tot); + BKE_defvert_array_copy(ltn->dvert, lt->dvert, tot); } ltn->editlatt = NULL; @@ -220,12 +220,12 @@ Lattice *BKE_lattice_copy(Lattice *lt) void BKE_lattice_free(Lattice *lt) { if (lt->def) MEM_freeN(lt->def); - if (lt->dvert) free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw); + if (lt->dvert) BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw); if (lt->editlatt) { Lattice *editlt = lt->editlatt->latt; if (editlt->def) MEM_freeN(editlt->def); - if (editlt->dvert) free_dverts(editlt->dvert, lt->pntsu * lt->pntsv * lt->pntsw); + if (editlt->dvert) BKE_defvert_array_free(editlt->dvert, lt->pntsu * lt->pntsv * lt->pntsw); MEM_freeN(editlt); MEM_freeN(lt->editlatt); diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 2fa928e7c07..73452b216ff 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -933,7 +933,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas } /* main scan-fill */ - sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, 0, zvec); + sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_HOLES, zvec); face_array = MEM_mallocN(sizeof(*face_array) * (sf_tri_tot + tot_feather_quads), "maskrast_face_index"); face_index = 0; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 54bd03ece70..4655dd04261 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -631,11 +631,14 @@ Material *give_current_material(Object *ob, short act) if (totcolp == NULL || ob->totcol == 0) return NULL; if (act < 0) { - printf("no!\n"); + printf("Negative material index!\n"); } - if (act > ob->totcol) act = ob->totcol; - else if (act <= 0) act = 1; + /* return NULL for invalid 'act', can happen for mesh face indices */ + if (act > ob->totcol) + return NULL; + else if (act <= 0) + return NULL; if (ob->matbits && ob->matbits[act - 1]) { /* in object */ ma = ob->mat[act - 1]; @@ -1237,6 +1240,11 @@ int object_remove_material_slot(Object *ob) if (*matarar == NULL) return FALSE; + /* can happen on face selection in editmode */ + if (ob->actcol > ob->totcol) { + ob->actcol = ob->totcol; + } + /* we delete the actcol */ mao = (*matarar)[ob->actcol - 1]; if (mao) mao->id.us--; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 3eb96f218e4..30e7cb3bb36 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -430,42 +430,6 @@ void BKE_mesh_free(Mesh *me, int unlink) if (me->edit_btmesh) MEM_freeN(me->edit_btmesh); } -void copy_dverts(MDeformVert *dst, const MDeformVert *src, int copycount) -{ - /* Assumes dst is already set up */ - int i; - - if (!src || !dst) - return; - - memcpy(dst, src, copycount * sizeof(MDeformVert)); - - for (i = 0; i < copycount; i++) { - if (src[i].dw) { - dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * src[i].totweight, "copy_deformWeight"); - memcpy(dst[i].dw, src[i].dw, sizeof(MDeformWeight) * src[i].totweight); - } - } - -} - -void free_dverts(MDeformVert *dvert, int totvert) -{ - /* Instead of freeing the verts directly, - * call this function to delete any special - * vert data */ - int i; - - if (!dvert) - return; - - /* Free any special data from the verts */ - for (i = 0; i < totvert; i++) { - if (dvert[i].dw) MEM_freeN(dvert[i].dw); - } - MEM_freeN(dvert); -} - static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata) { if (free_customdata) { @@ -2488,7 +2452,7 @@ void BKE_mesh_loops_to_mface_corners(CustomData *fdata, CustomData *ldata, */ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomData *pdata, - MVert *mvert, int totface, int UNUSED(totloop), + MVert *mvert, int totface, int totloop, int totpoly, /* when tessellating to recalculate normals after * we can skip copying here */ @@ -2503,15 +2467,15 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, #define TESSFACE_SCANFILL (1 << 0) #define TESSFACE_IS_QUAD (1 << 1) + const int looptris_tot = poly_to_tri_count(totpoly, totloop); + MPoly *mp, *mpoly; MLoop *ml, *mloop; - MFace *mface = NULL, *mf; - BLI_array_declare(mface); + MFace *mface, *mf; ScanFillContext sf_ctx; ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first; ScanFillFace *sf_tri; - int *mface_to_poly_map = NULL; - BLI_array_declare(mface_to_poly_map); + int *mface_to_poly_map; int lindex[4]; /* only ever use 3 in this case */ int poly_index, j, mface_index; @@ -2525,8 +2489,9 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, /* allocate the length of totfaces, avoid many small reallocs, * if all faces are tri's it will be correct, quads == 2x allocs */ - BLI_array_reserve(mface_to_poly_map, totpoly); - BLI_array_reserve(mface, totpoly); + /* take care. we are _not_ calloc'ing so be sure to initialize each field */ + mface_to_poly_map = MEM_mallocN(sizeof(*mface_to_poly_map) * looptris_tot, __func__); + mface = MEM_mallocN(sizeof(*mface) * looptris_tot, __func__); mface_index = 0; mp = mpoly; @@ -2538,8 +2503,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, #ifdef USE_TESSFACE_SPEEDUP #define ML_TO_MF(i1, i2, i3) \ - BLI_array_grow_one(mface_to_poly_map); \ - BLI_array_grow_one(mface); \ mface_to_poly_map[mface_index] = poly_index; \ mf = &mface[mface_index]; \ /* set loop indices, transformed to vert indices later */ \ @@ -2549,12 +2512,11 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, mf->v4 = 0; \ mf->mat_nr = mp->mat_nr; \ mf->flag = mp->flag; \ + mf->edcode = 0; \ (void)0 /* ALMOST IDENTICAL TO DEFINE ABOVE (see EXCEPTION) */ #define ML_TO_MF_QUAD() \ - BLI_array_grow_one(mface_to_poly_map); \ - BLI_array_grow_one(mface); \ mface_to_poly_map[mface_index] = poly_index; \ mf = &mface[mface_index]; \ /* set loop indices, transformed to vert indices later */ \ @@ -2564,7 +2526,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, mf->v4 = mp->loopstart + 3; /* EXCEPTION */ \ mf->mat_nr = mp->mat_nr; \ mf->flag = mp->flag; \ - mf->edcode |= TESSFACE_IS_QUAD; /* EXCEPTION */ \ + mf->edcode = TESSFACE_IS_QUAD; /* EXCEPTION */ \ (void)0 @@ -2607,29 +2569,26 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert_first); totfilltri = BLI_scanfill_calc(&sf_ctx, 0); - if (totfilltri) { - BLI_array_grow_items(mface_to_poly_map, totfilltri); - BLI_array_grow_items(mface, totfilltri); + BLI_assert(totfilltri <= mp->totloop - 2); - for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next, mf++) { - mface_to_poly_map[mface_index] = poly_index; - mf = &mface[mface_index]; + for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next, mf++) { + mface_to_poly_map[mface_index] = poly_index; + mf = &mface[mface_index]; - /* set loop indices, transformed to vert indices later */ - mf->v1 = sf_tri->v1->keyindex; - mf->v2 = sf_tri->v2->keyindex; - mf->v3 = sf_tri->v3->keyindex; - mf->v4 = 0; + /* set loop indices, transformed to vert indices later */ + mf->v1 = sf_tri->v1->keyindex; + mf->v2 = sf_tri->v2->keyindex; + mf->v3 = sf_tri->v3->keyindex; + mf->v4 = 0; - mf->mat_nr = mp->mat_nr; - mf->flag = mp->flag; + mf->mat_nr = mp->mat_nr; + mf->flag = mp->flag; #ifdef USE_TESSFACE_SPEEDUP - mf->edcode |= TESSFACE_SCANFILL; /* tag for sorting loop indices */ + mf->edcode = TESSFACE_SCANFILL; /* tag for sorting loop indices */ #endif - mface_index++; - } + mface_index++; } BLI_scanfill_end(&sf_ctx); @@ -2639,9 +2598,10 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData_free(fdata, totface); totface = mface_index; + BLI_assert(totface <= looptris_tot); /* not essential but without this we store over-alloc'd memory in the CustomData layers */ - if (LIKELY((MEM_allocN_len(mface) / sizeof(*mface)) != totface)) { + if (LIKELY(looptris_tot != totface)) { mface = MEM_reallocN(mface, sizeof(*mface) * totface); mface_to_poly_map = MEM_reallocN(mface_to_poly_map, sizeof(*mface_to_poly_map) * totface); } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 4156b5b4367..69e368f0d08 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1325,7 +1325,7 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip) bConstraint *con; for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) { bFollowTrackConstraint *data = (bFollowTrackConstraint *) con->data; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 06d7cf55d49..b12463daf72 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -379,7 +379,7 @@ void multires_force_update(Object *ob) ob->derivedFinal = NULL; } if (ob->sculpt && ob->sculpt->pbvh) { - BLI_pbvh_free(ob->sculpt->pbvh); + BKE_pbvh_free(ob->sculpt->pbvh); ob->sculpt->pbvh = NULL; } } @@ -1407,7 +1407,7 @@ void multires_stitch_grids(Object *ob) int totface; if (ccgdm->pbvh) { - BLI_pbvh_get_grid_updates(ccgdm->pbvh, 0, (void ***)&faces, &totface); + BKE_pbvh_get_grid_updates(ccgdm->pbvh, 0, (void ***)&faces, &totface); if (totface) { ccgSubSurf_stitchFaces(ccgdm->ss, 0, faces, totface); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 8babdf2402f..84e280034ed 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1161,11 +1161,11 @@ void ntreeSetOutput(bNodeTree *ntree) bNodeTree *ntreeFromID(ID *id) { switch (GS(id->name)) { - case ID_MA: return ((Material*)id)->nodetree; - case ID_LA: return ((Lamp*)id)->nodetree; - case ID_WO: return ((World*)id)->nodetree; - case ID_TE: return ((Tex*)id)->nodetree; - case ID_SCE: return ((Scene*)id)->nodetree; + case ID_MA: return ((Material *)id)->nodetree; + case ID_LA: return ((Lamp *)id)->nodetree; + case ID_WO: return ((World *)id)->nodetree; + case ID_TE: return ((Tex *)id)->nodetree; + case ID_SCE: return ((Scene *)id)->nodetree; default: return NULL; } } @@ -2323,6 +2323,7 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_layer_weight(ttype); register_node_type_sh_tex_coord(ttype); register_node_type_sh_particle_info(ttype); + register_node_type_sh_hair_info(ttype); register_node_type_sh_bump(ttype); register_node_type_sh_script(ttype); register_node_type_sh_tangent(ttype); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d13d456a183..5a22973164e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -268,14 +268,44 @@ void free_sculptsession_deformMats(SculptSession *ss) ss->deform_imats = NULL; } +/* Write out the sculpt dynamic-topology BMesh to the Mesh */ +void sculptsession_bm_to_me(struct Object *ob, int reorder) +{ + if (ob && ob->sculpt) { + SculptSession *ss = ob->sculpt; + + if (ss->bm) { + if (ob->data) { + BMIter iter; + BMFace *efa; + BM_ITER_MESH (efa, &iter, ss->bm, BM_FACES_OF_MESH) { + BM_elem_flag_set(efa, BM_ELEM_SMOOTH, + ss->bm_smooth_shading); + } + if (reorder) + BM_log_mesh_elems_reorder(ss->bm, ss->bm_log); + BM_mesh_bm_to_me(ss->bm, ob->data, FALSE); + } + } + } +} + void free_sculptsession(Object *ob) { if (ob && ob->sculpt) { SculptSession *ss = ob->sculpt; DerivedMesh *dm = ob->derivedFinal; + if (ss->bm) { + sculptsession_bm_to_me(ob, TRUE); + BM_mesh_free(ss->bm); + } + if (ss->pbvh) - BLI_pbvh_free(ss->pbvh); + BKE_pbvh_free(ss->pbvh); + if (ss->bm_log) + BM_log_free(ss->bm_log); + if (dm && dm->getPBVH) dm->getPBVH(NULL, dm); /* signal to clear */ @@ -353,7 +383,7 @@ void BKE_object_free(Object *ob) free_controllers(&ob->controllers); free_actuators(&ob->actuators); - free_constraints(&ob->constraints); + BKE_free_constraints(&ob->constraints); free_partdeflect(ob->pd); @@ -438,7 +468,7 @@ void BKE_object_unlink(Object *ob) bPoseChannel *pchan; for (pchan = obt->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -469,7 +499,7 @@ void BKE_object_unlink(Object *ob) sca_remove_ob_poin(obt, ob); for (con = obt->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -1143,7 +1173,7 @@ static void copy_object_pose(Object *obn, Object *ob) } for (con = chan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = constraint_get_typeinfo(con); + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -1243,7 +1273,7 @@ static Object *object_copy_do(Object *ob, int copy_caches) BKE_pose_rebuild(obn, obn->data); } defgroup_copy_list(&obn->defbase, &ob->defbase); - copy_constraints(&obn->constraints, &ob->constraints, TRUE); + BKE_copy_constraints(&obn->constraints, &ob->constraints, TRUE); obn->mode = 0; obn->sculpt = NULL; @@ -2127,9 +2157,9 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) { bConstraintOb *cob; - cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); - solve_constraints(&ob->constraints, cob, ctime); - constraints_clear_evalob(cob); + cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + BKE_solve_constraints(&ob->constraints, cob, ctime); + BKE_constraints_clear_evalob(cob); } /* set negative scale flag in object */ @@ -2198,9 +2228,9 @@ void BKE_object_where_is_calc_simul(Scene *scene, Object *ob) if (ob->constraints.first) { bConstraintOb *cob; - cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); - solve_constraints(&ob->constraints, cob, (float)scene->r.cfra); - constraints_clear_evalob(cob); + cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + BKE_solve_constraints(&ob->constraints, cob, (float)scene->r.cfra); + BKE_constraints_clear_evalob(cob); } } @@ -2799,7 +2829,7 @@ void BKE_object_sculpt_modifiers_changed(Object *ob) * changing PVBH node organization, we hope topology does not change in * the meantime .. weak */ if (ss->pbvh) { - BLI_pbvh_free(ss->pbvh); + BKE_pbvh_free(ss->pbvh); ss->pbvh = NULL; } @@ -2809,10 +2839,10 @@ void BKE_object_sculpt_modifiers_changed(Object *ob) PBVHNode **nodes; int n, totnode; - BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); + BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); for (n = 0; n < totnode; n++) - BLI_pbvh_node_mark_update(nodes[n]); + BKE_pbvh_node_mark_update(nodes[n]); MEM_freeN(nodes); } @@ -2965,12 +2995,13 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, int } else { /* copy from current values */ - float *data = do_ob_key(scene, ob); + int totelem; + float *data = BKE_key_evaluate_object(scene, ob, &totelem); /* create new block with prepared data */ kb = BKE_keyblock_add_ctime(key, name, FALSE); kb->data = data; - kb->totelem = me->totvert; + kb->totelem = totelem; } return kb; @@ -3002,11 +3033,12 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int } else { /* copy from current values */ - float *data = do_ob_key(scene, ob); + int totelem; + float *data = BKE_key_evaluate_object(scene, ob, &totelem); /* create new block with prepared data */ kb = BKE_keyblock_add_ctime(key, name, FALSE); - kb->totelem = lt->pntsu * lt->pntsv * lt->pntsw; + kb->totelem = totelem; kb->data = data; } @@ -3041,11 +3073,12 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int } else { /* copy from current values */ - float *data = do_ob_key(scene, ob); + int totelem; + float *data = BKE_key_evaluate_object(scene, ob, &totelem); /* create new block with prepared data */ kb = BKE_keyblock_add_ctime(key, name, FALSE); - kb->totelem = BKE_nurbList_verts_count(lb); + kb->totelem = totelem; kb->data = data; } @@ -3148,11 +3181,11 @@ void BKE_object_relink(Object *ob) if (ob->id.lib) return; - relink_constraints(&ob->constraints); + BKE_relink_constraints(&ob->constraints); if (ob->pose) { bPoseChannel *chan; for (chan = ob->pose->chanbase.first; chan; chan = chan->next) { - relink_constraints(&chan->constraints); + BKE_relink_constraints(&chan->constraints); } } modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL); diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index e694a7e7eb3..c4274aa1f93 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -35,16 +35,15 @@ #include "DNA_scene_types.h" +#include "BKE_global.h" /* XXX TESTING */ #include "BKE_image.h" #include "BKE_ocean.h" -#include "BKE_global.h" // XXX TESTING -#include "BLI_math_base.h" -#include "BLI_math_inline.h" +#include "BLI_math.h" +#include "BLI_path_util.h" #include "BLI_rand.h" #include "BLI_string.h" #include "BLI_threads.h" -#include "BLI_path_util.h" #include "BLI_utildefines.h" #include "IMB_imbuf.h" @@ -54,7 +53,7 @@ #ifdef WITH_OCEANSIM -// Ocean code +/* Ocean code */ #include "fftw3.h" #define GRAVITY 9.81f @@ -82,7 +81,7 @@ typedef struct Ocean { float _Lx; float _Lz; - float normalize_factor; // init w + float normalize_factor; /* init w */ float time; short _do_disp_y; @@ -96,51 +95,52 @@ typedef struct Ocean { /* ********* sim data arrays ********* */ /* two dimensional arrays of complex */ - fftw_complex *_fft_in; // init w sim w - fftw_complex *_fft_in_x; // init w sim w - fftw_complex *_fft_in_z; // init w sim w - fftw_complex *_fft_in_jxx; // init w sim w - fftw_complex *_fft_in_jzz; // init w sim w - fftw_complex *_fft_in_jxz; // init w sim w - fftw_complex *_fft_in_nx; // init w sim w - fftw_complex *_fft_in_nz; // init w sim w - fftw_complex *_htilda; // init w sim w (only once) + fftw_complex *_fft_in; /* init w sim w */ + fftw_complex *_fft_in_x; /* init w sim w */ + fftw_complex *_fft_in_z; /* init w sim w */ + fftw_complex *_fft_in_jxx; /* init w sim w */ + fftw_complex *_fft_in_jzz; /* init w sim w */ + fftw_complex *_fft_in_jxz; /* init w sim w */ + fftw_complex *_fft_in_nx; /* init w sim w */ + fftw_complex *_fft_in_nz; /* init w sim w */ + fftw_complex *_htilda; /* init w sim w (only once) */ /* fftw "plans" */ - fftw_plan _disp_y_plan; // init w sim r - fftw_plan _disp_x_plan; // init w sim r - fftw_plan _disp_z_plan; // init w sim r - fftw_plan _N_x_plan; // init w sim r - fftw_plan _N_z_plan; // init w sim r - fftw_plan _Jxx_plan; // init w sim r - fftw_plan _Jxz_plan; // init w sim r - fftw_plan _Jzz_plan; // init w sim r + fftw_plan _disp_y_plan; /* init w sim r */ + fftw_plan _disp_x_plan; /* init w sim r */ + fftw_plan _disp_z_plan; /* init w sim r */ + fftw_plan _N_x_plan; /* init w sim r */ + fftw_plan _N_z_plan; /* init w sim r */ + fftw_plan _Jxx_plan; /* init w sim r */ + fftw_plan _Jxz_plan; /* init w sim r */ + fftw_plan _Jzz_plan; /* init w sim r */ /* two dimensional arrays of float */ - double *_disp_y; // init w sim w via plan? - double *_N_x; // init w sim w via plan? - /*float * _N_y; all member of this array has same values, so convert this array to a float to reduce memory usage (MEM01)*/ - 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? - double *_disp_z; // init w sim w via plan? + double *_disp_y; /* init w sim w via plan? */ + 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; */ + 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? */ + double *_disp_z; /* init w sim w via plan? */ /* two dimensional arrays of float */ /* Jacobian and minimum eigenvalue */ - double *_Jxx; // init w sim w - double *_Jzz; // init w sim w - double *_Jxz; // init w sim w + double *_Jxx; /* init w sim w */ + double *_Jzz; /* init w sim w */ + double *_Jxz; /* init w sim w */ /* one dimensional float array */ - float *_kx; // init w sim r - float *_kz; // init w sim r + float *_kx; /* init w sim r */ + float *_kz; /* init w sim r */ /* two dimensional complex array */ - fftw_complex *_h0; // init w sim r - fftw_complex *_h0_minus; // init w sim r + fftw_complex *_h0; /* init w sim r */ + fftw_complex *_h0_minus; /* init w sim r */ /* two dimensional float array */ - float *_k; // init w sim r + float *_k; /* init w sim r */ } Ocean; @@ -152,10 +152,13 @@ static float nextfr(float min, float max) static float gaussRand(void) { - float x; // Note: to avoid numerical problems with very small - float y; // numbers, we make these variables singe-precision - float length2; // floats, but later we call the double-precision log() - // and sqrt() functions instead of logf() and sqrtf(). + /* Note: to avoid numerical problems with very small numbers, we make these variables singe-precision floats, + * but later we call the double-precision log() and sqrt() functions instead of logf() and sqrtf(). + */ + float x; + float y; + float length2; + do { x = (float) (nextfr(-1, 1)); y = (float)(nextfr(-1, 1)); @@ -167,12 +170,7 @@ static float gaussRand(void) /** * Some useful functions - * */ -MINLINE float lerp(float a, float b, float f) -{ - return a + (b - a) * f; -} - + */ MINLINE float catrom(float p0, float p1, float p2, float p3, float f) { return 0.5f * ((2.0f * p1) + @@ -186,23 +184,24 @@ MINLINE float omega(float k, float depth) return sqrtf(GRAVITY * k * tanhf(k * depth)); } -// modified Phillips spectrum +/* modified Phillips spectrum */ static float Ph(struct Ocean *o, float kx, float kz) { float tmp; float k2 = kx * kx + kz * kz; if (k2 == 0.0f) { - return 0.0f; // no DC component + return 0.0f; /* no DC component */ } - // damp out the waves going in the direction opposite the wind + /* damp out the waves going in the direction opposite the wind */ tmp = (o->_wx * kx + o->_wz * kz) / sqrtf(k2); if (tmp < 0) { tmp *= o->_damp_reflections; } - return o->_A * expf(-1.0f / (k2 * (o->_L * o->_L))) * expf(-k2 * (o->_l * o->_l)) * powf(fabsf(tmp), o->_wind_alignment) / (k2 * k2); + return o->_A * expf(-1.0f / (k2 * (o->_L * o->_L))) * expf(-k2 * (o->_l * o->_l)) * + powf(fabsf(tmp), o->_wind_alignment) / (k2 * k2); } static void compute_eigenstuff(struct OceanResult *ocr, float jxx, float jzz, float jxz) @@ -240,7 +239,7 @@ static void init_complex(fftw_complex cmpl, float real, float image) cmpl[1] = image; } -#if 0 // unused +#if 0 /* unused */ static void add_complex_f(fftw_complex res, fftw_complex cmpl, float f) { res[0] = cmpl[0] + f; @@ -306,7 +305,7 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float float frac_x, frac_z; float uu, vv; - // first wrap the texture so 0 <= (u, v) < 1 + /* first wrap the texture so 0 <= (u, v) < 1 */ u = fmodf(u, 1.0f); v = fmodf(v, 1.0f); @@ -334,7 +333,9 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float j1 = j1 % oc->_N; -#define BILERP(m) (lerp(lerp(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], frac_x), lerp(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], frac_x), frac_z)) +#define BILERP(m) (interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \ + interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \ + frac_z)) { if (oc->_do_disp_y) { ocr->disp[1] = BILERP(oc->_disp_y); @@ -364,14 +365,14 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float BLI_rw_mutex_unlock(&oc->oceanmutex); } -// use catmullrom interpolation rather than linear +/* use catmullrom interpolation rather than linear */ void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u, float v) { int i0, i1, i2, i3, j0, j1, j2, j3; float frac_x, frac_z; float uu, vv; - // first wrap the texture so 0 <= (u, v) < 1 + /* first wrap the texture so 0 <= (u, v) < 1 */ u = fmod(u, 1.0f); v = fmod(v, 1.0f); @@ -408,11 +409,15 @@ void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u j0 = j0 < 0 ? j0 + oc->_N : j0; j3 = j3 >= oc->_N ? j3 - oc->_N : j3; -#define INTERP(m) catrom(catrom(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], m[i2 * oc->_N + j0], m[i3 * oc->_N + j0], frac_x), \ - catrom(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], m[i2 * oc->_N + j1], m[i3 * oc->_N + j1], frac_x), \ - catrom(m[i0 * oc->_N + j2], m[i1 * oc->_N + j2], m[i2 * oc->_N + j2], m[i3 * oc->_N + j2], frac_x), \ - catrom(m[i0 * oc->_N + j3], m[i1 * oc->_N + j3], m[i2 * oc->_N + j3], m[i3 * oc->_N + j3], frac_x), \ - frac_z) +#define INTERP(m) catrom(catrom(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], \ + m[i2 * oc->_N + j0], m[i3 * oc->_N + j0], frac_x), \ + catrom(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], \ + m[i2 * oc->_N + j1], m[i3 * oc->_N + j1], frac_x), \ + catrom(m[i0 * oc->_N + j2], m[i1 * oc->_N + j2], \ + m[i2 * oc->_N + j2], m[i3 * oc->_N + j2], frac_x), \ + catrom(m[i0 * oc->_N + j3], m[i1 * oc->_N + j3], \ + m[i2 * oc->_N + j3], m[i3 * oc->_N + j3], frac_x), \ + frac_z) { if (oc->_do_disp_y) { @@ -452,9 +457,9 @@ void BKE_ocean_eval_xz_catrom(struct Ocean *oc, struct OceanResult *ocr, float x BKE_ocean_eval_uv_catrom(oc, ocr, x / oc->_Lx, z / oc->_Lz); } -// note that this doesn't wrap properly for i, j < 0, but its -// not really meant for that being just a way to get the raw data out -// to save in some image format. +/* note that this doesn't wrap properly for i, j < 0, but its not really meant for that being just a way to get + * the raw data out to save in some image format. + */ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j) { BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ); @@ -496,11 +501,10 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); - // compute a new htilda + /* compute a new htilda */ #pragma omp parallel for private(i, j) for (i = 0; i < o->_M; ++i) { - // note the <= _N/2 here, see the fftw doco about - // the mechanics of the complex->real fft storage + /* note the <= _N/2 here, see the fftw doco about the mechanics of the complex->real fft storage */ for (j = 0; j <= o->_N / 2; ++j) { fftw_complex exp_param1; fftw_complex exp_param2; @@ -527,15 +531,15 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount #pragma omp section { if (o->_do_disp_y) { - // y displacement + /* y displacement */ fftw_execute(o->_disp_y_plan); } - } // section 1 + } /* section 1 */ #pragma omp section { if (o->_do_chop) { - // x displacement + /* x displacement */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; @@ -546,18 +550,21 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, minus_i); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, + ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ? + 0.0f : + o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } fftw_execute(o->_disp_x_plan); } - } //section 2 + } /* section 2 */ #pragma omp section { if (o->_do_chop) { - // z displacement + /* z displacement */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; @@ -568,28 +575,34 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, minus_i); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, + ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ? + 0.0f : + o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } fftw_execute(o->_disp_z_plan); } - } // section 3 + } /* section 3 */ #pragma omp section { if (o->_do_jacobian) { - // Jxx + /* Jxx */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; - //init_complex(mul_param, -scale, 0); + /* init_complex(mul_param, -scale, 0); */ init_complex(mul_param, -1, 0); mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, + ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ? + 0.0f : + o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -601,22 +614,25 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount } } } - } // section 4 + } /* section 4 */ #pragma omp section { if (o->_do_jacobian) { - // Jzz + /* Jzz */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; - //init_complex(mul_param, -scale, 0); + /* init_complex(mul_param, -scale, 0); */ init_complex(mul_param, -1, 0); mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, + ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ? + 0.0f : + o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -627,32 +643,35 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount } } } - } // section 5 + } /* section 5 */ #pragma omp section { if (o->_do_jacobian) { - // Jxz + /* Jxz */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; - //init_complex(mul_param, -scale, 0); + /* init_complex(mul_param, -scale, 0); */ init_complex(mul_param, -1, 0); mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, + ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ? + 0.0f : + o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jxz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } fftw_execute(o->_Jxz_plan); } - } // section 6 + } /* section 6 */ #pragma omp section { - // fft normals + /* fft normals */ if (o->_do_normals) { for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { @@ -667,7 +686,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount fftw_execute(o->_N_x_plan); } - } // section 7 + } /* section 7 */ #pragma omp section { @@ -694,9 +713,9 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount #endif o->_N_y = 1.0f / scale; } - } // section 8 + } /* section 8 */ - } // omp sections + } /* omp sections */ BLI_rw_mutex_unlock(&o->oceanmutex); } @@ -726,7 +745,8 @@ static void set_height_normalize_factor(struct Ocean *oc) BLI_rw_mutex_unlock(&oc->oceanmutex); - if (max_h == 0.0f) max_h = 0.00001f; // just in case ... + if (max_h == 0.0f) + max_h = 0.00001f; /* just in case ... */ res = 1.0f / (max_h); @@ -743,7 +763,8 @@ struct Ocean *BKE_add_ocean(void) } void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp, - float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals, short do_jacobian, int seed) + float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals, + short do_jacobian, int seed) { int i, j, ii; @@ -761,8 +782,8 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, o->_Lx = Lx; o->_Lz = Lz; o->_wx = cos(w); - o->_wz = -sin(w); // wave direction - o->_L = V * V / GRAVITY; // largest wave for a given velocity V + o->_wz = -sin(w); /* wave direction */ + o->_L = V * V / GRAVITY; /* largest wave for a given velocity V */ o->time = time; o->_do_disp_y = do_height_field; @@ -776,30 +797,30 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, o->_kx = (float *) MEM_mallocN(o->_M * sizeof(float), "ocean_kx"); o->_kz = (float *) MEM_mallocN(o->_N * sizeof(float), "ocean_kz"); - // make this robust in the face of erroneous usage + /* make this robust in the face of erroneous usage */ if (o->_Lx == 0.0f) o->_Lx = 0.001f; if (o->_Lz == 0.0f) o->_Lz = 0.001f; - // the +ve components and DC + /* the +ve components and DC */ for (i = 0; i <= o->_M / 2; ++i) o->_kx[i] = 2.0f * (float)M_PI * i / o->_Lx; - // the -ve components + /* the -ve components */ for (i = o->_M - 1, ii = 0; i > o->_M / 2; --i, ++ii) o->_kx[i] = -2.0f * (float)M_PI * ii / o->_Lx; - // the +ve components and DC + /* the +ve components and DC */ for (i = 0; i <= o->_N / 2; ++i) o->_kz[i] = 2.0f * (float)M_PI * i / o->_Lz; - // the -ve components + /* the -ve components */ for (i = o->_N - 1, ii = 0; i > o->_N / 2; --i, ++ii) o->_kz[i] = -2.0f * (float)M_PI * ii / o->_Lz; - // pre-calculate the k matrix + /* pre-calculate the k matrix */ for (i = 0; i < o->_M; ++i) for (j = 0; j <= o->_N / 2; ++j) o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]); @@ -819,11 +840,11 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, } } - o->_fft_in = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in"); - o->_htilda = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda"); + o->_fft_in = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in"); + o->_htilda = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda"); if (o->_do_disp_y) { - o->_disp_y = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y"); + o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y"); o->_disp_y_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in, o->_disp_y, FFTW_ESTIMATE); } @@ -831,32 +852,35 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, o->_fft_in_nx = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_nx"); o->_fft_in_nz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_nz"); - o->_N_x = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x"); + o->_N_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x"); /* o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01) */ - o->_N_z = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z"); + o->_N_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z"); o->_N_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nx, o->_N_x, FFTW_ESTIMATE); o->_N_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nz, o->_N_z, FFTW_ESTIMATE); } if (o->_do_chop) { - o->_fft_in_x = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_x"); - o->_fft_in_z = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_z"); + o->_fft_in_x = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_x"); + o->_fft_in_z = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_z"); - o->_disp_x = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x"); - o->_disp_z = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z"); + o->_disp_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x"); + o->_disp_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z"); o->_disp_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_x, o->_disp_x, FFTW_ESTIMATE); o->_disp_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_z, o->_disp_z, FFTW_ESTIMATE); } if (o->_do_jacobian) { - o->_fft_in_jxx = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jxx"); - o->_fft_in_jzz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jzz"); - o->_fft_in_jxz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jxz"); + o->_fft_in_jxx = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), + "ocean_fft_in_jxx"); + o->_fft_in_jzz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), + "ocean_fft_in_jzz"); + o->_fft_in_jxz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), + "ocean_fft_in_jxz"); - o->_Jxx = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx"); - o->_Jzz = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz"); - o->_Jxz = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz"); + o->_Jxx = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx"); + o->_Jzz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz"); + o->_Jxz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz"); o->_Jxx_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxx, o->_Jxx, FFTW_ESTIMATE); o->_Jzz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jzz, o->_Jzz, FFTW_ESTIMATE); @@ -967,7 +991,7 @@ static void cache_filename(char *string, const char *path, const char *relbase, BLI_join_dirfile(cachepath, sizeof(cachepath), path, fname); - BKE_makepicstring(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, 1, TRUE); + BKE_makepicstring_from_type(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, 1, TRUE); } /* silly functions but useful to inline when the args do a lot of indirections */ @@ -1076,8 +1100,7 @@ void BKE_ocean_cache_eval_ij(struct OceanCache *och, struct OceanResult *ocr, in } } -struct OceanCache *BKE_init_ocean_cache(const char *bakepath, const char *relbase, - int start, int end, float wave_scale, +struct OceanCache *BKE_init_ocean_cache(const char *bakepath, const char *relbase, int start, int end, float wave_scale, float chop_amount, float foam_coverage, float foam_fade, int resolution) { OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data"); @@ -1112,7 +1135,7 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame) /* ibufs array is zero based, but filenames are based on frame numbers */ /* still need to clamp frame numbers to valid range of images on disk though */ CLAMP(frame, och->start, och->end); - f = frame - och->start; // shift to 0 based + f = frame - och->start; /* shift to 0 based */ /* if image is already loaded in mem, return */ if (och->ibufs_disp[f] != NULL) return; @@ -1121,22 +1144,35 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame) cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_DISPLACE); och->ibufs_disp[f] = IMB_loadiffname(string, 0, NULL); - //if (och->ibufs_disp[f] == NULL) printf("error loading %s\n", string); - //else printf("loaded cache %s\n", string); +#if 0 + if (och->ibufs_disp[f] == NULL) + printf("error loading %s\n", string); + else + printf("loaded cache %s\n", string); +#endif cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_FOAM); och->ibufs_foam[f] = IMB_loadiffname(string, 0, NULL); - //if (och->ibufs_foam[f] == NULL) printf("error loading %s\n", string); - //else printf("loaded cache %s\n", string); +#if 0 + if (och->ibufs_foam[f] == NULL) + printf("error loading %s\n", string); + else + printf("loaded cache %s\n", string); +#endif cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_NORMAL); och->ibufs_norm[f] = IMB_loadiffname(string, 0, NULL); - //if (och->ibufs_norm[f] == NULL) printf("error loading %s\n", string); - //else printf("loaded cache %s\n", string); +#if 0 + if (och->ibufs_norm[f] == NULL) + printf("error loading %s\n", string); + else + printf("loaded cache %s\n", string); +#endif } -void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), void *update_cb_data) +void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), + void *update_cb_data) { /* note: some of these values remain uninitialized unless certain options * are enabled, take care that BKE_ocean_eval_ij() initializes a member @@ -1197,13 +1233,13 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v pr = prev_foam[res_x * y + x]; } - /* r = BLI_frand(); */ /* UNUSED */ // randomly reduce foam + /* r = BLI_frand(); */ /* 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), - // and X and Z displacement is greatest + /* remember ocean coord sys is Y up! + * break up the foam where height (Y) is low (wave valley), and X and Z displacement is greatest + */ #if 0 vec[0] = ocr.disp[0]; @@ -1219,22 +1255,27 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v neg_eplus = ocr.Eplus[2] < 0.0f ? 1.0f + ocr.Eplus[2] : 1.0f; neg_eplus = neg_eplus < 0.0f ? 0.0f : neg_eplus; - //if (ocr.disp[1] < 0.0 || r > och->foam_fade) - // pr *= och->foam_fade; +#if 0 + if (ocr.disp[1] < 0.0 || r > och->foam_fade) + pr *= och->foam_fade; - //pr = pr * (1.0 - hor_stretch) * ocr.disp[1]; - //pr = pr * neg_disp * neg_eplus; + pr = pr * (1.0 - hor_stretch) * ocr.disp[1]; + pr = pr * neg_disp * neg_eplus; +#endif - if (pr < 1.0f) pr *= pr; + if (pr < 1.0f) + pr *= pr; pr *= och->foam_fade * (0.75f + neg_eplus * 0.25f); - - foam_result = pr + ocr.foam; + /* A full clamping should not be needed! */ + foam_result = min_ff(pr + ocr.foam, 1.0f); prev_foam[res_x * y + x] = foam_result; + /*foam_result = min_ff(foam_result, 1.0f); */ + value_to_rgba_unit_alpha(&ibuf_foam->rect_float[4 * (res_x * y + x)], foam_result); } @@ -1279,7 +1320,7 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v och->baked = 1; } -#else // WITH_OCEANSIM +#else /* WITH_OCEANSIM */ /* stub */ typedef struct Ocean { @@ -1297,8 +1338,9 @@ void BKE_ocean_eval_uv(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr) { } -// use catmullrom interpolation rather than linear -void BKE_ocean_eval_uv_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(u), float UNUSED(v)) +/* use catmullrom interpolation rather than linear */ +void BKE_ocean_eval_uv_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(u), + float UNUSED(v)) { } @@ -1306,7 +1348,8 @@ void BKE_ocean_eval_xz(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr) { } -void BKE_ocean_eval_xz_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(x), float UNUSED(z)) +void BKE_ocean_eval_xz_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(x), + float UNUSED(z)) { } @@ -1325,8 +1368,10 @@ struct Ocean *BKE_add_ocean(void) return oc; } -void BKE_init_ocean(struct Ocean *UNUSED(o), int UNUSED(M), int UNUSED(N), float UNUSED(Lx), float UNUSED(Lz), float UNUSED(V), float UNUSED(l), float UNUSED(A), float UNUSED(w), float UNUSED(damp), - float UNUSED(alignment), float UNUSED(depth), float UNUSED(time), short UNUSED(do_height_field), short UNUSED(do_chop), short UNUSED(do_normals), short UNUSED(do_jacobian), int UNUSED(seed)) +void BKE_init_ocean(struct Ocean *UNUSED(o), int UNUSED(M), int UNUSED(N), float UNUSED(Lx), float UNUSED(Lz), + float UNUSED(V), float UNUSED(l), float UNUSED(A), float UNUSED(w), float UNUSED(damp), + float UNUSED(alignment), float UNUSED(depth), float UNUSED(time), short UNUSED(do_height_field), + short UNUSED(do_chop), short UNUSED(do_normals), short UNUSED(do_jacobian), int UNUSED(seed)) { } @@ -1351,17 +1396,19 @@ void BKE_free_ocean_cache(struct OceanCache *och) MEM_freeN(och); } -void BKE_ocean_cache_eval_uv(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f), float UNUSED(u), float UNUSED(v)) +void BKE_ocean_cache_eval_uv(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f), + float UNUSED(u), float UNUSED(v)) { } -void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f), int UNUSED(i), int UNUSED(j)) +void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f), + int UNUSED(i), int UNUSED(j)) { } -OceanCache *BKE_init_ocean_cache(const char *UNUSED(bakepath), const char *UNUSED(relbase), - int UNUSED(start), int UNUSED(end), float UNUSED(wave_scale), - float UNUSED(chop_amount), float UNUSED(foam_coverage), float UNUSED(foam_fade), int UNUSED(resolution)) +OceanCache *BKE_init_ocean_cache(const char *UNUSED(bakepath), const char *UNUSED(relbase), int UNUSED(start), + int UNUSED(end), float UNUSED(wave_scale), float UNUSED(chop_amount), + float UNUSED(foam_coverage), float UNUSED(foam_fade), int UNUSED(resolution)) { OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data"); @@ -1372,9 +1419,10 @@ void BKE_simulate_ocean_cache(struct OceanCache *UNUSED(och), int UNUSED(frame)) { } -void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och), void (*update_cb)(void *, float progress, int *cancel), void *UNUSED(update_cb_data)) +void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och), + void (*update_cb)(void *, float progress, int *cancel), void *UNUSED(update_cb_data)) { /* unused */ (void)update_cb; } -#endif // WITH_OCEANSIM +#endif /* WITH_OCEANSIM */
\ No newline at end of file diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index dec49f417ae..9f77094994d 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -43,6 +43,7 @@ #include "MEM_guardedalloc.h" #include "DNA_image_types.h" +#include "DNA_ID.h" #include "DNA_sound_types.h" #include "DNA_vfont_types.h" #include "DNA_packedFile_types.h" @@ -226,6 +227,7 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char return (pf); } +/* no libraries for now */ void packAll(Main *bmain, ReportList *reports) { Image *ima; @@ -538,6 +540,41 @@ int unpackImage(ReportList *reports, Image *ima, int how) return(ret_value); } +int unpackLibraries(Main *bmain, ReportList *reports) +{ + Library *lib; + char *newname; + int ret_value = RET_ERROR; + + for (lib = bmain->library.first; lib; lib = lib->id.next) { + if (lib->packedfile && lib->name[0]) { + + newname = unpackFile(reports, lib->filepath, lib->filepath, lib->packedfile, PF_WRITE_ORIGINAL); + if (newname != NULL) { + ret_value = RET_OK; + + printf("Saved .blend library: %s\n", newname); + + freePackedFile(lib->packedfile); + lib->packedfile = NULL; + + MEM_freeN(newname); + } + } + } + + return(ret_value); +} + +void packLibraries(Main *bmain, ReportList *reports) +{ + Library *lib; + + for (lib = bmain->library.first; lib; lib = lib->id.next) + if (lib->packedfile == NULL) + lib->packedfile = newPackedFile(reports, lib->name, bmain->name); +} + void unpackAll(Main *bmain, ReportList *reports, int how) { Image *ima; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index fa5268e039e..5847e7508f0 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -212,7 +212,7 @@ int paint_is_face_hidden(const MFace *f, const MVert *mvert) } /* returns non-zero if any of the corners of the grid - * face whose inner corner is at (x,y) are hidden, + * face whose inner corner is at (x, y) are hidden, * zero otherwise */ int paint_is_grid_face_hidden(const unsigned int *grid_hidden, int gridsize, int x, int y) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 090082b333d..3b897e94241 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -522,9 +522,9 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys) vec[0]/=delta[0]; vec[1]/=delta[1]; vec[2]/=delta[2]; - (pa + ((int)(vec[0] * (size[0] - 1)) * res + - (int)(vec[1] * (size[1] - 1))) * res + - (int)(vec[2] * (size[2] - 1)))->flag &= ~PARS_UNEXIST; + pa[((int)(vec[0] * (size[0] - 1)) * res + + (int)(vec[1] * (size[1] - 1))) * res + + (int)(vec[2] * (size[2] - 1))].flag &= ~PARS_UNEXIST; } } else if (ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) { diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 209461bad2f..2df2dd631d5 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -41,124 +41,12 @@ #include "GPU_buffers.h" +#include "pbvh_intern.h" + #define LEAF_LIMIT 10000 //#define PERFCNTRS -/* Axis-aligned bounding box */ -typedef struct { - float bmin[3], bmax[3]; -} BB; - -/* Axis-aligned bounding box with centroid */ -typedef struct { - float bmin[3], bmax[3], bcentroid[3]; -} BBC; - -struct PBVHNode { - /* Opaque handle for drawing code */ - GPU_Buffers *draw_buffers; - - /* Voxel bounds */ - BB vb; - BB orig_vb; - - /* For internal nodes, the offset of the children in the PBVH - * 'nodes' array. */ - int children_offset; - - /* Pointer into the PBVH prim_indices array and the number of - * primitives used by this leaf node. - * - * Used for leaf nodes in both mesh- and multires-based PBVHs. - */ - int *prim_indices; - unsigned int totprim; - - /* Array of indices into the mesh's MVert array. Contains the - * indices of all vertices used by faces that are within this - * node's bounding box. - * - * Note that a vertex might be used by a multiple faces, and - * these faces might be in different leaf nodes. Such a vertex - * will appear in the vert_indices array of each of those leaf - * nodes. - * - * In order to support cases where you want access to multiple - * nodes' vertices without duplication, the vert_indices array - * is ordered such that the first part of the array, up to - * index 'uniq_verts', contains "unique" vertex indices. These - * vertices might not be truly unique to this node, but if - * they appear in another node's vert_indices array, they will - * be above that node's 'uniq_verts' value. - * - * Used for leaf nodes in a mesh-based PBVH (not multires.) - */ - int *vert_indices; - unsigned int uniq_verts, face_verts; - - /* An array mapping face corners into the vert_indices - * array. The array is sized to match 'totprim', and each of - * the face's corners gets an index into the vert_indices - * array, in the same order as the corners in the original - * MFace. The fourth value should not be used if the original - * face is a triangle. - * - * Used for leaf nodes in a mesh-based PBVH (not multires.) - */ - int (*face_vert_indices)[4]; - - /* Indicates whether this node is a leaf or not; also used for - * marking various updates that need to be applied. */ - PBVHNodeFlags flag : 8; - - /* Used for raycasting: how close bb is to the ray point. */ - float tmin; - - int proxy_count; - PBVHProxyNode *proxies; -}; - -struct PBVH { - PBVHType type; - - PBVHNode *nodes; - int node_mem_count, totnode; - - int *prim_indices; - int totprim; - int totvert; - - int leaf_limit; - - /* Mesh data */ - MVert *verts; - MFace *faces; - CustomData *vdata; - - /* Grid Data */ - CCGKey gridkey; - CCGElem **grids; - DMGridAdjacency *gridadj; - void **gridfaces; - const DMFlagMat *grid_flag_mats; - int totgrid; - BLI_bitmap *grid_hidden; - - /* Only used during BVH build and update, - * don't need to remain valid after */ - BLI_bitmap vert_bitmap; - -#ifdef PERFCNTRS - int perf_modified; -#endif - - /* flag are verts/faces deformed */ - int deformed; - - int show_diffuse_color; -}; - #define STACK_FIXED_DEPTH 100 typedef struct PBVHStack { @@ -168,7 +56,7 @@ typedef struct PBVHStack { typedef struct PBVHIter { PBVH *bvh; - BLI_pbvh_SearchCallback scb; + BKE_pbvh_SearchCallback scb; void *search_data; PBVHStack *stack; @@ -178,14 +66,14 @@ typedef struct PBVHIter { int stackspace; } PBVHIter; -static void BB_reset(BB *bb) +void BB_reset(BB *bb) { bb->bmin[0] = bb->bmin[1] = bb->bmin[2] = FLT_MAX; bb->bmax[0] = bb->bmax[1] = bb->bmax[2] = -FLT_MAX; } /* Expand the bounding box to include a new coordinate */ -static void BB_expand(BB *bb, float co[3]) +void BB_expand(BB *bb, const float co[3]) { int i; for (i = 0; i < 3; ++i) { @@ -195,7 +83,7 @@ static void BB_expand(BB *bb, float co[3]) } /* Expand the bounding box to include another bounding box */ -static void BB_expand_with_bb(BB *bb, BB *bb2) +void BB_expand_with_bb(BB *bb, BB *bb2) { int i; for (i = 0; i < 3; ++i) { @@ -205,7 +93,7 @@ static void BB_expand_with_bb(BB *bb, BB *bb2) } /* Return 0, 1, or 2 to indicate the widest axis of the bounding box */ -static int BB_widest_axis(BB *bb) +int BB_widest_axis(const BB *bb) { float dim[3]; int i; @@ -227,7 +115,7 @@ static int BB_widest_axis(BB *bb) } } -static void BBC_update_centroid(BBC *bbc) +void BBC_update_centroid(BBC *bbc) { int i; for (i = 0; i < 3; ++i) @@ -244,11 +132,11 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node) if (node->flag & PBVH_Leaf) { PBVHVertexIter vd; - BLI_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL) + BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL) { BB_expand(&vb, vd.co); } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } else { BB_expand_with_bb(&vb, @@ -260,12 +148,12 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node) node->vb = vb; } -//void BLI_pbvh_node_BB_reset(PBVHNode *node) +//void BKE_pbvh_node_BB_reset(PBVHNode *node) //{ // BB_reset(&node->vb); //} // -//void BLI_pbvh_node_BB_expand(PBVHNode *node, float co[3]) +//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]) //{ // BB_expand(&node->vb, co); //} @@ -332,7 +220,7 @@ static int partition_indices_material(PBVH *bvh, int lo, int hi) } } -static void grow_nodes(PBVH *bvh, int totnode) +void pbvh_grow_nodes(PBVH *bvh, int totnode) { if (totnode > bvh->node_mem_count) { PBVHNode *prev = bvh->nodes; @@ -545,7 +433,7 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, /* Add two child nodes */ bvh->nodes[node_index].children_offset = bvh->totnode; - grow_nodes(bvh, bvh->totnode + 2); + pbvh_grow_nodes(bvh, bvh->totnode + 2); /* Update parent node bounding box */ update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count); @@ -605,7 +493,7 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim) } /* Do a full rebuild with on Mesh data structure */ -void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert, struct CustomData *vdata) +void BKE_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert, struct CustomData *vdata) { BBC *prim_bbc = NULL; BB cb; @@ -647,7 +535,7 @@ void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int } /* Do a full rebuild with on Grids data structure */ -void BLI_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, +void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, int totgrid, CCGKey *key, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap *grid_hidden) { BBC *prim_bbc = NULL; @@ -690,14 +578,14 @@ void BLI_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, MEM_freeN(prim_bbc); } -PBVH *BLI_pbvh_new(void) +PBVH *BKE_pbvh_new(void) { PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh"); return bvh; } -void BLI_pbvh_free(PBVH *bvh) +void BKE_pbvh_free(PBVH *bvh) { PBVHNode *node; int i; @@ -712,6 +600,14 @@ void BLI_pbvh_free(PBVH *bvh) MEM_freeN(node->vert_indices); if (node->face_vert_indices) MEM_freeN(node->face_vert_indices); + BKE_pbvh_node_layer_disp_free(node); + + if (node->bm_faces) + BLI_ghash_free(node->bm_faces, NULL, NULL); + if (node->bm_unique_verts) + BLI_ghash_free(node->bm_unique_verts, NULL, NULL); + if (node->bm_other_verts) + BLI_ghash_free(node->bm_other_verts, NULL, NULL); } } @@ -731,10 +627,15 @@ void BLI_pbvh_free(PBVH *bvh) if (bvh->prim_indices) MEM_freeN(bvh->prim_indices); + if (bvh->bm_vert_to_node) + BLI_ghash_free(bvh->bm_vert_to_node, NULL, NULL); + if (bvh->bm_face_to_node) + BLI_ghash_free(bvh->bm_face_to_node, NULL, NULL); + MEM_freeN(bvh); } -static void pbvh_iter_begin(PBVHIter *iter, PBVH *bvh, BLI_pbvh_SearchCallback scb, void *search_data) +static void pbvh_iter_begin(PBVHIter *iter, PBVH *bvh, BKE_pbvh_SearchCallback scb, void *search_data) { iter->bvh = bvh; iter->scb = scb; @@ -845,8 +746,8 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter) return NULL; } -void BLI_pbvh_search_gather(PBVH *bvh, - BLI_pbvh_SearchCallback scb, void *search_data, +void BKE_pbvh_search_gather(PBVH *bvh, + BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***r_array, int *r_tot) { PBVHIter iter; @@ -886,9 +787,9 @@ void BLI_pbvh_search_gather(PBVH *bvh, *r_tot = tot; } -void BLI_pbvh_search_callback(PBVH *bvh, - BLI_pbvh_SearchCallback scb, void *search_data, - BLI_pbvh_HitCallback hcb, void *hit_data) +void BKE_pbvh_search_callback(PBVH *bvh, + BKE_pbvh_SearchCallback scb, void *search_data, + BKE_pbvh_HitCallback hcb, void *hit_data) { PBVHIter iter; PBVHNode *node; @@ -929,7 +830,7 @@ static void node_tree_insert(node_tree *tree, node_tree *new_node) } } -static void traverse_tree(node_tree *tree, BLI_pbvh_HitOccludedCallback hcb, void *hit_data, float *tmin) +static void traverse_tree(node_tree *tree, BKE_pbvh_HitOccludedCallback hcb, void *hit_data, float *tmin) { if (tree->left) traverse_tree(tree->left, hcb, hit_data, tmin); @@ -953,14 +854,14 @@ static void free_tree(node_tree *tree) free(tree); } -float BLI_pbvh_node_get_tmin(PBVHNode *node) +float BKE_pbvh_node_get_tmin(PBVHNode *node) { return node->tmin; } -static void BLI_pbvh_search_callback_occluded(PBVH *bvh, - BLI_pbvh_SearchCallback scb, void *search_data, - BLI_pbvh_HitOccludedCallback hcb, void *hit_data) +static void BKE_pbvh_search_callback_occluded(PBVH *bvh, + BKE_pbvh_SearchCallback scb, void *search_data, + BKE_pbvh_HitOccludedCallback hcb, void *hit_data) { PBVHIter iter; PBVHNode *node; @@ -1011,6 +912,11 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes, float (*vnor)[3]; int n; + if (bvh->type == PBVH_BMESH) { + pbvh_bmesh_normals_update(nodes, totnode); + return; + } + if (bvh->type != PBVH_FACES) return; @@ -1104,8 +1010,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes, MEM_freeN(vnor); } -static void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, - int totnode, int flag) +void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) { int n; @@ -1152,6 +1057,11 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) node->prim_indices, node->totprim); break; + case PBVH_BMESH: + node->draw_buffers = + GPU_build_bmesh_buffers(bvh->flags & + PBVH_DYNTOPO_SMOOTH_SHADING); + break; } node->flag &= ~PBVH_RebuildDrawBuffers; @@ -1179,6 +1089,13 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) node->face_vert_indices, bvh->show_diffuse_color); break; + case PBVH_BMESH: + GPU_update_bmesh_buffers(node->draw_buffers, + bvh->bm, + node->bm_faces, + node->bm_unique_verts, + node->bm_other_verts); + break; } node->flag &= ~PBVH_UpdateDrawBuffers; @@ -1217,7 +1134,7 @@ static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag) return update; } -void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3]) +void BKE_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3]) { PBVHNode **nodes; int totnode; @@ -1225,7 +1142,7 @@ void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3]) if (!bvh->nodes) return; - BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(flag), + BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(flag), &nodes, &totnode); if (flag & PBVH_UpdateNormals) @@ -1240,7 +1157,7 @@ void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3]) if (nodes) MEM_freeN(nodes); } -void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]) +void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]) { PBVHIter iter; PBVHNode *node; @@ -1260,7 +1177,7 @@ void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]) copy_v3_v3(bb_max, bb.bmax); } -void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface) +void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface) { PBVHIter iter; PBVHNode *node; @@ -1316,36 +1233,42 @@ void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *tot /***************************** PBVH Access ***********************************/ -PBVHType BLI_pbvh_type(const PBVH *bvh) +PBVHType BKE_pbvh_type(const PBVH *bvh) { return bvh->type; } -BLI_bitmap *BLI_pbvh_grid_hidden(const PBVH *bvh) +BLI_bitmap *BKE_pbvh_grid_hidden(const PBVH *bvh) { BLI_assert(bvh->type == PBVH_GRIDS); return bvh->grid_hidden; } -void BLI_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key) +void BKE_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key) { BLI_assert(bvh->type == PBVH_GRIDS); *key = bvh->gridkey; } +BMesh *BKE_pbvh_get_bmesh(PBVH *bvh) +{ + BLI_assert(bvh->type == PBVH_BMESH); + return bvh->bm; +} + /***************************** Node Access ***********************************/ -void BLI_pbvh_node_mark_update(PBVHNode *node) +void BKE_pbvh_node_mark_update(PBVHNode *node) { node->flag |= PBVH_UpdateNormals | PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw; } -void BLI_pbvh_node_mark_rebuild_draw(PBVHNode *node) +void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node) { node->flag |= PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw; } -void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden) +void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden) { BLI_assert(node->flag & PBVH_Leaf); @@ -1355,13 +1278,13 @@ void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden) node->flag &= ~PBVH_FullyHidden; } -void BLI_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, int **vert_indices, MVert **verts) +void BKE_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, int **vert_indices, MVert **verts) { if (vert_indices) *vert_indices = node->vert_indices; if (verts) *verts = bvh->verts; } -void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *totvert) +void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *totvert) { int tot; @@ -1375,10 +1298,15 @@ void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *to if (totvert) *totvert = node->uniq_verts + node->face_verts; if (uniquevert) *uniquevert = node->uniq_verts; break; + case PBVH_BMESH: + tot = BLI_ghash_size(node->bm_unique_verts); + if (totvert) *totvert = tot + BLI_ghash_size(node->bm_other_verts); + if (uniquevert) *uniquevert = tot; + break; } } -void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int *totgrid, int *maxgrid, int *gridsize, CCGElem ***griddata, DMGridAdjacency **gridadj) +void BKE_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int *totgrid, int *maxgrid, int *gridsize, CCGElem ***griddata, DMGridAdjacency **gridadj) { switch (bvh->type) { case PBVH_GRIDS: @@ -1390,6 +1318,7 @@ void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int if (gridadj) *gridadj = bvh->gridadj; break; case PBVH_FACES: + case PBVH_BMESH: if (grid_indices) *grid_indices = NULL; if (totgrid) *totgrid = 0; if (maxgrid) *maxgrid = 0; @@ -1400,19 +1329,19 @@ void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int } } -void BLI_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3]) +void BKE_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3]) { copy_v3_v3(bb_min, node->vb.bmin); copy_v3_v3(bb_max, node->vb.bmax); } -void BLI_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3]) +void BKE_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3]) { copy_v3_v3(bb_min, node->orig_vb.bmin); copy_v3_v3(bb_max, node->orig_vb.bmax); } -void BLI_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count) +void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count) { if (node->proxy_count > 0) { if (proxies) *proxies = node->proxies; @@ -1437,14 +1366,14 @@ static int ray_aabb_intersect(PBVHNode *node, void *data_v) float bb_min[3], bb_max[3]; if (rcd->original) - BLI_pbvh_node_get_original_BB(node, bb_min, bb_max); + BKE_pbvh_node_get_original_BB(node, bb_min, bb_max); else - BLI_pbvh_node_get_BB(node, bb_min, bb_max); + BKE_pbvh_node_get_BB(node, bb_min, bb_max); return isect_ray_aabb(&rcd->ray, bb_min, bb_max, &node->tmin); } -void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data, +void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data, const float ray_start[3], const float ray_normal[3], int original) { @@ -1453,14 +1382,14 @@ void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data, isect_ray_aabb_initialize(&rcd.ray, ray_start, ray_normal); rcd.original = original; - BLI_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data); + BKE_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data); } -static int ray_face_intersection(const float ray_start[3], - const float ray_normal[3], - const float *t0, const float *t1, - const float *t2, const float *t3, - float *fdist) +int ray_face_intersection(const float ray_start[3], + const float ray_normal[3], + const float *t0, const float *t1, + const float *t2, const float *t3, + float *fdist) { float dist; @@ -1566,7 +1495,7 @@ static int pbvh_grids_node_raycast(PBVH *bvh, PBVHNode *node, return hit; } -int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], +int BKE_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco, const float ray_start[3], const float ray_normal[3], float *dist) { @@ -1584,6 +1513,9 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], hit |= pbvh_grids_node_raycast(bvh, node, origco, ray_start, ray_normal, dist); break; + case PBVH_BMESH: + hit = pbvh_bmesh_node_raycast(node, ray_start, ray_normal, dist, use_origco); + break; } return hit; @@ -1591,8 +1523,15 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], //#include <GL/glew.h> -void BLI_pbvh_node_draw(PBVHNode *node, void *setMaterial) +typedef struct { + DMSetMaterial setMaterial; + int wireframe; +} PBVHNodeDrawData; + +void BKE_pbvh_node_draw(PBVHNode *node, void *data_v) { + PBVHNodeDrawData *data = data_v; + #if 0 /* XXX: Just some quick code to show leaf nodes in different colors */ float col[3]; int i; @@ -1611,7 +1550,9 @@ void BLI_pbvh_node_draw(PBVHNode *node, void *setMaterial) #endif if (!(node->flag & PBVH_FullyHidden)) - GPU_draw_buffers(node->draw_buffers, setMaterial); + GPU_draw_buffers(node->draw_buffers, + data->setMaterial, + data->wireframe); } typedef enum { @@ -1654,19 +1595,19 @@ static PlaneAABBIsect test_planes_aabb(const float bb_min[3], return ret; } -int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data) +int BKE_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data) { float bb_min[3], bb_max[3]; - BLI_pbvh_node_get_BB(node, bb_min, bb_max); + BKE_pbvh_node_get_BB(node, bb_min, bb_max); return test_planes_aabb(bb_min, bb_max, data) != ISECT_OUTSIDE; } -int BLI_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data) +int BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data) { float bb_min[3], bb_max[3]; - BLI_pbvh_node_get_BB(node, bb_min, bb_max); + BKE_pbvh_node_get_BB(node, bb_min, bb_max); return test_planes_aabb(bb_min, bb_max, data) != ISECT_INSIDE; } @@ -1679,16 +1620,17 @@ static void pbvh_node_check_diffuse_changed(PBVH *bvh, PBVHNode *node) node->flag |= PBVH_UpdateDrawBuffers; } -void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], - DMSetMaterial setMaterial) +void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], + DMSetMaterial setMaterial, int wireframe) { + PBVHNodeDrawData draw_data = {setMaterial, wireframe}; PBVHNode **nodes; int a, totnode; for (a = 0; a < bvh->totnode; a++) pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]); - BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers), + BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers), &nodes, &totnode); pbvh_update_normals(bvh, nodes, totnode, face_nors); @@ -1697,15 +1639,15 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], if (nodes) MEM_freeN(nodes); if (planes) { - BLI_pbvh_search_callback(bvh, BLI_pbvh_node_planes_contain_AABB, - planes, BLI_pbvh_node_draw, setMaterial); + BKE_pbvh_search_callback(bvh, BKE_pbvh_node_planes_contain_AABB, + planes, BKE_pbvh_node_draw, &draw_data); } else { - BLI_pbvh_search_callback(bvh, NULL, NULL, BLI_pbvh_node_draw, setMaterial); + BKE_pbvh_search_callback(bvh, NULL, NULL, BKE_pbvh_node_draw, &draw_data); } } -void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces, +void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap *grid_hidden) { int a; @@ -1719,11 +1661,31 @@ void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, bvh->grid_hidden = grid_hidden; for (a = 0; a < bvh->totnode; ++a) - BLI_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]); + BKE_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]); + } +} + +/* Get the node's displacement layer, creating it if necessary */ +float *BKE_pbvh_node_layer_disp_get(PBVH *bvh, PBVHNode *node) +{ + if (!node->layer_disp) { + int totvert = 0; + BKE_pbvh_node_num_verts(bvh, node, &totvert, NULL); + node->layer_disp = MEM_callocN(sizeof(float) * totvert, "layer disp"); } + return node->layer_disp; } -float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3] +/* If the node has a displacement layer, free it and set to null */ +void BKE_pbvh_node_layer_disp_free(PBVHNode *node) +{ + if (node->layer_disp) { + MEM_freeN(node->layer_disp); + node->layer_disp = NULL; + } +} + +float (*BKE_pbvh_get_vertCos(PBVH * pbvh))[3] { int a; float (*vertCos)[3] = NULL; @@ -1732,7 +1694,7 @@ float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3] float *co; MVert *mvert = pbvh->verts; - vertCos = MEM_callocN(3 * pbvh->totvert * sizeof(float), "BLI_pbvh_get_vertCoords"); + vertCos = MEM_callocN(3 * pbvh->totvert * sizeof(float), "BKE_pbvh_get_vertCoords"); co = (float *)vertCos; for (a = 0; a < pbvh->totvert; a++, mvert++, co += 3) { @@ -1743,7 +1705,7 @@ float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3] return vertCos; } -void BLI_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3]) +void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3]) { int a; @@ -1772,21 +1734,21 @@ void BLI_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3]) BKE_mesh_calc_normals_tessface(pbvh->verts, pbvh->totvert, pbvh->faces, pbvh->totprim, NULL); for (a = 0; a < pbvh->totnode; ++a) - BLI_pbvh_node_mark_update(&pbvh->nodes[a]); + BKE_pbvh_node_mark_update(&pbvh->nodes[a]); - BLI_pbvh_update(pbvh, PBVH_UpdateBB, NULL); - BLI_pbvh_update(pbvh, PBVH_UpdateOriginalBB, NULL); + BKE_pbvh_update(pbvh, PBVH_UpdateBB, NULL); + BKE_pbvh_update(pbvh, PBVH_UpdateOriginalBB, NULL); } } -int BLI_pbvh_isDeformed(PBVH *pbvh) +int BKE_pbvh_isDeformed(PBVH *pbvh) { return pbvh->deformed; } /* Proxies */ -PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node) +PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node) { int index, totverts; @@ -1802,14 +1764,14 @@ PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node) else node->proxies = MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy"); - BLI_pbvh_node_num_verts(bvh, node, &totverts, NULL); + BKE_pbvh_node_num_verts(bvh, node, &totverts, NULL); node->proxies[index].co = MEM_callocN(sizeof(float[3]) * totverts, "PBVHNodeProxy.co"); } return node->proxies + index; } -void BLI_pbvh_node_free_proxies(PBVHNode *node) +void BKE_pbvh_node_free_proxies(PBVHNode *node) { #pragma omp critical { @@ -1827,7 +1789,7 @@ void BLI_pbvh_node_free_proxies(PBVHNode *node) } } -void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot) +void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot) { PBVHNode **array = NULL, **newarray, *node; int tot = 0, space = 0; @@ -1840,7 +1802,7 @@ void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot) if (tot == space) { /* resize array if needed */ space = (tot == 0) ? 32 : space * 2; - newarray = MEM_callocN(sizeof(PBVHNode) * space, "BLI_pbvh_gather_proxies"); + newarray = MEM_callocN(sizeof(PBVHNode) * space, "BKE_pbvh_gather_proxies"); if (array) { memcpy(newarray, array, sizeof(PBVHNode) * tot); @@ -1877,9 +1839,9 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, vi->fno = 0; vi->mvert = 0; - BLI_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids, NULL); - BLI_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert); - BLI_pbvh_node_get_verts(bvh, node, &vert_indices, &verts); + BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids, NULL); + BKE_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert); + BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &verts); vi->key = &bvh->gridkey; vi->grids = grids; @@ -1894,12 +1856,18 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, vi->vert_indices = vert_indices; vi->mverts = verts; + if (bvh->type == PBVH_BMESH) { + BLI_ghashIterator_init(&vi->bm_unique_verts, node->bm_unique_verts); + BLI_ghashIterator_init(&vi->bm_other_verts, node->bm_other_verts); + vi->bm_vdata = &bvh->bm->vdata; + } + vi->gh = NULL; if (vi->grids && mode == PBVH_ITER_UNIQUE) vi->grid_hidden = bvh->grid_hidden; vi->mask = NULL; - if (!vi->grids) + if (bvh->type == PBVH_FACES) vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK); } diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c new file mode 100644 index 00000000000..791288a4dda --- /dev/null +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -0,0 +1,1414 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_buffer.h" +#include "BLI_ghash.h" +#include "BLI_heap.h" +#include "BLI_math.h" + +#include "BKE_ccg.h" +#include "BKE_DerivedMesh.h" +#include "BKE_global.h" +#include "BKE_pbvh.h" + +#include "GPU_buffers.h" + +#include "bmesh.h" +#include "pbvh_intern.h" + +#include <assert.h> + +/****************************** Building ******************************/ + +/* Update node data after splitting */ +static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) +{ + GHashIterator gh_iter; + PBVHNode *n = &bvh->nodes[node_index]; + + /* Create vert hash sets */ + n->bm_unique_verts = BLI_ghash_ptr_new("bm_unique_verts"); + n->bm_other_verts = BLI_ghash_ptr_new("bm_other_verts"); + + BB_reset(&n->vb); + + GHASH_ITER (gh_iter, n->bm_faces) { + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + BMIter bm_iter; + BMVert *v; + void *node_val = SET_INT_IN_POINTER(node_index); + + /* Update ownership of faces */ + BLI_ghash_insert(bvh->bm_face_to_node, f, node_val); + + /* Update vertices */ + BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { + if (!BLI_ghash_haskey(n->bm_unique_verts, v)) { + if (BLI_ghash_haskey(bvh->bm_vert_to_node, v)) { + if (!BLI_ghash_haskey(n->bm_other_verts, v)) + BLI_ghash_insert(n->bm_other_verts, v, NULL); + } + else { + BLI_ghash_insert(n->bm_unique_verts, v, NULL); + BLI_ghash_insert(bvh->bm_vert_to_node, v, node_val); + } + } + /* Update node bounding box */ + BB_expand(&n->vb, v->co); + } + } + + BLI_assert(n->vb.bmin[0] <= n->vb.bmax[0] && + n->vb.bmin[1] <= n->vb.bmax[1] && + n->vb.bmin[2] <= n->vb.bmax[2]); + + n->orig_vb = n->vb; + + /* Build GPU buffers */ + if (!G.background) { + int smooth = bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING; + n->draw_buffers = GPU_build_bmesh_buffers(smooth); + n->flag |= PBVH_UpdateDrawBuffers; + } +} + +/* Recursively split the node if it exceeds the leaf_limit */ +static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) +{ + GHash *empty, *other; + GHashIterator gh_iter; + PBVHNode *n, *c1, *c2; + BB cb; + float mid; + int axis, children; + + n = &bvh->nodes[node_index]; + + if (BLI_ghash_size(n->bm_faces) <= bvh->leaf_limit) { + /* Node limit not exceeded */ + pbvh_bmesh_node_finalize(bvh, node_index); + return; + } + + /* Calculate bounding box around primitive centroids */ + BB_reset(&cb); + GHASH_ITER (gh_iter, n->bm_faces) { + const BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + const BBC *bbc = BLI_ghash_lookup(prim_bbc, f); + + BB_expand(&cb, bbc->bcentroid); + } + + /* Find widest axis and its midpoint */ + axis = BB_widest_axis(&cb); + mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f; + + /* Add two new child nodes */ + children = bvh->totnode; + n->children_offset = children; + pbvh_grow_nodes(bvh, bvh->totnode + 2); + + /* Array reallocated, update current node pointer */ + n = &bvh->nodes[node_index]; + + /* Initialize children */ + c1 = &bvh->nodes[children]; + c2 = &bvh->nodes[children + 1]; + c1->flag |= PBVH_Leaf; + c2->flag |= PBVH_Leaf; + c1->bm_faces = BLI_ghash_ptr_new("bm_faces"); + c2->bm_faces = BLI_ghash_ptr_new("bm_faces"); + + /* Partition the parent node's faces between the two children */ + GHASH_ITER (gh_iter, n->bm_faces) { + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + const BBC *bbc = BLI_ghash_lookup(prim_bbc, f); + + if (bbc->bcentroid[axis] < mid) + BLI_ghash_insert(c1->bm_faces, f, NULL); + else + BLI_ghash_insert(c2->bm_faces, f, NULL); + } + + /* Enforce at least one primitive in each node */ + empty = NULL; + if (BLI_ghash_size(c1->bm_faces) == 0) { + empty = c1->bm_faces; + other = c2->bm_faces; + } + else if (BLI_ghash_size(c2->bm_faces) == 0) { + empty = c2->bm_faces; + other = c1->bm_faces; + } + if (empty) { + GHASH_ITER (gh_iter, other) { + void *key = BLI_ghashIterator_getKey(&gh_iter); + BLI_ghash_insert(empty, key, NULL); + BLI_ghash_remove(other, key, NULL, NULL); + break; + } + } + + /* Clear this node */ + + /* Mark this node's unique verts as unclaimed */ + if (n->bm_unique_verts) { + GHASH_ITER (gh_iter, n->bm_unique_verts) { + BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL); + } + BLI_ghash_free(n->bm_unique_verts, NULL, NULL); + } + + /* Unclaim faces */ + GHASH_ITER (gh_iter, n->bm_faces) { + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + BLI_ghash_remove(bvh->bm_face_to_node, f, NULL, NULL); + } + BLI_ghash_free(n->bm_faces, NULL, NULL); + + if (n->bm_other_verts) + BLI_ghash_free(n->bm_other_verts, NULL, NULL); + + if (n->layer_disp) + MEM_freeN(n->layer_disp); + + n->bm_faces = NULL; + n->bm_unique_verts = NULL; + n->bm_other_verts = NULL; + n->layer_disp = NULL; + + if (n->draw_buffers) { + GPU_free_buffers(n->draw_buffers); + n->draw_buffers = NULL; + } + n->flag &= ~PBVH_Leaf; + + /* Recurse */ + c1 = c2 = NULL; + pbvh_bmesh_node_split(bvh, prim_bbc, children); + pbvh_bmesh_node_split(bvh, prim_bbc, children + 1); + + /* Array maybe reallocated, update current node pointer */ + n = &bvh->nodes[node_index]; + + /* Update bounding box */ + BB_reset(&n->vb); + BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset].vb); + BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset + 1].vb); + n->orig_vb = n->vb; +} + +/* Recursively split the node if it exceeds the leaf_limit */ +static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) +{ + GHash *prim_bbc; + GHashIterator gh_iter; + + if (BLI_ghash_size(bvh->nodes[node_index].bm_faces) <= bvh->leaf_limit) { + /* Node limit not exceeded */ + return FALSE; + } + + /* For each BMFace, store the AABB and AABB centroid */ + prim_bbc = BLI_ghash_ptr_new("prim_bbc"); + + GHASH_ITER (gh_iter, bvh->nodes[node_index].bm_faces) { + BMIter bm_iter; + BMVert *v; + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + BBC *bbc = MEM_callocN(sizeof(BBC), "BBC"); + + BB_reset((BB *)bbc); + BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { + BB_expand((BB *)bbc, v->co); + } + BBC_update_centroid(bbc); + + BLI_ghash_insert(prim_bbc, f, bbc); + } + + pbvh_bmesh_node_split(bvh, prim_bbc, node_index); + + BLI_ghash_free(prim_bbc, NULL, (void *)MEM_freeN); + + return TRUE; +} + +/**********************************************************************/ + +static PBVHNode *pbvh_bmesh_node_lookup(PBVH *bvh, GHash *map, void *key) +{ + int node_index; + + BLI_assert(BLI_ghash_haskey(map, key)); + + node_index = GET_INT_FROM_POINTER(BLI_ghash_lookup(map, key)); + BLI_assert(node_index < bvh->totnode); + + return &bvh->nodes[node_index]; +} + +static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index, + const float co[3], + const BMVert *example) +{ + BMVert *v = BM_vert_create(bvh->bm, co, example, 0); + void *val = SET_INT_IN_POINTER(node_index); + + BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode); + + BLI_ghash_insert(bvh->nodes[node_index].bm_unique_verts, v, NULL); + BLI_ghash_insert(bvh->bm_vert_to_node, v, val); + + /* Log the new vertex */ + BM_log_vert_added(bvh->bm, bvh->bm_log, v); + + return v; +} + +static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, BMVert *v1, + BMVert *v2, BMVert *v3, + const BMFace *UNUSED(example)) +{ + BMFace *f; + void *val = SET_INT_IN_POINTER(node_index); + + /* Note: passing NULL for the 'example' parameter, profiling shows + * a small performance bump */ + f = BM_face_create_quad_tri(bvh->bm, v1, v2, v3, NULL, NULL, TRUE); + if (!BLI_ghash_haskey(bvh->bm_face_to_node, f)) { + + BLI_ghash_insert(bvh->nodes[node_index].bm_faces, f, NULL); + BLI_ghash_insert(bvh->bm_face_to_node, f, val); + + /* Log the new face */ + BM_log_face_added(bvh->bm_log, f); + } + + return f; +} + +/* Return the number of faces in 'node' that use vertex 'v' */ +static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v) +{ + BMIter bm_iter; + BMFace *f; + int count = 0; + + BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { + PBVHNode *f_node; + + f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f); + + if (f_node == node) + count++; + } + + return count; +} + +/* Return a node that uses vertex 'v' other than its current owner */ +static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v) +{ + BMIter bm_iter; + BMFace *f; + PBVHNode *current_node; + + current_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v); + + BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { + PBVHNode *f_node; + + f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f); + + if (f_node != current_node) + return f_node; + } + + return NULL; +} + +static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, + BMVert *v) +{ + PBVHNode *current_owner; + + current_owner = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v); + BLI_assert(current_owner != new_owner); + + /* Remove current ownership */ + BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL); + BLI_ghash_remove(current_owner->bm_unique_verts, v, NULL, NULL); + + /* Set new ownership */ + BLI_ghash_insert(bvh->bm_vert_to_node, v, + SET_INT_IN_POINTER(new_owner - bvh->nodes)); + BLI_ghash_insert(new_owner->bm_unique_verts, v, NULL); + BLI_ghash_remove(new_owner->bm_other_verts, v, NULL, NULL); + BLI_assert(!BLI_ghash_haskey(new_owner->bm_other_verts, v)); +} + +static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v) +{ + PBVHNode *v_node; + BMIter bm_iter; + BMFace *f; + + BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v)); + v_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v); + BLI_ghash_remove(v_node->bm_unique_verts, v, NULL, NULL); + BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL); + + /* Have to check each neighboring face's node */ + BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { + PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f); + + BLI_ghash_remove(f_node->bm_unique_verts, v, NULL, NULL); + BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL); + + BLI_assert(!BLI_ghash_haskey(f_node->bm_unique_verts, v)); + BLI_assert(!BLI_ghash_haskey(f_node->bm_other_verts, v)); + } +} + +static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) +{ + PBVHNode *f_node; + BMIter bm_iter; + BMVert *v; + + f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f); + + /* Check if any of this face's vertices need to be removed + * from the node */ + BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { + if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v) == 1) { + if (BLI_ghash_lookup(f_node->bm_unique_verts, v)) { + /* Find a different node that uses 'v' */ + PBVHNode *new_node; + + new_node = pbvh_bmesh_vert_other_node_find(bvh, v); + BLI_assert(new_node || BM_vert_face_count(v) == 1); + + if (new_node) { + pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v); + } + } + else { + /* Remove from other verts */ + BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL); + } + } + } + + /* Remove face from node and top level */ + BLI_ghash_remove(f_node->bm_faces, f, NULL, NULL); + BLI_ghash_remove(bvh->bm_face_to_node, f, NULL, NULL); + + /* Log removed face */ + BM_log_face_removed(bvh->bm_log, f); +} + +static BMVert *bm_triangle_other_vert_find(BMFace *triangle, const BMVert *v1, + const BMVert *v2) +{ + BLI_assert(triangle->len == 3); + BLI_assert(v1 != v2); + + if (triangle->len == 3) { + BMIter iter; + BMVert *v, *other = NULL; + int found_v1 = FALSE, found_v2 = FALSE; + + BM_ITER_ELEM (v, &iter, triangle, BM_VERTS_OF_FACE) { + if (v == v1) + found_v1 = TRUE; + else if (v == v2) + found_v2 = TRUE; + else + other = v; + } + + if (found_v1 && found_v2) + return other; + } + + BLI_assert(0); + return NULL; +} + +static void pbvh_bmesh_edge_faces(BLI_Buffer *buf, BMEdge *e) +{ + BLI_buffer_resize(buf, BM_edge_face_count(e)); + BM_iter_as_array(NULL, BM_FACES_OF_EDGE, e, buf->data, buf->count); +} + +/* TODO: maybe a better way to do this, if not then this should go to + * bmesh_queries */ +static int bm_face_edge_backwards(BMFace *f, BMEdge *e) +{ + BMIter bm_iter; + BMLoop *l, *l1 = NULL, *l2 = NULL; + + BM_ITER_ELEM (l, &bm_iter, f, BM_LOOPS_OF_FACE) { + if (l->v == e->v1) + l1 = l; + else if (l->v == e->v2) + l2 = l; + } + + BLI_assert(l1 && l2); + BLI_assert(l1->next == l2 || l2->next == l1); + return l2->next == l1; +} + +static void pbvh_bmesh_node_drop_orig(PBVHNode *node) +{ + if (node->bm_orco) + MEM_freeN(node->bm_orco); + if (node->bm_ortri) + MEM_freeN(node->bm_ortri); + node->bm_orco = NULL; + node->bm_ortri = NULL; + node->bm_tot_ortri = 0; +} + +/****************************** EdgeQueue *****************************/ + +typedef struct { + Heap *heap; + const float *center; + float radius_squared; + float limit_len_squared; +} EdgeQueue; + +static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) +{ + BMVert *v[3]; + float c[3]; + + /* Get closest point in triangle to sphere center */ + BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + closest_on_tri_to_point_v3(c, q->center, v[0]->co, v[1]->co, v[2]->co); + + /* Check if triangle intersects the sphere */ + return ((len_squared_v3v3(q->center, c) <= q->radius_squared)); +} + +static void edge_queue_insert(EdgeQueue *q, BLI_mempool *pool, BMEdge *e, + float priority) +{ + BMVert **pair; + + pair = BLI_mempool_alloc(pool); + pair[0] = e->v1; + pair[1] = e->v2; + BLI_heap_insert(q->heap, priority, pair); +} + +static void long_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool, + BMEdge *e) +{ + const float len_sq = BM_edge_calc_length_squared(e); + if (len_sq > q->limit_len_squared) + edge_queue_insert(q, pool, e, 1.0f / len_sq); +} + +static void short_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool, + BMEdge *e) +{ + const float len_sq = BM_edge_calc_length_squared(e); + if (len_sq < q->limit_len_squared) + edge_queue_insert(q, pool, e, len_sq); +} + +static int long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, + BMFace *f) +{ + BMIter bm_iter; + BMEdge *e; + + if (edge_queue_tri_in_sphere(q, f)) { + /* Check each edge of the face */ + BM_ITER_ELEM (e, &bm_iter, f, BM_EDGES_OF_FACE) { + long_edge_queue_edge_add(q, pool, e); + } + } + + return TRUE; +} + +static int short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, + BMFace *f) +{ + BMIter bm_iter; + BMEdge *e; + + if (edge_queue_tri_in_sphere(q, f)) { + /* Check each edge of the face */ + BM_ITER_ELEM (e, &bm_iter, f, BM_EDGES_OF_FACE) { + short_edge_queue_edge_add(q, pool, e); + } + } + + return TRUE; +} + +/* Create a priority queue containing vertex pairs connected by a long + * edge as defined by PBVH.bm_max_edge_len. + * + * Only nodes marked for topology update are checked, and in those + * nodes only edges used by a face intersecting the (center, radius) + * sphere are checked. + * + * The highest priority (lowest number) is given to the longest edge. + */ +static void long_edge_queue_create(EdgeQueue *q, BLI_mempool *pool, + PBVH *bvh, const float center[3], + float radius) +{ + int n; + + q->heap = BLI_heap_new(); + q->center = center; + q->radius_squared = radius * radius; + q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len; + + for (n = 0; n < bvh->totnode; n++) { + PBVHNode *node = &bvh->nodes[n]; + + /* Check leaf nodes marked for topology update */ + if ((node->flag & PBVH_Leaf) && + (node->flag & PBVH_UpdateTopology)) + { + GHashIterator gh_iter; + + /* Check each face */ + GHASH_ITER (gh_iter, node->bm_faces) { + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + + long_edge_queue_face_add(q, pool, f); + } + } + } +} + +/* Create a priority queue containing vertex pairs connected by a + * short edge as defined by PBVH.bm_min_edge_len. + * + * Only nodes marked for topology update are checked, and in those + * nodes only edges used by a face intersecting the (center, radius) + * sphere are checked. + * + * The highest priority (lowest number) is given to the shortest edge. + */ +static void short_edge_queue_create(EdgeQueue *q, BLI_mempool *pool, + PBVH *bvh, const float center[3], + float radius) +{ + int n; + + q->heap = BLI_heap_new(); + q->center = center; + q->radius_squared = radius * radius; + q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; + + for (n = 0; n < bvh->totnode; n++) { + PBVHNode *node = &bvh->nodes[n]; + + /* Check leaf nodes marked for topology update */ + if ((node->flag & PBVH_Leaf) && + (node->flag & PBVH_UpdateTopology)) + { + GHashIterator gh_iter; + + /* Check each face */ + GHASH_ITER (gh_iter, node->bm_faces) { + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + + short_edge_queue_face_add(q, pool, f); + } + } + } +} + +/*************************** Topology update **************************/ + +static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, + BMEdge *e, BLI_Buffer *edge_faces) +{ + BMVert *v_new; + float mid[3]; + int i, node_index; + + /* Get all faces adjacent to the edge */ + pbvh_bmesh_edge_faces(edge_faces, e); + + /* Create a new vertex in current node at the edge's midpoint */ + mid_v3_v3v3(mid, e->v1->co, e->v2->co); + + node_index = GET_INT_FROM_POINTER(BLI_ghash_lookup(bvh->bm_vert_to_node, + e->v1)); + v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1); + + /* For each face, add two new triangles and delete the original */ + for (i = 0; i < edge_faces->count; i++) { + BMFace *f_adj = BLI_buffer_at(edge_faces, BMFace *, i); + BMFace *f_new; + BMVert *opp, *v1, *v2; + void *nip; + int ni; + + BLI_assert(f_adj->len == 3); + nip = BLI_ghash_lookup(bvh->bm_face_to_node, f_adj); + ni = GET_INT_FROM_POINTER(nip); + + /* Ensure node gets redrawn */ + bvh->nodes[ni].flag |= PBVH_UpdateDrawBuffers; + + /* Find the vertex not in the edge */ + opp = bm_triangle_other_vert_find(f_adj, e->v1, e->v2); + + /* Get e->v1 and e->v2 in the order they appear in the + * existing face so that the new faces' winding orders + * match */ + v1 = e->v1; + v2 = e->v2; + if (bm_face_edge_backwards(f_adj, e)) + SWAP(BMVert *, v1, v2); + + if (ni != node_index && i == 0) + pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new); + + /* Create two new faces */ + f_new = pbvh_bmesh_face_create(bvh, ni, v1, v_new, opp, f_adj); + long_edge_queue_face_add(q, pool, f_new); + f_new = pbvh_bmesh_face_create(bvh, ni, v_new, v2, opp, f_adj); + long_edge_queue_face_add(q, pool, f_new); + + /* Delete original */ + pbvh_bmesh_face_remove(bvh, f_adj); + BM_face_kill(bvh->bm, f_adj); + + /* Ensure new vertex is in the node */ + if (!BLI_ghash_haskey(bvh->nodes[ni].bm_unique_verts, v_new) && + !BLI_ghash_haskey(bvh->nodes[ni].bm_other_verts, v_new)) + { + BLI_ghash_insert(bvh->nodes[ni].bm_other_verts, v_new, NULL); + } + + if (BM_vert_edge_count(opp) >= 9) { + BMIter bm_iter; + BMEdge *e2; + + BM_ITER_ELEM (e2, &bm_iter, opp, BM_EDGES_OF_VERT) { + long_edge_queue_edge_add(q, pool, e2); + } + } + } + + BM_edge_kill(bvh->bm, e); +} + +static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q, + BLI_mempool *pool, + BLI_Buffer *edge_faces) +{ + int any_subdivided = FALSE; + + while (!BLI_heap_is_empty(q->heap)) { + BMVert **pair = BLI_heap_popmin(q->heap); + BMEdge *e; + + /* Check that the edge still exists */ + if (!(e = BM_edge_exists(pair[0], pair[1]))) { + BLI_mempool_free(pool, pair); + continue; + } + + BLI_mempool_free(pool, pair); + pair = NULL; + + /* Check that the edge's vertices are still in the PBVH. It's + * possible that an edge collapse has deleted adjacent faces + * and the node has been split, thus leaving wire edges and + * associated vertices. */ + if (!BLI_ghash_haskey(bvh->bm_vert_to_node, e->v1) || + !BLI_ghash_haskey(bvh->bm_vert_to_node, e->v2)) + { + continue; + } + + if (BM_edge_calc_length_squared(e) <= q->limit_len_squared) + continue; + + any_subdivided = TRUE; + + pbvh_bmesh_split_edge(bvh, q, pool, e, edge_faces); + } + + return any_subdivided; +} + +static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, + BMVert *v2, GHash *deleted_verts, + BLI_Buffer *edge_faces, + BLI_Buffer *deleted_faces) +{ + BMIter bm_iter; + BMFace *f; + int i; + + /* Get all faces adjacent to the edge */ + pbvh_bmesh_edge_faces(edge_faces, e); + + /* Remove the merge vertex from the PBVH */ + pbvh_bmesh_vert_remove(bvh, v2); + + /* Remove all faces adjacent to the edge */ + for (i = 0; i < edge_faces->count; i++) { + BMFace *f_adj = BLI_buffer_at(edge_faces, BMFace *, i); + + pbvh_bmesh_face_remove(bvh, f_adj); + BM_face_kill(bvh->bm, f_adj); + } + + /* Kill the edge */ + BLI_assert(BM_edge_face_count(e) == 0); + BM_edge_kill(bvh->bm, e); + + /* For all remaining faces of v2, create a new face that is the + same except it uses v1 instead of v2 */ + /* Note: this could be done with BM_vert_splice(), but that + * requires handling other issues like duplicate edges, so doesn't + * really buy anything. */ + deleted_faces->count = 0; + BM_ITER_ELEM (f, &bm_iter, v2, BM_FACES_OF_VERT) { + BMVert *v[3]; + BMFace *existing_face; + PBVHNode *n; + int ni; + + /* Get vertices, replace use of v2 with v1 */ + BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + for (i = 0; i < 3; i++) { + if (v[i] == v2) + v[i] = v1; + } + + /* Check if a face using these vertices already exists. If so, + * skip adding this face and mark the existing one for + * deletion as well. Prevents extraneous "flaps" from being + * created. */ + if (BM_face_exists(v, 3, &existing_face)) { + BLI_assert(existing_face); + BLI_buffer_append(deleted_faces, BMFace *, existing_face); + } + else { + n = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f); + ni = n - bvh->nodes; + pbvh_bmesh_face_create(bvh, ni, v[0], v[1], v[2], f); + + /* Ensure that v1 is in the new face's node */ + if (!BLI_ghash_haskey(n->bm_unique_verts, v1) && + !BLI_ghash_haskey(n->bm_other_verts, v1)) { + BLI_ghash_insert(n->bm_other_verts, v1, NULL); + } + } + + BLI_buffer_append(deleted_faces, BMFace *, f); + } + + /* Delete the tagged faces */ + for (i = 0; i < deleted_faces->count; i++) { + BMFace *f_del = BLI_buffer_at(deleted_faces, BMFace *, i); + BMVert *v[3]; + int j; + + BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f_del, (void **)v, 3); + + /* Check if any of the face's vertices are now unused, if so + remove them from the PBVH */ + for (j = 0; j < 3; j++) { + if (v[j] != v2 && BM_vert_face_count(v[j]) == 0) { + BLI_ghash_insert(deleted_verts, v[j], NULL); + pbvh_bmesh_vert_remove(bvh, v[j]); + } + else { + v[j] = NULL; + } + } + + /* Remove the face */ + pbvh_bmesh_face_remove(bvh, f_del); + BM_face_kill(bvh->bm, f_del); + + /* Delete unused vertices */ + for (j = 0; j < 3; j++) { + if (v[j]) { + BM_log_vert_removed(bvh->bm, bvh->bm_log, v[j]); + BM_vert_kill(bvh->bm, v[j]); + } + } + } + + /* Move v1 to the midpoint of v1 and v2 */ + BM_log_vert_before_modified(bvh->bm, bvh->bm_log, v1); + mid_v3_v3v3(v1->co, v1->co, v2->co); + + /* Delete v2 */ + BLI_assert(BM_vert_face_count(v2) == 0); + BLI_ghash_insert(deleted_verts, v2, NULL); + BM_log_vert_removed(bvh->bm, bvh->bm_log, v2); + BM_vert_kill(bvh->bm, v2); +} + +static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q, + BLI_mempool *pool, + BLI_Buffer *edge_faces, + BLI_Buffer *deleted_faces) +{ + float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; + GHash *deleted_verts; + int any_collapsed = FALSE; + + deleted_verts = BLI_ghash_ptr_new("deleted_verts"); + + while (!BLI_heap_is_empty(q->heap)) { + BMVert **pair = BLI_heap_popmin(q->heap); + BMEdge *e; + BMVert *v1, *v2; + + v1 = pair[0]; + v2 = pair[1]; + BLI_mempool_free(pool, pair); + pair = NULL; + + /* Check that the vertices/edge still exist */ + if (BLI_ghash_haskey(deleted_verts, v1) || + BLI_ghash_haskey(deleted_verts, v2) || + !(e = BM_edge_exists(v1, v2))) + { + continue; + } + + /* Check that the edge's vertices are still in the PBVH. It's + * possible that an edge collapse has deleted adjacent faces + * and the node has been split, thus leaving wire edges and + * associated vertices. */ + if (!BLI_ghash_haskey(bvh->bm_vert_to_node, e->v1) || + !BLI_ghash_haskey(bvh->bm_vert_to_node, e->v2)) + { + continue; + } + + if (BM_edge_calc_length_squared(e) >= min_len_squared) + continue; + + any_collapsed = TRUE; + + pbvh_bmesh_collapse_edge(bvh, e, v1, v2, + deleted_verts, edge_faces, + deleted_faces); + } + + BLI_ghash_free(deleted_verts, NULL, NULL); + + return any_collapsed; +} + +/************************* Called from pbvh.c *************************/ + +int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], + const float ray_normal[3], float *dist, + int use_original) +{ + GHashIterator gh_iter; + int hit = 0; + + if (use_original && node->bm_tot_ortri) { + int i; + for (i = 0; i < node->bm_tot_ortri; i++) { + const int *t = node->bm_ortri[i]; + hit |= ray_face_intersection(ray_start, ray_normal, + node->bm_orco[t[0]], + node->bm_orco[t[1]], + node->bm_orco[t[2]], + NULL, dist); + } + } + else { + GHASH_ITER (gh_iter, node->bm_faces) { + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + + BLI_assert(f->len == 3); + if (f->len == 3) { + BMVert *v[3]; + + BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + hit |= ray_face_intersection(ray_start, ray_normal, + v[0]->co, + v[1]->co, + v[2]->co, + NULL, dist); + } + } + } + + return hit; +} + +void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode) +{ + int n; + + for (n = 0; n < totnode; n++) { + PBVHNode *node = nodes[n]; + GHashIterator gh_iter; + + GHASH_ITER (gh_iter, node->bm_faces) { + BM_face_normal_update(BLI_ghashIterator_getKey(&gh_iter)); + } + GHASH_ITER (gh_iter, node->bm_unique_verts) { + BM_vert_normal_update(BLI_ghashIterator_getKey(&gh_iter)); + } + } +} + +/***************************** Public API *****************************/ + +/* Build a PBVH from a BMesh */ +void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading, + BMLog *log) +{ + BMIter iter; + BMFace *f; + PBVHNode *n; + int node_index = 0; + + bvh->bm = bm; + + BKE_pbvh_bmesh_detail_size_set(bvh, 0.75); + + bvh->type = PBVH_BMESH; + bvh->bm_face_to_node = BLI_ghash_ptr_new("bm_face_to_node"); + bvh->bm_vert_to_node = BLI_ghash_ptr_new("bm_vert_to_node"); + bvh->bm_log = log; + + /* TODO: choose leaf limit better */ + bvh->leaf_limit = 100; + + if (smooth_shading) + bvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING; + + /* Start with all faces in the root node */ + n = bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode"); + bvh->totnode = 1; + n->flag = PBVH_Leaf; + n->bm_faces = BLI_ghash_ptr_new("bm_faces"); + BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) { + BLI_ghash_insert(n->bm_faces, f, NULL); + } + + /* Recursively split the node until it is under the limit; if no + * splitting occurs then finalize the existing leaf node */ + if (!pbvh_bmesh_node_limit_ensure(bvh, node_index)) + pbvh_bmesh_node_finalize(bvh, 0); +} + +/* Collapse short edges, subdivide long edges */ +int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, + const float center[3], float radius) +{ + BLI_buffer_declare_static(BMFace *, edge_faces, BLI_BUFFER_NOP, 8); + BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32); + + int modified = FALSE; + int n; + + if (mode & PBVH_Collapse) { + EdgeQueue q; + BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2, + 128, 128, 0); + short_edge_queue_create(&q, queue_pool, bvh, center, radius); + pbvh_bmesh_collapse_short_edges(bvh, &q, queue_pool, &edge_faces, + &deleted_faces); + BLI_heap_free(q.heap, NULL); + BLI_mempool_destroy(queue_pool); + } + + if (mode & PBVH_Subdivide) { + EdgeQueue q; + BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2, + 128, 128, 0); + long_edge_queue_create(&q, queue_pool, bvh, center, radius); + pbvh_bmesh_subdivide_long_edges(bvh, &q, queue_pool, &edge_faces); + BLI_heap_free(q.heap, NULL); + BLI_mempool_destroy(queue_pool); + } + + /* Unmark nodes */ + for (n = 0; n < bvh->totnode; n++) { + PBVHNode *node = &bvh->nodes[n]; + + if (node->flag & PBVH_Leaf && + node->flag & PBVH_UpdateTopology) + { + node->flag &= ~PBVH_UpdateTopology; + } + } + BLI_buffer_free(&edge_faces); + BLI_buffer_free(&deleted_faces); + + return modified; +} + +/* In order to perform operations on the original node coordinates + * (such as raycast), store the node's triangles and vertices.*/ +void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node) +{ + GHashIterator gh_iter; + int i, totvert, tottri; + + /* Skip if original coords/triangles are already saved */ + if (node->bm_orco) + return; + + totvert = (BLI_ghash_size(node->bm_unique_verts) + + BLI_ghash_size(node->bm_other_verts)); + + tottri = BLI_ghash_size(node->bm_faces); + + node->bm_orco = MEM_mallocN(sizeof(*node->bm_orco) * totvert, AT); + node->bm_ortri = MEM_mallocN(sizeof(*node->bm_ortri) * tottri, AT); + + /* Copy out the vertices and assign a temporary index */ + i = 0; + GHASH_ITER (gh_iter, node->bm_unique_verts) { + BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + copy_v3_v3(node->bm_orco[i], v->co); + BM_elem_index_set(v, i); /* set_dirty! */ + i++; + } + GHASH_ITER (gh_iter, node->bm_other_verts) { + BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + copy_v3_v3(node->bm_orco[i], v->co); + BM_elem_index_set(v, i); /* set_dirty! */ + i++; + } + + /* Copy the triangles */ + i = 0; + GHASH_ITER (gh_iter, node->bm_faces) { + BMIter bm_iter; + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + BMVert *v; + int j = 0; + + BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { + node->bm_ortri[i][j] = BM_elem_index_get(v); + j++; + } + i++; + } + node->bm_tot_ortri = i; +} + +void BKE_pbvh_bmesh_after_stroke(PBVH *bvh) +{ + int i; + for (i = 0; i < bvh->totnode; i++) { + PBVHNode *n = &bvh->nodes[i]; + if (n->flag & PBVH_Leaf) { + /* Free orco/ortri data */ + pbvh_bmesh_node_drop_orig(n); + + /* Recursively split nodes that have gotten too many + * elements */ + pbvh_bmesh_node_limit_ensure(bvh, i); + } + } +} + +void BKE_pbvh_bmesh_detail_size_set(PBVH *bvh, float detail_size) +{ + bvh->bm_max_edge_len = detail_size; + bvh->bm_min_edge_len = bvh->bm_max_edge_len * 0.4f; +} + +void BKE_pbvh_node_mark_topology_update(PBVHNode *node) +{ + node->flag |= PBVH_UpdateTopology; +} + +GHash *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node) +{ + return node->bm_unique_verts; +} + +GHash *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node) +{ + return node->bm_other_verts; +} + +/****************************** Debugging *****************************/ + +#if 0 +void bli_ghash_duplicate_key_check(GHash *gh) +{ + GHashIterator gh_iter1, gh_iter2; + + GHASH_ITER (gh_iter1, gh) { + void *key1 = BLI_ghashIterator_getKey(&gh_iter1); + int dup = -1; + + GHASH_ITER (gh_iter2, gh) { + void *key2 = BLI_ghashIterator_getKey(&gh_iter2); + + if (key1 == key2) { + dup++; + if (dup > 0) { + BLI_assert(!"duplicate in hash"); + } + } + } + } +} + +void bmesh_print(BMesh *bm) +{ + BMIter iter, siter; + BMVert *v; + BMEdge *e; + BMFace *f; + BMLoop *l; + + fprintf(stderr, "\nbm=%p, totvert=%d, totedge=%d, " + "totloop=%d, totface=%d\n", + bm, bm->totvert, bm->totedge, + bm->totloop, bm->totface); + + fprintf(stderr, "vertices:\n"); + BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) { + fprintf(stderr, " %d co=(%.3f %.3f %.3f) oflag=%x\n", + BM_elem_index_get(v), v->co[0], v->co[1], v->co[2], + v->oflags[bm->stackdepth - 1].f); + } + + fprintf(stderr, "edges:\n"); + BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) { + fprintf(stderr, " %d v1=%d, v2=%d, oflag=%x\n", + BM_elem_index_get(e), + BM_elem_index_get(e->v1), + BM_elem_index_get(e->v2), + e->oflags[bm->stackdepth - 1].f); + } + + fprintf(stderr, "faces:\n"); + BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) { + fprintf(stderr, " %d len=%d, oflag=%x\n", + BM_elem_index_get(f), f->len, + f->oflags[bm->stackdepth - 1].f); + + fprintf(stderr, " v: "); + BM_ITER_ELEM(v, &siter, f, BM_VERTS_OF_FACE) { + fprintf(stderr, "%d ", BM_elem_index_get(v)); + } + fprintf(stderr, "\n"); + + fprintf(stderr, " e: "); + BM_ITER_ELEM(e, &siter, f, BM_EDGES_OF_FACE) { + fprintf(stderr, "%d ", BM_elem_index_get(e)); + } + fprintf(stderr, "\n"); + + fprintf(stderr, " l: "); + BM_ITER_ELEM(l, &siter, f, BM_LOOPS_OF_FACE) { + fprintf(stderr, "%d(v=%d, e=%d) ", + BM_elem_index_get(l), + BM_elem_index_get(l->v), + BM_elem_index_get(l->e)); + } + fprintf(stderr, "\n"); + } +} + +void pbvh_bmesh_print(PBVH *bvh) +{ + GHashIterator gh_iter; + int n; + + fprintf(stderr, "\npbvh=%p\n", bvh); + fprintf(stderr, "bm_face_to_node:\n"); + GHASH_ITER (gh_iter, bvh->bm_face_to_node) { + fprintf(stderr, " %d -> %d\n", + BM_elem_index_get((BMFace*)BLI_ghashIterator_getKey(&gh_iter)), + GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter))); + } + + fprintf(stderr, "bm_vert_to_node:\n"); + GHASH_ITER (gh_iter, bvh->bm_vert_to_node) { + fprintf(stderr, " %d -> %d\n", + BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter)), + GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter))); + } + + for (n = 0; n < bvh->totnode; n++) { + PBVHNode *node = &bvh->nodes[n]; + if (!(node->flag & PBVH_Leaf)) + continue; + + fprintf(stderr, "node %d\n faces:\n", n); + GHASH_ITER (gh_iter, node->bm_faces) + fprintf(stderr, " %d\n", + BM_elem_index_get((BMFace*)BLI_ghashIterator_getKey(&gh_iter))); + fprintf(stderr, " unique verts:\n"); + GHASH_ITER (gh_iter, node->bm_unique_verts) + fprintf(stderr, " %d\n", + BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter))); + fprintf(stderr, " other verts:\n"); + GHASH_ITER (gh_iter, node->bm_other_verts) + fprintf(stderr, " %d\n", + BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter))); + } +} + +void print_flag_factors(int flag) +{ + int i; + printf("flag=0x%x:\n", flag); + for (i = 0; i < 32; i++) { + if (flag & (1 << i)) { + printf(" %d (1 << %d)\n", 1 << i, i); + } + } +} + +void pbvh_bmesh_verify(PBVH *bvh) +{ + GHashIterator gh_iter; + int i; + + /* Check faces */ + BLI_assert(bvh->bm->totface == BLI_ghash_size(bvh->bm_face_to_node)); + GHASH_ITER (gh_iter, bvh->bm_face_to_node) { + BMIter bm_iter; + BMVert *v; + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + void *nip = BLI_ghashIterator_getValue(&gh_iter); + int ni = GET_INT_FROM_POINTER(nip); + PBVHNode *n = &bvh->nodes[ni]; + + /* Check that the face's node is a leaf */ + BLI_assert(n->flag & PBVH_Leaf); + + /* Check that the face's node knows it owns the face */ + BLI_assert(BLI_ghash_haskey(n->bm_faces, f)); + + /* Check the face's vertices... */ + BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { + PBVHNode *nv; + + /* Check that the vertex is in the node */ + BLI_assert(BLI_ghash_haskey(n->bm_unique_verts, v) ^ + BLI_ghash_haskey(n->bm_other_verts, v)); + + /* Check that the vertex has a node owner */ + nv = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v); + + /* Check that the vertex's node knows it owns the vert */ + BLI_assert(BLI_ghash_haskey(nv->bm_unique_verts, v)); + + /* Check that the vertex isn't duplicated as an 'other' vert */ + BLI_assert(!BLI_ghash_haskey(nv->bm_other_verts, v)); + } + } + + /* Check verts */ + BLI_assert(bvh->bm->totvert == BLI_ghash_size(bvh->bm_vert_to_node)); + GHASH_ITER (gh_iter, bvh->bm_vert_to_node) { + BMIter bm_iter; + BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + BMFace *f; + void *nip = BLI_ghashIterator_getValue(&gh_iter); + int ni = GET_INT_FROM_POINTER(nip); + PBVHNode *n = &bvh->nodes[ni]; + int found; + + /* Check that the vert's node is a leaf */ + BLI_assert(n->flag & PBVH_Leaf); + + /* Check that the vert's node knows it owns the vert */ + BLI_assert(BLI_ghash_haskey(n->bm_unique_verts, v)); + + /* Check that the vertex isn't duplicated as an 'other' vert */ + BLI_assert(!BLI_ghash_haskey(n->bm_other_verts, v)); + + /* Check that the vert's node also contains one of the vert's + * adjacent faces */ + BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { + if (BLI_ghash_lookup(bvh->bm_face_to_node, f) == nip) { + found = TRUE; + break; + } + } + BLI_assert(found); + } + + /* Check that node elements are recorded in the top level */ + for (i = 0; i < bvh->totnode; i++) { + PBVHNode *n = &bvh->nodes[i]; + if (n->flag & PBVH_Leaf) { + /* Check for duplicate entries */ + /* Slow */ + #if 0 + bli_ghash_duplicate_key_check(n->bm_faces); + bli_ghash_duplicate_key_check(n->bm_unique_verts); + bli_ghash_duplicate_key_check(n->bm_other_verts); + #endif + + GHASH_ITER (gh_iter, n->bm_faces) { + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + void *nip = BLI_ghash_lookup(bvh->bm_face_to_node, f); + BLI_assert(BLI_ghash_haskey(bvh->bm_face_to_node, f)); + BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes)); + } + + GHASH_ITER (gh_iter, n->bm_unique_verts) { + BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + void *nip = BLI_ghash_lookup(bvh->bm_vert_to_node, v); + BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v)); + BLI_assert(!BLI_ghash_haskey(n->bm_other_verts, v)); + BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes)); + } + + GHASH_ITER (gh_iter, n->bm_other_verts) { + BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v)); + BLI_assert(BM_vert_face_count(v) > 0); + } + } + } +} + +#endif diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h new file mode 100644 index 00000000000..b3f7bf6e3d1 --- /dev/null +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -0,0 +1,186 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __PBVH_INTERN_H__ +#define __PBVH_INTERN_H__ + +/* Axis-aligned bounding box */ +typedef struct { + float bmin[3], bmax[3]; +} BB; + +/* Axis-aligned bounding box with centroid */ +typedef struct { + float bmin[3], bmax[3], bcentroid[3]; +} BBC; + +/* Note: this structure is getting large, might want to split it into + * union'd structs */ +struct PBVHNode { + /* Opaque handle for drawing code */ + struct GPU_Buffers *draw_buffers; + + /* Voxel bounds */ + BB vb; + BB orig_vb; + + /* For internal nodes, the offset of the children in the PBVH + * 'nodes' array. */ + int children_offset; + + /* Pointer into the PBVH prim_indices array and the number of + * primitives used by this leaf node. + * + * Used for leaf nodes in both mesh- and multires-based PBVHs. + */ + int *prim_indices; + unsigned int totprim; + + /* Array of indices into the mesh's MVert array. Contains the + * indices of all vertices used by faces that are within this + * node's bounding box. + * + * Note that a vertex might be used by a multiple faces, and + * these faces might be in different leaf nodes. Such a vertex + * will appear in the vert_indices array of each of those leaf + * nodes. + * + * In order to support cases where you want access to multiple + * nodes' vertices without duplication, the vert_indices array + * is ordered such that the first part of the array, up to + * index 'uniq_verts', contains "unique" vertex indices. These + * vertices might not be truly unique to this node, but if + * they appear in another node's vert_indices array, they will + * be above that node's 'uniq_verts' value. + * + * Used for leaf nodes in a mesh-based PBVH (not multires.) + */ + int *vert_indices; + unsigned int uniq_verts, face_verts; + + /* An array mapping face corners into the vert_indices + * array. The array is sized to match 'totprim', and each of + * the face's corners gets an index into the vert_indices + * array, in the same order as the corners in the original + * MFace. The fourth value should not be used if the original + * face is a triangle. + * + * Used for leaf nodes in a mesh-based PBVH (not multires.) + */ + int (*face_vert_indices)[4]; + + /* Indicates whether this node is a leaf or not; also used for + * marking various updates that need to be applied. */ + PBVHNodeFlags flag : 16; + + /* Used for raycasting: how close bb is to the ray point. */ + float tmin; + + /* Scalar displacements for sculpt mode's layer brush. */ + float *layer_disp; + + int proxy_count; + PBVHProxyNode *proxies; + + /* Dyntopo */ + GHash *bm_faces; + GHash *bm_unique_verts; + GHash *bm_other_verts; + float (*bm_orco)[3]; + int (*bm_ortri)[3]; + int bm_tot_ortri; +}; + +typedef enum { + PBVH_DYNTOPO_SMOOTH_SHADING = 1 +} PBVHFlags; + +typedef struct PBVHBMeshLog PBVHBMeshLog; + +struct PBVH { + PBVHType type; + PBVHFlags flags; + + PBVHNode *nodes; + int node_mem_count, totnode; + + int *prim_indices; + int totprim; + int totvert; + + int leaf_limit; + + /* Mesh data */ + MVert *verts; + MFace *faces; + CustomData *vdata; + + /* Grid Data */ + CCGKey gridkey; + CCGElem **grids; + DMGridAdjacency *gridadj; + void **gridfaces; + const DMFlagMat *grid_flag_mats; + int totgrid; + BLI_bitmap *grid_hidden; + + /* Only used during BVH build and update, + * don't need to remain valid after */ + BLI_bitmap vert_bitmap; + +#ifdef PERFCNTRS + int perf_modified; +#endif + + /* flag are verts/faces deformed */ + int deformed; + + int show_diffuse_color; + + /* Dynamic topology */ + BMesh *bm; + GHash *bm_face_to_node; + GHash *bm_vert_to_node; + float bm_max_edge_len; + float bm_min_edge_len; + + struct BMLog *bm_log; +}; + +/* pbvh.c */ +void BB_reset(BB *bb); +void BB_expand(BB *bb, const float co[3]); +void BB_expand_with_bb(BB *bb, BB *bb2); +void BBC_update_centroid(BBC *bbc); +int BB_widest_axis(const BB *bb); +void pbvh_grow_nodes(PBVH *bvh, int totnode); +int ray_face_intersection(const float ray_start[3], const float ray_normal[3], + const float *t0, const float *t1, const float *t2, + const float *t3, float *fdist); +void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag); + +/* pbvh_bmesh.c */ +int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], + const float ray_normal[3], float *dist, + int use_original); + +void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode); + +#endif diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 2eadfe73858..9c3c1b0e508 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1540,7 +1540,7 @@ void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm) for (i=0; i<BPHYS_TOT_DATA; i++) { if (pm->cur[i]) - pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i]; + pm->cur[i] = (char *)pm->cur[i] + ptcache_data_size[i]; } } int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm) @@ -1558,7 +1558,7 @@ int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm) } for (i=0; i<BPHYS_TOT_DATA; i++) - pm->cur[i] = data_types & (1<<i) ? (char*)pm->data[i] + index * ptcache_data_size[i] : NULL; + pm->cur[i] = data_types & (1<<i) ? (char *)pm->data[i] + index * ptcache_data_size[i] : NULL; return 1; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 538f21ce20b..04e612d1a33 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -414,6 +414,7 @@ static Scene *scene_add(Main *bmain, const char *name) sce->r.im_format.planes = R_IMF_PLANES_RGB; sce->r.im_format.imtype = R_IMF_IMTYPE_PNG; + sce->r.im_format.depth = R_IMF_CHAN_DEPTH_8; sce->r.im_format.quality = 90; sce->r.im_format.compress = 90; diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 56fddfdaa2b..81bcdc4b06e 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -279,6 +279,7 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar) } BLI_freelistN(&ar->panels); + BLI_freelistN(&ar->ui_lists); } /* not area itself */ diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 3bff209f53c..3ca04f235b8 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -156,42 +156,43 @@ static void init_alpha_over_or_under(Sequence *seq) seq->seq1 = seq2; } -static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out) +static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) { - int fac2, mfac, fac, fac4; - int xo, tempc; - char *rt1, *rt2, *rt; + float fac2, mfac, fac, fac4; + int xo; + unsigned char *cp1, *cp2, *rt; + float tempc[4], rt1[4], rt2[4]; xo = x; - rt1 = (char *) rect1; - rt2 = (char *) rect2; - rt = (char *) out; + cp1 = rect1; + cp2 = rect2; + rt = out; - fac2 = (int) (256.0f * facf0); - fac4 = (int) (256.0f * facf1); + fac2 = facf0; + fac4 = facf1; while (y--) { x = xo; while (x--) { - /* rt = rt1 over rt2 (alpha from rt1) */ + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); + fac = fac2; - mfac = 256 - ( (fac2 * rt1[3]) >> 8); + mfac = 1.0f - fac2 * rt1[3]; - if (fac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt2); - else if (mfac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt1); + if (fac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp2); + else if (mfac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp1); else { - tempc = (fac * rt1[0] + mfac * rt2[0]) >> 8; - if (tempc > 255) rt[0] = 255; else rt[0] = tempc; - tempc = (fac * rt1[1] + mfac * rt2[1]) >> 8; - if (tempc > 255) rt[1] = 255; else rt[1] = tempc; - tempc = (fac * rt1[2] + mfac * rt2[2]) >> 8; - if (tempc > 255) rt[2] = 255; else rt[2] = tempc; - tempc = (fac * rt1[3] + mfac * rt2[3]) >> 8; - if (tempc > 255) rt[3] = 255; else rt[3] = tempc; + tempc[0] = fac * rt1[0] + mfac * rt2[0]; + tempc[1] = fac * rt1[1] + mfac * rt2[1]; + tempc[2] = fac * rt1[2] + mfac * rt2[2]; + tempc[3] = fac * rt1[3] + mfac * rt2[3]; + + premul_float_to_straight_uchar(rt, tempc); } - rt1 += 4; rt2 += 4; rt += 4; + cp1 += 4; cp2 += 4; rt += 4; } if (y == 0) break; @@ -199,22 +200,23 @@ static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, ch x = xo; while (x--) { + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); + fac = fac4; - mfac = 256 - ( (fac4 * rt1[3]) >> 8); + mfac = 1.0f - (fac4 * rt1[3]); - if (fac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt2); - else if (mfac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt1); + if (fac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp2); + else if (mfac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp1); else { - tempc = (fac * rt1[0] + mfac * rt2[0]) >> 8; - if (tempc > 255) rt[0] = 255; else rt[0] = tempc; - tempc = (fac * rt1[1] + mfac * rt2[1]) >> 8; - if (tempc > 255) rt[1] = 255; else rt[1] = tempc; - tempc = (fac * rt1[2] + mfac * rt2[2]) >> 8; - if (tempc > 255) rt[2] = 255; else rt[2] = tempc; - tempc = (fac * rt1[3] + mfac * rt2[3]) >> 8; - if (tempc > 255) rt[3] = 255; else rt[3] = tempc; + tempc[0] = fac * rt1[0] + mfac * rt2[0]; + tempc[1] = fac * rt1[1] + mfac * rt2[1]; + tempc[2] = fac * rt1[2] + mfac * rt2[2]; + tempc[3] = fac * rt1[3] + mfac * rt2[3]; + + premul_float_to_straight_uchar(rt, tempc); } - rt1 += 4; rt2 += 4; rt += 4; + cp1 += 4; cp2 += 4; rt += 4; } } } @@ -298,17 +300,17 @@ static void do_alphaover_effect(SeqRenderData context, Sequence *UNUSED(seq), fl slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); - do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); + do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } } /*********************** Alpha Under *************************/ -static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out) +static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) { int fac2, mfac, fac, fac4; int xo; - char *rt1, *rt2, *rt; + unsigned char *rt1, *rt2, *rt; xo = x; rt1 = rect1; @@ -460,17 +462,17 @@ static void do_alphaunder_effect(SeqRenderData context, Sequence *UNUSED(seq), f slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); - do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); + do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } } /*********************** Cross *************************/ -static void do_cross_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out) +static void do_cross_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) { int fac1, fac2, fac3, fac4; int xo; - char *rt1, *rt2, *rt; + unsigned char *rt1, *rt2, *rt; xo = x; rt1 = rect1; @@ -570,7 +572,7 @@ static void do_cross_effect(SeqRenderData context, Sequence *UNUSED(seq), float slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); - do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); + do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } } @@ -713,31 +715,32 @@ static void free_gammacross(Sequence *UNUSED(seq)) static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1), int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) { - int fac1, fac2, col; + float fac1, fac2; int xo; - unsigned char *rt1, *rt2, *rt; - + unsigned char *cp1, *cp2, *rt; + float rt1[4], rt2[4], tempc[4]; + xo = x; - rt1 = (unsigned char *) rect1; - rt2 = (unsigned char *) rect2; - rt = (unsigned char *) out; + cp1 = rect1; + cp2 = rect2; + rt = out; - fac2 = (int)(256.0f * facf0); - fac1 = 256 - fac2; + fac2 = facf0; + fac1 = 1.0f - fac2; while (y--) { x = xo; while (x--) { - col = (fac1 * igamtab1[rt1[0]] + fac2 * igamtab1[rt2[0]]) >> 8; - if (col > 65535) rt[0] = 255; else rt[0] = ( (char *)(gamtab + col))[MOST_SIG_BYTE]; - col = (fac1 * igamtab1[rt1[1]] + fac2 * igamtab1[rt2[1]]) >> 8; - if (col > 65535) rt[1] = 255; else rt[1] = ( (char *)(gamtab + col))[MOST_SIG_BYTE]; - col = (fac1 * igamtab1[rt1[2]] + fac2 * igamtab1[rt2[2]]) >> 8; - if (col > 65535) rt[2] = 255; else rt[2] = ( (char *)(gamtab + col))[MOST_SIG_BYTE]; - col = (fac1 * igamtab1[rt1[3]] + fac2 * igamtab1[rt2[3]]) >> 8; - if (col > 65535) rt[3] = 255; else rt[3] = ( (char *)(gamtab + col))[MOST_SIG_BYTE]; + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); - rt1 += 4; rt2 += 4; rt += 4; + tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0])); + tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1])); + tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2])); + tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3])); + + premul_float_to_straight_uchar(rt, tempc); + cp1 += 4; cp2 += 4; rt += 4; } if (y == 0) @@ -746,16 +749,16 @@ static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1), int x, x = xo; while (x--) { - col = (fac1 * igamtab1[rt1[0]] + fac2 * igamtab1[rt2[0]]) >> 8; - if (col > 65535) rt[0] = 255; else rt[0] = ( (char *)(gamtab + col))[MOST_SIG_BYTE]; - col = (fac1 * igamtab1[rt1[1]] + fac2 * igamtab1[rt2[1]]) >> 8; - if (col > 65535) rt[1] = 255; else rt[1] = ( (char *)(gamtab + col))[MOST_SIG_BYTE]; - col = (fac1 * igamtab1[rt1[2]] + fac2 * igamtab1[rt2[2]]) >> 8; - if (col > 65535) rt[2] = 255; else rt[2] = ( (char *)(gamtab + col))[MOST_SIG_BYTE]; - col = (fac1 * igamtab1[rt1[3]] + fac2 * igamtab1[rt2[3]]) >> 8; - if (col > 65535) rt[3] = 255; else rt[3] = ( (char *)(gamtab + col))[MOST_SIG_BYTE]; + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); - rt1 += 4; rt2 += 4; rt += 4; + tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0])); + tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1])); + tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2])); + tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3])); + + premul_float_to_straight_uchar(rt, tempc); + cp1 += 4; cp2 += 4; rt += 4; } } } @@ -828,31 +831,34 @@ static void do_gammacross_effect(SeqRenderData context, Sequence *UNUSED(seq), f static void do_add_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) { - int col, xo, fac1, fac3; - char *rt1, *rt2, *rt; + int xo; + unsigned char *cp1, *cp2, *rt; + float fac1, fac3; + float tempc[4], rt1[4], rt2[4]; xo = x; - rt1 = (char *)rect1; - rt2 = (char *)rect2; - rt = (char *)out; + cp1 = rect1; + cp2 = rect2; + rt = out; - fac1 = (int)(256.0f * facf0); - fac3 = (int)(256.0f * facf1); + fac1 = facf0; + fac3 = facf1; while (y--) { x = xo; while (x--) { - col = rt1[0] + ((fac1 * rt2[0]) >> 8); - if (col > 255) rt[0] = 255; else rt[0] = col; - col = rt1[1] + ((fac1 * rt2[1]) >> 8); - if (col > 255) rt[1] = 255; else rt[1] = col; - col = rt1[2] + ((fac1 * rt2[2]) >> 8); - if (col > 255) rt[2] = 255; else rt[2] = col; - col = rt1[3] + ((fac1 * rt2[3]) >> 8); - if (col > 255) rt[3] = 255; else rt[3] = col; + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); - rt1 += 4; rt2 += 4; rt += 4; + tempc[0] = rt1[0] + fac1 * rt2[0]; + tempc[1] = rt1[1] + fac1 * rt2[1]; + tempc[2] = rt1[2] + fac1 * rt2[2]; + tempc[3] = min_ff(1.0f, rt1[3] + fac1 * rt2[3]); + + premul_float_to_straight_uchar(rt, tempc); + + cp1 += 4; cp2 += 4; rt += 4; } if (y == 0) @@ -861,16 +867,17 @@ static void do_add_effect_byte(float facf0, float facf1, int x, int y, unsigned x = xo; while (x--) { - col = rt1[0] + ((fac3 * rt2[0]) >> 8); - if (col > 255) rt[0] = 255; else rt[0] = col; - col = rt1[1] + ((fac3 * rt2[1]) >> 8); - if (col > 255) rt[1] = 255; else rt[1] = col; - col = rt1[2] + ((fac3 * rt2[2]) >> 8); - if (col > 255) rt[2] = 255; else rt[2] = col; - col = rt1[3] + ((fac3 * rt2[3]) >> 8); - if (col > 255) rt[3] = 255; else rt[3] = col; + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); - rt1 += 4; rt2 += 4; rt += 4; + tempc[0] = rt1[0] + fac3 * rt2[0]; + tempc[1] = rt1[1] + fac3 * rt2[1]; + tempc[2] = rt1[2] + fac3 * rt2[2]; + tempc[3] = min_ff(1.0f, rt1[3] + fac3 * rt2[3]); + + premul_float_to_straight_uchar(rt, tempc); + + cp1 += 4; cp2 += 4; rt += 4; } } } @@ -890,22 +897,28 @@ static void do_add_effect_float(float facf0, float facf1, int x, int y, float *r fac3 = facf1; while (y--) { - x = xo * 4; + x = xo; while (x--) { - *rt = *rt1 + fac1 * (*rt2); + rt[0] = rt1[0] + fac1 * rt2[0]; + rt[1] = rt1[1] + fac1 * rt2[1]; + rt[2] = rt1[2] + fac1 * rt2[2]; + rt[3] = min_ff(1.0f, rt1[3] + fac1 * rt2[3]); - rt1++; rt2++; rt++; + rt1 += 4; rt2 += 4; rt += 4; } if (y == 0) break; y--; - x = xo * 4; + x = xo; while (x--) { - *rt = *rt1 + fac3 * (*rt2); + rt[0] = rt1[0] + fac1 * rt2[0]; + rt[1] = rt1[1] + fac1 * rt2[1]; + rt[2] = rt1[2] + fac1 * rt2[2]; + rt[3] = min_ff(1.0f, rt1[3] + fac3 * rt2[3]); - rt1++; rt2++; rt++; + rt1 += 4; rt2 += 4; rt += 4; } } } @@ -931,32 +944,35 @@ static void do_add_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN /*********************** Sub *************************/ -static void do_sub_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out) +static void do_sub_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) { - int col, xo, fac1, fac3; - char *rt1, *rt2, *rt; + int xo; + unsigned char *cp1, *cp2, *rt; + float fac1, fac3; + float tempc[4], rt1[4], rt2[4]; xo = x; - rt1 = (char *) rect1; - rt2 = (char *) rect2; - rt = (char *) out; + cp1 = rect1; + cp2 = rect2; + rt = out; - fac1 = (int) (256.0f * facf0); - fac3 = (int) (256.0f * facf1); + fac1 = facf0; + fac3 = facf1; while (y--) { x = xo; while (x--) { - col = rt1[0] - ((fac1 * rt2[0]) >> 8); - if (col < 0) rt[0] = 0; else rt[0] = col; - col = rt1[1] - ((fac1 * rt2[1]) >> 8); - if (col < 0) rt[1] = 0; else rt[1] = col; - col = rt1[2] - ((fac1 * rt2[2]) >> 8); - if (col < 0) rt[2] = 0; else rt[2] = col; - col = rt1[3] - ((fac1 * rt2[3]) >> 8); - if (col < 0) rt[3] = 0; else rt[3] = col; + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); - rt1 += 4; rt2 += 4; rt += 4; + tempc[0] = rt1[0] - fac1 * rt2[0]; + tempc[1] = rt1[1] - fac1 * rt2[1]; + tempc[2] = rt1[2] - fac1 * rt2[2]; + tempc[3] = rt1[3] - fac1 * rt2[3]; + + premul_float_to_straight_uchar(rt, tempc); + + cp1 += 4; cp2 += 4; rt += 4; } if (y == 0) @@ -965,16 +981,17 @@ static void do_sub_effect_byte(float facf0, float facf1, int x, int y, char *rec x = xo; while (x--) { - col = rt1[0] - ((fac3 * rt2[0]) >> 8); - if (col < 0) rt[0] = 0; else rt[0] = col; - col = rt1[1] - ((fac3 * rt2[1]) >> 8); - if (col < 0) rt[1] = 0; else rt[1] = col; - col = rt1[2] - ((fac3 * rt2[2]) >> 8); - if (col < 0) rt[2] = 0; else rt[2] = col; - col = rt1[3] - ((fac3 * rt2[3]) >> 8); - if (col < 0) rt[3] = 0; else rt[3] = col; + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); - rt1 += 4; rt2 += 4; rt += 4; + tempc[0] = rt1[0] - fac3 * rt2[0]; + tempc[1] = rt1[1] - fac3 * rt2[1]; + tempc[2] = rt1[2] - fac3 * rt2[2]; + tempc[3] = rt1[3] - fac3 * rt2[3]; + + premul_float_to_straight_uchar(rt, tempc); + + cp1 += 4; cp2 += 4; rt += 4; } } } @@ -1029,7 +1046,7 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); - do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); + do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } } @@ -1039,10 +1056,10 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN #define XOFF 8 #define YOFF 8 -static void do_drop_effect_byte(float facf0, float facf1, int x, int y, char *rect2i, char *rect1i, char *outi) +static void do_drop_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect2i, unsigned char *rect1i, unsigned char *outi) { int height, width, temp, fac, fac1, fac2; - char *rt1, *rt2, *out; + unsigned char *rt1, *rt2, *out; int field = 1; width = x; @@ -1051,9 +1068,9 @@ static void do_drop_effect_byte(float facf0, float facf1, int x, int y, char *re fac1 = (int) (70.0f * facf0); fac2 = (int) (70.0f * facf1); - rt2 = (char *) (rect2i + YOFF * width); - rt1 = (char *) rect1i; - out = (char *) outi; + rt2 = (unsigned char *) (rect2i + YOFF * width); + rt1 = (unsigned char *) rect1i; + out = (unsigned char *) outi; for (y = 0; y < height - YOFF; y++) { if (field) fac = fac1; else fac = fac2; @@ -1122,12 +1139,12 @@ static void do_mul_effect_byte(float facf0, float facf1, int x, int y, unsigned unsigned char *out) { int xo, fac1, fac3; - char *rt1, *rt2, *rt; + unsigned char *rt1, *rt2, *rt; xo = x; - rt1 = (char *)rect1; - rt2 = (char *)rect2; - rt = (char *)out; + rt1 = rect1; + rt2 = rect2; + rt = out; fac1 = (int)(256.0f * facf0); fac3 = (int)(256.0f * facf1); @@ -1539,13 +1556,13 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1), WipeZone wipezone; WipeVars *wipe = (WipeVars *)seq->effectdata; int xo, yo; - char *rt1, *rt2, *rt; + unsigned char *cp1, *cp2, *rt; precalc_wipe_zone(&wipezone, wipe, x, y); - rt1 = (char *)rect1; - rt2 = (char *)rect2; - rt = (char *)out; + cp1 = rect1; + cp2 = rect2; + rt = out; xo = x; yo = y; @@ -1553,11 +1570,18 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1), for (x = 0; x < xo; x++) { float check = check_zone(&wipezone, x, y, seq, facf0); if (check) { - if (rt1) { - rt[0] = (int)(rt1[0] * check) + (int)(rt2[0] * (1 - check)); - rt[1] = (int)(rt1[1] * check) + (int)(rt2[1] * (1 - check)); - rt[2] = (int)(rt1[2] * check) + (int)(rt2[2] * (1 - check)); - rt[3] = (int)(rt1[3] * check) + (int)(rt2[3] * (1 - check)); + if (cp1) { + float rt1[4], rt2[4], tempc[4]; + + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); + + tempc[0] = rt1[0] * check + rt2[0] * (1 - check); + tempc[1] = rt1[1] * check + rt2[1] * (1 - check); + tempc[2] = rt1[2] * check + rt2[2] * (1 - check); + tempc[3] = rt1[3] * check + rt2[3] * (1 - check); + + premul_float_to_straight_uchar(rt, tempc); } else { rt[0] = 0; @@ -1567,11 +1591,11 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1), } } else { - if (rt2) { - rt[0] = rt2[0]; - rt[1] = rt2[1]; - rt[2] = rt2[2]; - rt[3] = rt2[3]; + if (cp2) { + rt[0] = cp2[0]; + rt[1] = cp2[1]; + rt[2] = cp2[2]; + rt[3] = cp2[3]; } else { rt[0] = 0; @@ -1582,11 +1606,11 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1), } rt += 4; - if (rt1 != NULL) { - rt1 += 4; + if (cp1 != NULL) { + cp1 += 4; } - if (rt2 != NULL) { - rt2 += 4; + if (cp2 != NULL) { + cp2 += 4; } } } @@ -1803,166 +1827,6 @@ static ImBuf *do_transform_effect(SeqRenderData context, Sequence *seq, float UN /*********************** Glow *************************/ -static void RVBlurBitmap2_byte(unsigned char *map, int width, int height, float blur, int quality) -/* MUUUCCH better than the previous blur. */ -/* We do the blurring in two passes which is a whole lot faster. */ -/* I changed the math arount to implement an actual Gaussian */ -/* distribution. */ -/* */ -/* Watch out though, it tends to misbehaven with large blur values on */ -/* a small bitmap. Avoid avoid avoid. */ -/*=============================== */ -{ - unsigned char *temp = NULL, *swap; - float *filter = NULL; - int x, y, i, fx, fy; - int index, ix, halfWidth; - float fval, k, curColor[3], curColor2[3], weight = 0; - - /* If we're not really blurring, bail out */ - if (blur <= 0) - return; - - /*Allocate memory for the tempmap and the blur filter matrix */ - temp = MEM_mallocN((width * height * 4), "blurbitmaptemp"); - if (!temp) - return; - - /*Allocate memory for the filter elements */ - halfWidth = ((quality + 1) * blur); - filter = (float *)MEM_mallocN(sizeof(float) * halfWidth * 2, "blurbitmapfilter"); - if (!filter) { - MEM_freeN(temp); - return; - } - - /* Apparently we're calculating a bell curve based on the standard deviation (or radius) - * This code is based on an example posted to comp.graphics.algorithms by - * Blancmange (bmange@airdmhor.gen.nz) - */ - - k = -1.0f / (2.0f * (float)M_PI * blur * blur); - for (ix = 0; ix < halfWidth; ix++) { - weight = (float)exp(k * (ix * ix)); - filter[halfWidth - ix] = weight; - filter[halfWidth + ix] = weight; - } - filter[0] = weight; - - /* Normalize the array */ - fval = 0; - for (ix = 0; ix < halfWidth * 2; ix++) - fval += filter[ix]; - - for (ix = 0; ix < halfWidth * 2; ix++) - filter[ix] /= fval; - - /* Blur the rows */ - for (y = 0; y < height; y++) { - /* Do the left & right strips */ - for (x = 0; x < halfWidth; x++) { - index = (x + y * width) * 4; - fx = 0; - zero_v3(curColor); - zero_v3(curColor2); - - for (i = x - halfWidth; i < x + halfWidth; i++) { - if ((i >= 0) && (i < width)) { - curColor[0] += map[(i + y * width) * 4 + GlowR] * filter[fx]; - curColor[1] += map[(i + y * width) * 4 + GlowG] * filter[fx]; - curColor[2] += map[(i + y * width) * 4 + GlowB] * filter[fx]; - - curColor2[0] += map[(width - 1 - i + y * width) * 4 + GlowR] * filter[fx]; - curColor2[1] += map[(width - 1 - i + y * width) * 4 + GlowG] * filter[fx]; - curColor2[2] += map[(width - 1 - i + y * width) * 4 + GlowB] * filter[fx]; - } - fx++; - } - temp[index + GlowR] = curColor[0]; - temp[index + GlowG] = curColor[1]; - temp[index + GlowB] = curColor[2]; - - temp[((width - 1 - x + y * width) * 4) + GlowR] = curColor2[0]; - temp[((width - 1 - x + y * width) * 4) + GlowG] = curColor2[1]; - temp[((width - 1 - x + y * width) * 4) + GlowB] = curColor2[2]; - - } - - /* Do the main body */ - for (x = halfWidth; x < width - halfWidth; x++) { - index = (x + y * width) * 4; - fx = 0; - zero_v3(curColor); - for (i = x - halfWidth; i < x + halfWidth; i++) { - curColor[0] += map[(i + y * width) * 4 + GlowR] * filter[fx]; - curColor[1] += map[(i + y * width) * 4 + GlowG] * filter[fx]; - curColor[2] += map[(i + y * width) * 4 + GlowB] * filter[fx]; - fx++; - } - temp[index + GlowR] = curColor[0]; - temp[index + GlowG] = curColor[1]; - temp[index + GlowB] = curColor[2]; - } - } - - /* Swap buffers */ - swap = temp; temp = map; map = swap; - - /* Blur the columns */ - for (x = 0; x < width; x++) { - /* Do the top & bottom strips */ - for (y = 0; y < halfWidth; y++) { - index = (x + y * width) * 4; - fy = 0; - zero_v3(curColor); - zero_v3(curColor2); - for (i = y - halfWidth; i < y + halfWidth; i++) { - if ((i >= 0) && (i < height)) { - /* Bottom */ - curColor[0] += map[(x + i * width) * 4 + GlowR] * filter[fy]; - curColor[1] += map[(x + i * width) * 4 + GlowG] * filter[fy]; - curColor[2] += map[(x + i * width) * 4 + GlowB] * filter[fy]; - - /* Top */ - curColor2[0] += map[(x + (height - 1 - i) * width) * 4 + GlowR] * filter[fy]; - curColor2[1] += map[(x + (height - 1 - i) * width) * 4 + GlowG] * filter[fy]; - curColor2[2] += map[(x + (height - 1 - i) * width) * 4 + GlowB] * filter[fy]; - } - fy++; - } - temp[index + GlowR] = curColor[0]; - temp[index + GlowG] = curColor[1]; - temp[index + GlowB] = curColor[2]; - temp[((x + (height - 1 - y) * width) * 4) + GlowR] = curColor2[0]; - temp[((x + (height - 1 - y) * width) * 4) + GlowG] = curColor2[1]; - temp[((x + (height - 1 - y) * width) * 4) + GlowB] = curColor2[2]; - } - - /* Do the main body */ - for (y = halfWidth; y < height - halfWidth; y++) { - index = (x + y * width) * 4; - fy = 0; - zero_v3(curColor); - for (i = y - halfWidth; i < y + halfWidth; i++) { - curColor[0] += map[(x + i * width) * 4 + GlowR] * filter[fy]; - curColor[1] += map[(x + i * width) * 4 + GlowG] * filter[fy]; - curColor[2] += map[(x + i * width) * 4 + GlowB] * filter[fy]; - fy++; - } - temp[index + GlowR] = curColor[0]; - temp[index + GlowG] = curColor[1]; - temp[index + GlowB] = curColor[2]; - } - } - - /* Swap buffers */ - swap = temp; temp = map; /* map = swap; */ /* UNUSED */ - - /* Tidy up */ - MEM_freeN(filter); - MEM_freeN(temp); -} - static void RVBlurBitmap2_float(float *map, int width, int height, float blur, int quality) /* MUUUCCH better than the previous blur. */ /* We do the blurring in two passes which is a whole lot faster. */ @@ -2124,26 +1988,6 @@ static void RVBlurBitmap2_float(float *map, int width, int height, float blur, i MEM_freeN(temp); } - -/* Adds two bitmaps and puts the results into a third map. */ -/* C must have been previously allocated but it may be A or B. */ -/* We clamp values to 255 to prevent weirdness */ -/*=============================== */ -static void RVAddBitmaps_byte(unsigned char *a, unsigned char *b, unsigned char *c, int width, int height) -{ - int x, y, index; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - index = (x + y * width) * 4; - c[index + GlowR] = MIN2(255, a[index + GlowR] + b[index + GlowR]); - c[index + GlowG] = MIN2(255, a[index + GlowG] + b[index + GlowG]); - c[index + GlowB] = MIN2(255, a[index + GlowB] + b[index + GlowB]); - c[index + GlowA] = MIN2(255, a[index + GlowA] + b[index + GlowA]); - } - } -} - static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int height) { int x, y, index; @@ -2159,37 +2003,6 @@ static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int heig } } -/* For each pixel whose total luminance exceeds the threshold, - * Multiply it's value by BOOST and add it to the output map - */ -static void RVIsolateHighlights_byte(unsigned char *in, unsigned char *out, int width, int height, int threshold, - float boost, float clamp) -{ - int x, y, index; - int intensity; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - index = (x + y * width) * 4; - - /* Isolate the intensity */ - intensity = (in[index + GlowR] + in[index + GlowG] + in[index + GlowB] - threshold); - if (intensity > 0) { - out[index + GlowR] = MIN2(255 * clamp, (in[index + GlowR] * boost * intensity) / 255); - out[index + GlowG] = MIN2(255 * clamp, (in[index + GlowG] * boost * intensity) / 255); - out[index + GlowB] = MIN2(255 * clamp, (in[index + GlowB] * boost * intensity) / 255); - out[index + GlowA] = MIN2(255 * clamp, (in[index + GlowA] * boost * intensity) / 255); - } - else { - out[index + GlowR] = 0; - out[index + GlowG] = 0; - out[index + GlowB] = 0; - out[index + GlowA] = 0; - } - } - } -} - static void RVIsolateHighlights_float(float *in, float *out, int width, int height, float threshold, float boost, float clamp) { int x, y, index; @@ -2254,16 +2067,27 @@ static void copy_glow_effect(Sequence *dst, Sequence *src) } static void do_glow_effect_byte(Sequence *seq, int render_size, float facf0, float UNUSED(facf1), int x, int y, - char *rect1, char *UNUSED(rect2), char *out) + unsigned char *rect1, unsigned char *UNUSED(rect2), unsigned char *out) { - unsigned char *outbuf = (unsigned char *)out; - unsigned char *inbuf = (unsigned char *)rect1; + float *outbuf, *inbuf; GlowVars *glow = (GlowVars *)seq->effectdata; - - RVIsolateHighlights_byte(inbuf, outbuf, x, y, glow->fMini * 765, glow->fBoost * facf0, glow->fClamp); - RVBlurBitmap2_byte(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality); + + inbuf = MEM_mallocN(4 * sizeof(float) * x * y, "glow effect input"); + outbuf = MEM_mallocN(4 * sizeof(float) * x * y, "glow effect output"); + + IMB_buffer_float_from_byte(inbuf, rect1, IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, x, y, x, x); + IMB_buffer_float_premultiply(inbuf, x, y); + + RVIsolateHighlights_float(inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp); + RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality); if (!glow->bNoComp) - RVAddBitmaps_byte(inbuf, outbuf, outbuf, x, y); + RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y); + + IMB_buffer_float_unpremultiply(outbuf, x, y); + IMB_buffer_byte_from_float(out, outbuf, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, x, y, x, x); + + MEM_freeN(inbuf); + MEM_freeN(outbuf); } static void do_glow_effect_float(Sequence *seq, int render_size, float facf0, float UNUSED(facf1), int x, int y, @@ -2292,7 +2116,7 @@ static ImBuf *do_glow_effect(SeqRenderData context, Sequence *seq, float UNUSED( } else { do_glow_effect_byte(seq, render_size, facf0, facf1, context.rectx, context.recty, - (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect); + (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect, (unsigned char *) out->rect); } return out; @@ -2735,7 +2559,7 @@ static ImBuf *do_speed_effect(SeqRenderData context, Sequence *UNUSED(seq), floa } else { do_cross_effect_byte(facf0, facf1, context.rectx, context.recty, - (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect); + (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect, (unsigned char *) out->rect); } return out; } @@ -2761,8 +2585,8 @@ static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), flo slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); - do_drop_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out); - do_alphaover_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out); + do_drop_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out); + do_alphaover_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out); } } diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 5b2e9f2bf23..3d8a2f7cddf 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -226,24 +226,28 @@ static void curves_apply_threaded(int width, int height, unsigned char *rect, fl } if (rect) { unsigned char *pixel = rect + pixel_index; - unsigned char result[3]; + float result[3], tempc[4]; - curvemapping_evaluate_premulRGB(curve_mapping, result, pixel); + straight_uchar_to_premul_float(tempc, pixel); + + curvemapping_evaluate_premulRGBF(curve_mapping, result, tempc); if (mask_rect) { float t[3]; rgb_uchar_to_float(t, mask_rect + pixel_index); - pixel[0] = pixel[0] * (1.0f - t[0]) + result[0] * t[0]; - pixel[1] = pixel[1] * (1.0f - t[1]) + result[1] * t[1]; - pixel[2] = pixel[2] * (1.0f - t[2]) + result[2] * t[2]; + tempc[0] = pixel[0] * (1.0f - t[0]) + result[0] * t[0]; + tempc[1] = pixel[1] * (1.0f - t[1]) + result[1] * t[1]; + tempc[2] = pixel[2] * (1.0f - t[2]) + result[2] * t[2]; } else { - pixel[0] = result[0]; - pixel[1] = result[1]; - pixel[2] = result[2]; + tempc[0] = result[0]; + tempc[1] = result[1]; + tempc[2] = result[2]; } + + premul_float_to_straight_uchar(pixel, tempc); } } } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 5e44f2d6d9e..8d010de408a 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -324,7 +324,6 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_ { const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); const char *to_colorspace = scene->sequencer_colorspace_settings.name; - int predivide = ibuf->flags & IB_cm_predivide; if (!ibuf->rect_float) { if (make_float && ibuf->rect) { @@ -354,7 +353,7 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_ imb_freerectImBuf(ibuf); IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); + from_colorspace, to_colorspace, TRUE); } } @@ -367,10 +366,8 @@ void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) return; if (to_colorspace && to_colorspace[0] != '\0') { - int predivide = ibuf->flags & IB_cm_predivide; - IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); + from_colorspace, to_colorspace, TRUE); } } @@ -636,7 +633,7 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq) } } -/* note: caller should run calc_sequence(scene, seq) after */ +/* note: caller should run BKE_sequence_calc(scene, seq) after */ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, int lock_range) { char str[FILE_MAX]; @@ -1517,18 +1514,6 @@ MINLINE float color_balance_fl(float in, const float lift, const float gain, con return powf(x, gamma) * mul; } -static void make_cb_table_byte(float lift, float gain, float gamma, - unsigned char *table, float mul) -{ - int y; - - for (y = 0; y < 256; y++) { - float v = color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul); - - table[y] = FTOCHAR(v); - } -} - static void make_cb_table_float(float lift, float gain, float gamma, float *table, float mul) { @@ -1543,35 +1528,33 @@ static void make_cb_table_float(float lift, float gain, float gamma, static void color_balance_byte_byte(StripColorBalance *cb_, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul) { - unsigned char cb_tab[3][256]; - int c; - unsigned char *p = rect; - unsigned char *e = p + width * 4 * height; + //unsigned char cb_tab[3][256]; + unsigned char *cp = rect; + unsigned char *e = cp + width * 4 * height; unsigned char *m = mask_rect; StripColorBalance cb = calc_cb(cb_); - for (c = 0; c < 3; c++) { - make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul); - } + while (cp < e) { + float p[4]; + int c; - while (p < e) { - if (m) { - float t[3] = {m[0] / 255.0f, m[1] / 255.0f, m[2] / 255.0f}; + straight_uchar_to_premul_float(p, cp); - p[0] = p[0] * (1.0f - t[0]) + t[0] * cb_tab[0][p[0]]; - p[1] = p[1] * (1.0f - t[1]) + t[1] * cb_tab[1][p[1]]; - p[2] = p[2] * (1.0f - t[2]) + t[2] * cb_tab[2][p[2]]; + for (c = 0; c < 3; c++) { + float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul); - m += 4; - } - else { - p[0] = cb_tab[0][p[0]]; - p[1] = cb_tab[1][p[1]]; - p[2] = cb_tab[2][p[2]]; + if (m) + p[c] = p[c] * (1.0f - (float)m[c] / 255.0f) + t * m[c]; + else + p[c] = t; } - p += 4; + premul_float_to_straight_uchar(cp, p); + + cp += 4; + if (m) + m += 4; } } @@ -1795,7 +1778,7 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen { float mul; - if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_PREMUL | SEQ_MAKE_FLOAT)) { + if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_FLOAT)) { return TRUE; } @@ -1892,7 +1875,8 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, ImBuf *i = IMB_allocImBuf(dx, dy, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy); - + sequencer_imbuf_assign_spaces(context.scene, i); + IMB_freeImBuf(ibuf); ibuf = i; @@ -1931,12 +1915,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, multibuf(ibuf, mul); } - if (seq->flag & SEQ_MAKE_PREMUL) { - if (ibuf->planes == 32 && ibuf->zbuf == NULL) { - IMB_premultiply_alpha(ibuf); - } - } - if (ibuf->x != context.rectx || ibuf->y != context.recty) { if (context.scene->r.mode & R_OSA) { IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty); @@ -2546,13 +2524,18 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo case SEQ_TYPE_IMAGE: { StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra); + int flag; if (s_elem) { BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); BLI_path_abs(name, G.main->name); } - if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name))) { + flag = IB_rect; + if (seq->alpha_mode == SEQ_ALPHA_PREMUL) + flag |= IB_alphamode_premul; + + if (s_elem && (ibuf = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name))) { /* we don't need both (speed reasons)! */ if (ibuf->rect_float && ibuf->rect) imb_freerectImBuf(ibuf); @@ -2641,7 +2624,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) { ImBuf *ibuf = NULL; - int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); + int use_preprocess = FALSE; int is_proxy_image = FALSE; float nr = give_stripelem_index(seq, cfra); /* all effects are handled similarly with the exception of speed effect */ @@ -2650,30 +2633,36 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); - /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF, - * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */ - if (ibuf) - use_preprocess = FALSE; - - if (ibuf == NULL) - ibuf = copy_from_ibuf_still(context, seq, nr); - if (ibuf == NULL) { - ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); + if (ibuf == NULL) + ibuf = copy_from_ibuf_still(context, seq, nr); if (ibuf == NULL) { - /* MOVIECLIPs have their own proxy management */ - if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) { - ibuf = seq_proxy_fetch(context, seq, cfra); - is_proxy_image = (ibuf != NULL); - } + ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); + + if (ibuf == NULL) { + /* MOVIECLIPs have their own proxy management */ + if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) { + ibuf = seq_proxy_fetch(context, seq, cfra); + is_proxy_image = (ibuf != NULL); + } - if (ibuf == NULL) - ibuf = do_render_strip_uncached(context, seq, cfra); + if (ibuf == NULL) + ibuf = do_render_strip_uncached(context, seq, cfra); - if (ibuf) - BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf); + if (ibuf) + BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf); + } } + + if (ibuf) + use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); + } + else { + /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF, + * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL + * so, no need in check for preprocess here + */ } if (ibuf == NULL) { @@ -3973,10 +3962,18 @@ void BKE_sequence_init_colorspace(Sequence *seq) /* initialize input color space */ if (seq->type == SEQ_TYPE_IMAGE) { - ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name); + ibuf = IMB_loadiffname(name, IB_test | IB_alphamode_detect, seq->strip->colorspace_settings.name); + + /* byte images are default to straight alpha, however sequencer + * works in premul space, so mark strip to be premultiplied first + */ + seq->alpha_mode = SEQ_ALPHA_STRAIGHT; + if (ibuf) { + if (ibuf->flags & IB_alphamode_premul) + seq->alpha_mode = IMA_ALPHA_PREMUL; - if (ibuf) IMB_freeImBuf(ibuf); + } } } } @@ -4176,7 +4173,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup seqn->seqbase.first = seqn->seqbase.last = NULL; /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */ - /* - seq_dupli_recursive(&seq->seqbase,&seqn->seqbase);*/ + /* - seq_dupli_recursive(&seq->seqbase, &seqn->seqbase);*/ } else if (seq->type == SEQ_TYPE_SCENE) { seqn->strip->stripdata = NULL; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 629b2c989d3..2563fc268b1 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -2407,7 +2407,7 @@ static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene) bv[3] = (float)sds->res[1]; // y bv[5] = (float)sds->res[2]; // z -// #pragma omp parallel for schedule(static,1) +// #pragma omp parallel for schedule(static, 1) for (z = 0; z < sds->res[2]; z++) { size_t index = z * slabsize; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 37c9c1dd84e..b1917c6091d 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1577,7 +1577,7 @@ static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm) CCGFace **faces; int totface; - BLI_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface); + BKE_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface); if (totface) { ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface); ccgSubSurf_updateNormals(ccgdm->ss, faces, totface); @@ -1715,7 +1715,8 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) if (ccgdm->pbvh && ccgdm->multires.mmd && !fast) { if (dm->numTessFaceData) { - BLI_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL, setMaterial); + BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL, + setMaterial, FALSE); glShadeModel(GL_FLAT); } @@ -3033,7 +3034,7 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) * when the ccgdm gets remade, the assumption is that the topology * does not change. */ ccgdm_create_grids(dm); - BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces, + BKE_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces, ccgdm->gridFlagMats, ccgdm->gridHidden); } @@ -3051,15 +3052,15 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) numGrids = ccgDM_getNumGrids(dm); - ob->sculpt->pbvh = ccgdm->pbvh = BLI_pbvh_new(); - BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, + ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new(); + BKE_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, numGrids, &key, (void **) ccgdm->gridFaces, ccgdm->gridFlagMats, ccgdm->gridHidden); } else if (ob->type == OB_MESH) { Mesh *me = ob->data; - ob->sculpt->pbvh = ccgdm->pbvh = BLI_pbvh_new(); + ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new(); BLI_assert(!(me->mface == NULL && me->mpoly != NULL)); /* BMESH ONLY complain if mpoly is valid but not mface */ - BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert, + BKE_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert, me->totface, me->totvert, &me->vdata); } diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c index ff9774f85af..6f9736df683 100644 --- a/source/blender/blenkernel/intern/suggestions.c +++ b/source/blender/blenkernel/intern/suggestions.c @@ -163,13 +163,13 @@ void texttool_suggest_add(const char *name, char type) suggestions.top = 0; } -void texttool_suggest_prefix(const char *prefix) +void texttool_suggest_prefix(const char *prefix, const int prefix_len) { SuggItem *match, *first, *last; - int cmp, len = strlen(prefix), top = 0; + int cmp, top = 0; if (!suggestions.first) return; - if (len == 0) { + if (prefix_len == 0) { suggestions.selected = suggestions.firstmatch = suggestions.first; suggestions.lastmatch = suggestions.last; return; @@ -177,7 +177,7 @@ void texttool_suggest_prefix(const char *prefix) first = last = NULL; for (match = suggestions.first; match; match = match->next) { - cmp = txttl_cmp(prefix, match->name, len); + cmp = txttl_cmp(prefix, match->name, prefix_len); if (cmp == 0) { if (!first) { first = match; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 322b77e0462..c337e339ebf 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -2936,3 +2936,18 @@ int text_check_whitespace(const char ch) return 1; return 0; } + +int text_find_identifier_start(const char *str, int i) +{ + if (UNLIKELY(i <= 0)) { + return 0; + } + + while (i--) { + if (!text_check_identifier(str[i])) { + break; + } + } + i++; + return i; +} diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 149842bc038..fbaf6f70fbc 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -440,7 +440,7 @@ void default_tex(Tex *tex) tex->type = TEX_CLOUDS; tex->stype = 0; tex->flag = TEX_CHECKER_ODD; - tex->imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA; + tex->imaflag = TEX_INTERPOL | TEX_MIPMAP; tex->extend = TEX_REPEAT; tex->cropxmin = tex->cropymin = 0.0; tex->cropxmax = tex->cropymax = 1.0; |