Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2012-12-19 05:49:58 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2012-12-19 05:49:58 +0400
commitd433cd65f7127d60e17d05a824290423ad226eae (patch)
treef0a9c821f6046e97b74c6969d41269b558fd52ab /source/blender/blenkernel
parent10f0f66560234a04aed3295c74fff20adacbc57f (diff)
parentf10dea7e3b9b431edae9c787fa1a9e09cd567ed7 (diff)
Merged changes in the trunk up to revision 53146.
Conflicts resolved: release/datafiles/startup.blend source/blender/blenkernel/CMakeLists.txt source/blender/blenlib/intern/bpath.c source/blender/blenloader/intern/readfile.c
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h7
-rw-r--r--source/blender/blenkernel/BKE_armature.h22
-rw-r--r--source/blender/blenkernel/BKE_blender.h20
-rw-r--r--source/blender/blenkernel/BKE_bpath.h72
-rw-r--r--source/blender/blenkernel/BKE_constraint.h4
-rw-r--r--source/blender/blenkernel/BKE_fluidsim.h2
-rw-r--r--source/blender/blenkernel/BKE_global.h2
-rw-r--r--source/blender/blenkernel/BKE_lattice.h2
-rw-r--r--source/blender/blenkernel/BKE_library.h1
-rw-r--r--source/blender/blenkernel/BKE_main.h7
-rw-r--r--source/blender/blenkernel/BKE_mesh.h2
-rw-r--r--source/blender/blenkernel/BKE_modifier.h2
-rw-r--r--source/blender/blenkernel/BKE_object.h15
-rw-r--r--source/blender/blenkernel/BKE_particle.h37
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h270
-rw-r--r--source/blender/blenkernel/BKE_property.h3
-rw-r--r--source/blender/blenkernel/BKE_scene.h4
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h2
-rw-r--r--source/blender/blenkernel/BKE_tessmesh.h5
-rw-r--r--source/blender/blenkernel/CMakeLists.txt7
-rw-r--r--source/blender/blenkernel/SConscript28
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c20
-rw-r--r--source/blender/blenkernel/intern/action.c1
-rw-r--r--source/blender/blenkernel/intern/anim.c15
-rw-r--r--source/blender/blenkernel/intern/armature.c33
-rw-r--r--source/blender/blenkernel/intern/blender.c268
-rw-r--r--source/blender/blenkernel/intern/bpath.c726
-rw-r--r--source/blender/blenkernel/intern/brush.c8
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c2
-rw-r--r--source/blender/blenkernel/intern/collision.c4
-rw-r--r--source/blender/blenkernel/intern/constraint.c12
-rw-r--r--source/blender/blenkernel/intern/curve.c23
-rw-r--r--source/blender/blenkernel/intern/customdata.c9
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c114
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c63
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c54
-rw-r--r--source/blender/blenkernel/intern/gpencil.c2
-rw-r--r--source/blender/blenkernel/intern/image.c16
-rw-r--r--source/blender/blenkernel/intern/key.c8
-rw-r--r--source/blender/blenkernel/intern/lattice.c3
-rw-r--r--source/blender/blenkernel/intern/library.c16
-rw-r--r--source/blender/blenkernel/intern/material.c3
-rw-r--r--source/blender/blenkernel/intern/mball.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c7
-rw-r--r--source/blender/blenkernel/intern/modifier.c10
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c31
-rw-r--r--source/blender/blenkernel/intern/multires.c2
-rw-r--r--source/blender/blenkernel/intern/object.c75
-rw-r--r--source/blender/blenkernel/intern/particle.c17
-rw-r--r--source/blender/blenkernel/intern/particle_system.c419
-rw-r--r--source/blender/blenkernel/intern/pbvh.c1909
-rw-r--r--source/blender/blenkernel/intern/pointcache.c3
-rw-r--r--source/blender/blenkernel/intern/property.c2
-rw-r--r--source/blender/blenkernel/intern/report.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c12
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c2
-rw-r--r--source/blender/blenkernel/intern/sequencer.c11
-rw-r--r--source/blender/blenkernel/intern/smoke.c9
-rw-r--r--source/blender/blenkernel/intern/speaker.c1
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c2
-rw-r--r--source/blender/blenkernel/intern/texture.c1
-rw-r--r--source/blender/blenkernel/intern/tracking.c6
-rw-r--r--source/blender/blenkernel/intern/world.c1
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c7
64 files changed, 4079 insertions, 366 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 617c4cd2bc8..ed90c63d949 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -105,6 +105,11 @@ struct PBVH;
* Also, the mface origindex layer indexes mpolys, not mfaces.
*/
+typedef struct DMCoNo {
+ float co[3];
+ float no[3];
+} DMCoNo;
+
typedef struct DMGridAdjacency {
int index[4];
int rotation[4];
@@ -603,7 +608,7 @@ void vDM_ColorBand_store(struct ColorBand *coba);
/** Simple function to get me->totvert amount of vertices/normals,
* correctly deformed and subsurfered. Needed especially when vertexgroups are involved.
* In use now by vertex/weight paint and particles */
-float *mesh_get_mapped_verts_nors(struct Scene *scene, struct Object *ob);
+DMCoNo *mesh_get_mapped_verts_nors(struct Scene *scene, struct Object *ob);
/* */
DerivedMesh *mesh_get_derived_final(struct Scene *scene, struct Object *ob,
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index b0f372e0bac..765a00b8d4b 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -97,28 +97,28 @@ void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPose
void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
/* get_objectspace_bone_matrix has to be removed still */
-void get_objectspace_bone_matrix(struct Bone *bone, float M_accumulatedMatrix[][4], int root, int posed);
-void vec_roll_to_mat3(const float vec[3], const float roll, float mat[][3]);
-void mat3_to_vec_roll(float mat[][3], float r_vec[3], float *r_roll);
+void get_objectspace_bone_matrix(struct Bone *bone, float M_accumulatedMatrix[4][4], int root, int posed);
+void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3]);
+void mat3_to_vec_roll(float mat[3][3], float r_vec[3], float *r_roll);
/* Common Conversions Between Co-ordinate Spaces */
-void BKE_armature_mat_world_to_pose(struct Object *ob, float inmat[][4], float outmat[][4]);
+void BKE_armature_mat_world_to_pose(struct Object *ob, float inmat[4][4], float outmat[4][4]);
void BKE_armature_loc_world_to_pose(struct Object *ob, const float inloc[3], float outloc[3]);
-void BKE_armature_mat_pose_to_bone(struct bPoseChannel *pchan, float inmat[][4], float outmat[][4]);
+void BKE_armature_mat_pose_to_bone(struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]);
void BKE_armature_loc_pose_to_bone(struct bPoseChannel *pchan, const float inloc[3], float outloc[3]);
-void BKE_armature_mat_bone_to_pose(struct bPoseChannel *pchan, float inmat[][4], float outmat[][4]);
-void BKE_armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float arm_mat[][4]);
+void BKE_armature_mat_bone_to_pose(struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]);
+void BKE_armature_mat_pose_to_delta(float delta_mat[4][4], float pose_mat[4][4], float arm_mat[4][4]);
-void BKE_armature_mat_pose_to_bone_ex(struct Object *ob, struct bPoseChannel *pchan, float inmat[][4], float outmat[][4]);
+void BKE_armature_mat_pose_to_bone_ex(struct Object *ob, struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]);
-void BKE_pchan_mat3_to_rot(struct bPoseChannel *pchan, float mat[][3], short use_compat);
-void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, float mat[][4], short use_comat);
+void BKE_pchan_mat3_to_rot(struct bPoseChannel *pchan, float mat[3][3], short use_compat);
+void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, float mat[4][4], short use_comat);
void BKE_pchan_to_mat4(struct bPoseChannel *pchan, float chan_mat[4][4]);
void BKE_pchan_calc_mat(struct bPoseChannel *pchan);
/* Get the "pchan to pose" transform matrix. These matrices apply the effects of
* HINGE/NO_SCALE/NO_LOCAL_LOCATION options over the pchan loc/rot/scale transformations. */
-void BKE_pchan_to_pose_mat(struct bPoseChannel *pchan, float rotscale_mat[][4], float loc_mat[][4]);
+void BKE_pchan_to_pose_mat(struct bPoseChannel *pchan, float rotscale_mat[4][4], float loc_mat[4][4]);
/* Rotation Mode Conversions - Used for PoseChannels + Objects... */
void BKE_rotMode_change_values(float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode);
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index b624d0f9c3a..570086e9b69 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 0
+#define BLENDER_SUBVERSION 3
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
@@ -52,7 +52,7 @@ extern "C" {
/* can be left blank, otherwise a,b,c... etc with no quotes */
#define BLENDER_VERSION_CHAR
/* alpha/beta/rc/release, docs use this */
-#define BLENDER_VERSION_CYCLE release
+#define BLENDER_VERSION_CYCLE alpha
extern char versionstr[]; /* from blender.c */
@@ -62,6 +62,7 @@ struct bContext;
struct ReportList;
struct Scene;
struct Main;
+struct ID;
int BKE_read_file(struct bContext *C, const char *filepath, struct ReportList *reports);
@@ -72,12 +73,17 @@ int BKE_read_file(struct bContext *C, const char *filepath, struct ReportList *r
int BKE_read_file_from_memory(struct bContext *C, char *filebuf, int filelength, struct ReportList *reports);
int BKE_read_file_from_memfile(struct bContext *C, struct MemFile *memfile, struct ReportList *reports);
+int BKE_read_file_userdef(const char *filepath, struct ReportList *reports);
+int BKE_write_file_userdef(const char *filepath, struct ReportList *reports);
+
void free_blender(void);
void initglobals(void);
/* load new userdef from file, exit blender */
void BKE_userdef_free(void);
-
+/* handle changes in userdef */
+void BKE_userdef_state(void);
+
/* set this callback when a UI is running */
void set_blender_test_break_cb(void (*func)(void) );
int blender_test_break(void);
@@ -93,9 +99,15 @@ extern void BKE_reset_undo(void);
extern char *BKE_undo_menu_string(void);
extern void BKE_undo_number(struct bContext *C, int nr);
extern const char *BKE_undo_get_name(int nr, int *active);
-extern void BKE_undo_save_quit(void);
+extern int BKE_undo_save_file(const char *filename);
extern struct Main *BKE_undo_get_main(struct Scene **scene);
+ /* copybuffer */
+void BKE_copybuffer_begin(void);
+void BKE_copybuffer_tag_ID(struct ID *id);
+int BKE_copybuffer_save(char *filename, struct ReportList *reports);
+ int BKE_copybuffer_paste(struct bContext *C, char *libname, struct ReportList *reports);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_bpath.h b/source/blender/blenkernel/BKE_bpath.h
new file mode 100644
index 00000000000..16a8b1be85b
--- /dev/null
+++ b/source/blender/blenkernel/BKE_bpath.h
@@ -0,0 +1,72 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file BKE_bpath.h
+ * \ingroup bke
+ * \attention Based on ghash, difference is ghash is not a fixed size,
+ * so for BPath we don't need to malloc
+ */
+
+#ifndef __BKE_BPATH_H__
+#define __BKE_BPATH_H__
+
+struct ID;
+struct ListBase;
+struct Main;
+struct ReportList;
+
+/* Function that does something with an ID's file path. Should return 1 if the
+ * path has changed, and in that case, should write the result to pathOut. */
+typedef int (*BPathVisitor)(void *userdata, char *path_dst, const char *path_src);
+/* Executes 'visit' for each path associated with 'id'. */
+void BKE_bpath_traverse_id(struct Main *bmain, struct ID *id, BPathVisitor visit_cb, const int flag, void *userdata);
+void BKE_bpath_traverse_id_list(struct Main *bmain, struct ListBase *lb, BPathVisitor visit_cb, const int flag, void *userdata);
+void BKE_bpath_traverse_main(struct Main *bmain, BPathVisitor visit_cb, const int flag, void *userdata);
+int BKE_bpath_relocate_visitor(void *oldbasepath, char *path_dst, const char *path_src);
+
+/* Functions for temp backup/restore of paths, path count must NOT change */
+void *BKE_bpath_list_backup(struct Main *bmain, const int flag);
+void BKE_bpath_list_restore(struct Main *bmain, const int flag, void *ls_handle);
+void BKE_bpath_list_free(void *ls_handle);
+
+#define BKE_BPATH_TRAVERSE_ABS (1 << 0) /* convert paths to absolute */
+#define BKE_BPATH_TRAVERSE_SKIP_LIBRARY (1 << 2) /* skip library paths */
+#define BKE_BPATH_TRAVERSE_SKIP_PACKED (1 << 3) /* skip packed data */
+#define BKE_BPATH_TRAVERSE_SKIP_MULTIFILE (1 << 4) /* skip paths where a single dir is used with an array of files, eg.
+ * sequence strip images and pointcache. in this case only use the first
+ * file, this is needed for directory manipulation functions which might
+ * otherwise modify the same directory multiple times */
+
+/* high level funcs */
+
+/* creates a text file with missing files if there are any */
+void BKE_bpath_missing_files_check(struct Main *bmain, struct ReportList *reports);
+void BKE_bpath_missing_files_find(struct Main *bmain, const char *searchpath, struct ReportList *reports);
+void BKE_bpath_relative_convert(struct Main *bmain, const char *basedir, struct ReportList *reports);
+void BKE_bpath_absolute_convert(struct Main *bmain, const char *basedir, struct ReportList *reports);
+
+#endif /* __BKE_BPATH_H__ */
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 686a60ab2c9..79e75127763 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -147,9 +147,9 @@ short proxylocked_constraints_owner(struct Object *ob, struct bPoseChannel *pcha
struct bConstraintOb *constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype);
void constraints_clear_evalob(struct bConstraintOb *cob);
-void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[][4], short from, short to);
+void 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], float ctime);
+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);
diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h
index c3fa6621c98..433c10b82f1 100644
--- a/source/blender/blenkernel/BKE_fluidsim.h
+++ b/source/blender/blenkernel/BKE_fluidsim.h
@@ -47,7 +47,7 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
int useGlobalCoords, int modifierIndex);
/* bounding box & memory estimate */
-void fluid_get_bb(struct MVert *mvert, int totvert, float obmat[][4],
+void fluid_get_bb(struct MVert *mvert, int totvert, float obmat[4][4],
float start[3], float size[3]);
void fluid_estimate_memory(struct Object *ob, struct FluidsimSettings *fss, char *value);
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index f6276a69d57..38a88607119 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -149,7 +149,7 @@ enum {
/* #define G_FILE_SHOW_PROFILE (1 << 6) */ /* deprecated */
#define G_FILE_LOCK (1 << 7)
#define G_FILE_SIGN (1 << 8)
-/* #define G_FILE_PUBLISH (1 << 9) */ /* deprecated */
+#define G_FILE_USERPREFS (1 << 9)
#define G_FILE_NO_UI (1 << 10)
/* #define G_FILE_GAME_TO_IPO (1 << 11) */ /* deprecated */
#define G_FILE_GAME_MAT (1 << 12) /* deprecated */
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 34baa48dbe2..a0bebd752b5 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -59,7 +59,7 @@ void curve_deform_verts(struct Scene *scene, struct Object *cuOb, struct Object
struct DerivedMesh *dm, float (*vertexCos)[3],
int numVerts, const char *vgroup, short defaxis);
void curve_deform_vector(struct Scene *scene, struct Object *cuOb, struct Object *target,
- float orco[3], float vec[3], float mat[][3], int no_rot_axis);
+ float orco[3], float vec[3], float mat[3][3], int no_rot_axis);
void lattice_deform_verts(struct Object *laOb, struct Object *target,
struct DerivedMesh *dm, float (*vertexCos)[3],
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index bc081b7f308..b9bb67fa509 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -62,6 +62,7 @@ void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const shor
void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
void id_lib_extern(struct ID *id);
void BKE_library_filepath_set(struct Library *lib, const char *filepath);
+void id_us_ensure_real(struct ID *id);
void id_us_plus(struct ID *id);
void id_us_min(struct ID *id);
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 06931662d3f..cb8f1a7d682 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -51,9 +51,10 @@ struct Library;
typedef struct Main {
struct Main *next, *prev;
char name[1024]; /* 1024 = FILE_MAX */
- short versionfile, subversionfile;
+ short versionfile, subversionfile; /* see BLENDER_VERSION, BLENDER_SUBVERSION */
short minversionfile, minsubversionfile;
- int revision; /* svn revision of binary that saved file */
+ int revision; /* svn revision of binary that saved file */
+ short recovered; /* indicate the main->name (file) is the recovered one */
struct Library *curlib;
ListBase scene;
@@ -92,6 +93,8 @@ typedef struct Main {
char id_tag_update[256];
} Main;
+#define MAIN_VERSION_ATLEAST(main, ver, subver) \
+ ((main)->versionfile >= (ver) || (main->versionfile == (ver) && (main)->subversionfile >= (subver)))
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index e53d0efffbd..3fc1b7d6136 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -229,8 +229,6 @@ typedef struct UvElement {
/* Next UvElement corresponding to same vertex */
struct UvElement *next;
/* Face the element belongs to */
- struct BMFace *face;
- /* Index in the editFace of the uv */
struct BMLoop *l;
/* index in loop. */
unsigned short tfindex;
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 2fa78b30835..cc260b8f60c 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -358,8 +358,6 @@ int modifiers_isCorrectableDeformed(struct Object *ob);
void modifier_freeTemporaryData(struct ModifierData *md);
int modifiers_isPreview(struct Object *ob);
-int modifiers_indexInObject(struct Object *ob, struct ModifierData *md);
-
typedef struct CDMaskLink {
struct CDMaskLink *next;
CustomDataMask mask;
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index ec0703248fd..bfae1bd2390 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -76,7 +76,8 @@ void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
void BKE_object_unlink(struct Object *ob);
int BKE_object_exists_check(struct Object *obtest);
-
+int BKE_object_is_in_editmode(struct Object *ob);
+
struct Object *BKE_object_add_only_object(int type, const char *name);
struct Object *BKE_object_add(struct Scene *scene, int type);
void *BKE_object_obdata_add_from_type(int type);
@@ -87,12 +88,12 @@ void BKE_object_make_local(struct Object *ob);
int BKE_object_is_libdata(struct Object *ob);
int BKE_object_obdata_is_libdata(struct Object *ob);
-void BKE_object_scale_to_mat3(struct Object *ob, float mat[][3]);
-void BKE_object_rot_to_mat3(struct Object *ob, float mat[][3]);
-void BKE_object_mat3_to_rot(struct Object *ob, float mat[][3], short use_compat);
-void BKE_object_to_mat3(struct Object *ob, float mat[][3]);
-void BKE_object_to_mat4(struct Object *ob, float mat[][4]);
-void BKE_object_apply_mat4(struct Object *ob, float mat[][4], const short use_compat, const short use_parent);
+void BKE_object_scale_to_mat3(struct Object *ob, float mat[3][3]);
+void BKE_object_rot_to_mat3(struct Object *ob, float mat[3][3], short use_drot);
+void BKE_object_mat3_to_rot(struct Object *ob, float mat[3][3], short use_compat);
+void BKE_object_to_mat3(struct Object *ob, float mat[3][3]);
+void BKE_object_to_mat4(struct Object *ob, float mat[4][4]);
+void BKE_object_apply_mat4(struct Object *ob, float mat[4][4], const short use_compat, const short use_parent);
int BKE_object_pose_context_check(struct Object *ob);
struct Object *BKE_object_pose_armature_get(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index ec03f53dbdb..f15ad296e4a 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -20,7 +20,9 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Adaptive time step
+ * Classical SPH
+ * Copyright 2011-2012 AutoCRC
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -58,6 +60,7 @@ struct RNG;
struct SurfaceModifierData;
struct BVHTreeRay;
struct BVHTreeRayHit;
+struct EdgeHash;
#define PARTICLE_P ParticleData * pa; int p
#define LOOP_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++)
@@ -85,6 +88,24 @@ typedef struct ParticleSimulationData {
float courant_num;
} ParticleSimulationData;
+typedef struct SPHData {
+ ParticleSystem *psys[10];
+ ParticleData *pa;
+ float mass;
+ struct EdgeHash *eh;
+ float *gravity;
+ float hfac;
+ /* Average distance to neighbours (other particles in the support domain),
+ for calculating the Courant number (adaptive time step). */
+ int pass;
+ float element_size;
+ float flow[3];
+
+ /* Integrator callbacks. This allows different SPH implementations. */
+ void (*force_cb) (void *sphdata_v, ParticleKey *state, float *force, float *impulse);
+ void (*density_cb) (void *rangedata_v, int index, float squared_dist);
+} SPHData;
+
typedef struct ParticleTexture {
float ivel; /* used in reset */
float time, life, exist, size; /* used in init */
@@ -247,7 +268,7 @@ void BKE_particlesettings_free(struct ParticleSettings *part);
void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit);
void psys_free(struct Object *ob, struct ParticleSystem *psys);
-void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset);
+void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset);
void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
int psys_render_simplify_distribution(struct ParticleThreadContext *ctx, int tot);
int psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
@@ -283,12 +304,16 @@ float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa
void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, struct ParticleKey *state, int vel);
int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always);
+void psys_sph_init(struct ParticleSimulationData *sim, struct SPHData *sphdata);
+void psys_sph_finalise(struct SPHData *sphdata);
+void psys_sph_density(struct BVHTree *tree, struct SPHData* data, float co[3], float vars[2]);
+
/* for anim.c */
void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings *part,
struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa,
float uv[2], float orco[3]);
void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa,
- struct ParticleCacheKey *cache, float mat[][4], float *scale);
+ struct ParticleCacheKey *cache, float mat[4][4], float *scale);
ParticleThread *psys_threads_create(struct ParticleSimulationData *sim);
void psys_threads_free(ParticleThread *threads);
@@ -322,9 +347,9 @@ void psys_free_children(struct ParticleSystem *psys);
void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, int velocity);
void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float vec[3]);
-void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]);
-void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]);
-void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]);
+void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
+void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
+void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
float psys_get_dietime_from_cache(struct PointCache *cache, int index);
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
new file mode 100644
index 00000000000..302de593963
--- /dev/null
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -0,0 +1,270 @@
+/*
+ * ***** 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 __BLI_PBVH_H__
+#define __BLI_PBVH_H__
+
+/** \file BKE_pbvh.h
+ * \ingroup bke
+ * \brief A BVH for high poly meshes.
+ */
+
+#include "BLI_bitmap.h"
+
+struct CCGElem;
+struct CCGKey;
+struct CustomData;
+struct DMFlagMat;
+struct DMGridAdjacency;
+struct ListBase;
+struct MFace;
+struct MVert;
+struct PBVH;
+struct PBVHNode;
+
+typedef struct PBVH PBVH;
+typedef struct PBVHNode PBVHNode;
+
+typedef struct {
+ float (*co)[3];
+} PBVHProxyNode;
+
+/* Callbacks */
+
+/* returns 1 if the search should continue from this node, 0 otherwise */
+typedef int (*BLI_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);
+
+/* Building */
+
+PBVH *BLI_pbvh_new(void);
+void BLI_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,
+ struct DMGridAdjacency *gridadj, int totgrid,
+ struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
+ unsigned int **grid_hidden);
+void BLI_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 BLI_pbvh_search_gather(PBVH *bvh,
+ BLI_pbvh_SearchCallback scb, void *search_data,
+ PBVHNode ***array, int *tot);
+
+/* Raycast
+ * the hit callback is called for all leaf nodes intersecting the ray;
+ * 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,
+ const float ray_start[3], const float ray_normal[3],
+ int original);
+
+int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
+ 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));
+
+/* PBVH Access */
+typedef enum {
+ PBVH_FACES,
+ PBVH_GRIDS,
+} PBVHType;
+
+PBVHType BLI_pbvh_type(const PBVH *bvh);
+
+/* multires hidden data, only valid for type == PBVH_GRIDS */
+unsigned int **BLI_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);
+
+/* Node Access */
+
+typedef enum {
+ PBVH_Leaf = 1,
+
+ PBVH_UpdateNormals = 2,
+ PBVH_UpdateBB = 4,
+ PBVH_UpdateOriginalBB = 8,
+ PBVH_UpdateDrawBuffers = 16,
+ PBVH_UpdateRedraw = 32,
+
+ PBVH_RebuildDrawBuffers = 64,
+ PBVH_FullyHidden = 128
+} 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 BLI_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,
+ int *uniquevert, int *totvert);
+void BLI_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]);
+
+float BLI_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);
+/* test if AABB is at least partially outside the planes' volume */
+int BLI_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data);
+
+/* 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,
+ 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);
+
+
+/* Vertex Iterator */
+
+/* this iterator has quite a lot of code, but it's designed to:
+ * - allow the compiler to eliminate dead code and variables
+ * - spend most of the time in the relatively simple inner loop */
+
+/* note: PBVH_ITER_ALL does not skip hidden vertices,
+ * PBVH_ITER_UNIQUE does */
+#define PBVH_ITER_ALL 0
+#define PBVH_ITER_UNIQUE 1
+
+typedef struct PBVHVertexIter {
+ /* iteration */
+ int g;
+ int width;
+ int height;
+ int gx;
+ int gy;
+ int i;
+
+ /* grid */
+ struct CCGElem **grids;
+ struct CCGElem *grid;
+ struct CCGKey *key;
+ BLI_bitmap *grid_hidden, gh;
+ int *grid_indices;
+ int totgrid;
+ int gridsize;
+
+ /* mesh */
+ struct MVert *mverts;
+ int totvert;
+ int *vert_indices;
+ float *vmask;
+
+ /* 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;
+ float *co;
+ short *no;
+ float *fno;
+ float *mask;
+} PBVHVertexIter;
+
+#ifdef _MSC_VER
+#pragma warning (disable:4127) // conditional expression is constant
+#endif
+
+void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
+ PBVHVertexIter *vi, int mode);
+
+#define BLI_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++) { \
+ if (vi.grids) { \
+ vi.width = vi.gridsize; \
+ vi.height = vi.gridsize; \
+ vi.grid = vi.grids[vi.grid_indices[vi.g]]; \
+ if (mode == PBVH_ITER_UNIQUE) \
+ vi.gh = vi.grid_hidden[vi.grid_indices[vi.g]]; \
+ } \
+ else { \
+ vi.width = vi.totvert; \
+ vi.height = 1; \
+ } \
+ \
+ for (vi.gy = 0; vi.gy < vi.height; vi.gy++) { \
+ for (vi.gx = 0; vi.gx < vi.width; vi.gx++, vi.i++) { \
+ if (vi.grid) { \
+ vi.co = CCG_elem_co(vi.key, vi.grid); \
+ vi.fno = CCG_elem_no(vi.key, vi.grid); \
+ vi.mask = vi.key->has_mask ? CCG_elem_mask(vi.key, vi.grid) : NULL; \
+ vi.grid = CCG_elem_next(vi.key, vi.grid); \
+ if (vi.gh) { \
+ if (BLI_BITMAP_GET(vi.gh, vi.gy * vi.gridsize + vi.gx)) \
+ continue; \
+ } \
+ } \
+ else { \
+ vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \
+ if (mode == PBVH_ITER_UNIQUE && vi.mvert->flag & ME_HIDE) \
+ continue; \
+ vi.co = vi.mvert->co; \
+ vi.no = vi.mvert->no; \
+ if (vi.vmask) \
+ vi.mask = &vi.vmask[vi.vert_indices[vi.gx]]; \
+ } \
+
+#define BLI_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 BLI_pbvh_node_BB_reset(PBVHNode *node);
+//void BLI_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__ */
+
diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h
index e0eb8c04b60..99e60757f15 100644
--- a/source/blender/blenkernel/BKE_property.h
+++ b/source/blender/blenkernel/BKE_property.h
@@ -47,6 +47,7 @@ void BKE_bproperty_object_set(struct Object *ob, struct bProperty *
// int BKE_bproperty_cmp(struct bProperty *prop, const char *str);
void BKE_bproperty_set(struct bProperty *prop, const char *str);
void BKE_bproperty_add(struct bProperty *prop, const char *str);
-void BKE_bproperty_set_valstr(struct bProperty *prop, char *str);
+/* should really be called '_get_valstr()' or '_as_string()' */
+void BKE_bproperty_set_valstr(struct bProperty *prop, char str[MAX_PROPSTRING]);
#endif
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 9927c7a42ed..6447b2a8dee 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -47,7 +47,7 @@ struct RenderData;
struct SceneRenderLayer;
struct Scene;
struct Text;
-struct Text;
+struct Main;
#define SCE_COPY_NEW 0
#define SCE_COPY_EMPTY 1
@@ -67,7 +67,7 @@ void free_avicodecdata(struct AviCodecData *acd);
void free_qtcodecdata(struct QuicktimeCodecData *acd);
void BKE_scene_free(struct Scene *sce);
-struct Scene *BKE_scene_add(const char *name);
+struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
/* base functions */
struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 88294cb30b6..e3d9c513c5c 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -363,7 +363,7 @@ struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seq
struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
/* view3d draw callback, run when not in background view */
-typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, int, int, char[256]);
+typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, int, int, int, char[256]);
extern SequencerDrawView sequencer_view3d_cb;
/* copy/paste */
diff --git a/source/blender/blenkernel/BKE_tessmesh.h b/source/blender/blenkernel/BKE_tessmesh.h
index dea5e726671..9462822e25f 100644
--- a/source/blender/blenkernel/BKE_tessmesh.h
+++ b/source/blender/blenkernel/BKE_tessmesh.h
@@ -80,12 +80,11 @@ typedef struct BMEditMesh {
/*temp variables for x-mirror editing*/
int mirror_cdlayer; /* -1 is invalid */
- int mirr_free_arrays;
} BMEditMesh;
-void BMEdit_RecalcTessellation(BMEditMesh *tm);
+void BMEdit_RecalcTessellation(BMEditMesh *em);
BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate);
-BMEditMesh *BMEdit_Copy(BMEditMesh *tm);
+BMEditMesh *BMEdit_Copy(BMEditMesh *em);
BMEditMesh *BMEdit_FromObject(struct Object *ob);
void BMEdit_Free(BMEditMesh *em);
void BMEdit_UpdateLinkedCustomData(BMEditMesh *em);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index e3b16fd92e2..70a3f927b23 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -66,6 +66,7 @@ set(SRC
intern/bmfont.c
intern/boids.c
intern/booleanops_mesh.c
+ intern/bpath.c
intern/brush.c
intern/bullet.c
intern/bvhutils.c
@@ -103,9 +104,9 @@ set(SRC
intern/lattice.c
intern/library.c
intern/linestyle.c
+ intern/mask.c
intern/mask_evaluate.c
intern/mask_rasterize.c
- intern/mask.c
intern/material.c
intern/mball.c
intern/mesh.c
@@ -123,6 +124,7 @@ set(SRC
intern/paint.c
intern/particle.c
intern/particle_system.c
+ intern/pbvh.c
intern/pointcache.c
intern/property.c
intern/report.c
@@ -161,6 +163,7 @@ set(SRC
BKE_bmfont_types.h
BKE_boids.h
BKE_booleanops_mesh.h
+ BKE_bpath.h
BKE_brush.h
BKE_bullet.h
BKE_bvhutils.h
@@ -212,6 +215,7 @@ set(SRC
BKE_packedFile.h
BKE_paint.h
BKE_particle.h
+ BKE_pbvh.h
BKE_pointcache.h
BKE_property.h
BKE_report.h
@@ -237,6 +241,7 @@ set(SRC
BKE_world.h
BKE_writeavi.h
BKE_writeframeserver.h
+
depsgraph_private.h
nla_private.h
intern/CCGSubSurf.h
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index dc1c9b5a1a2..ccb21b209ea 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
import os
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index d09bea0f662..010839764b2 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -47,10 +47,10 @@
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_array.h"
-#include "BLI_pbvh.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
+#include "BKE_pbvh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_displist.h"
#include "BKE_key.h"
@@ -1421,7 +1421,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
}
/* grab modifiers until index i */
- if ((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
+ if ((index >= 0) && (BLI_findindex(&ob->modifiers, md) >= index))
break;
}
@@ -1666,7 +1666,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
/* grab modifiers until index i */
- if ((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
+ if ((index >= 0) && (BLI_findindex(&ob->modifiers, md) >= index))
break;
if (sculpt_mode && md->type == eModifierType_Multires)
@@ -2334,29 +2334,29 @@ static void make_vertexcosnos__mapFunc(void *userData, int index, const float co
/* it stores the normals as floats, but they can still be scaled as shorts (32767 = unit) */
/* in use now by vertex/weight paint and particle generating */
-float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
+DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
{
Mesh *me = ob->data;
DerivedMesh *dm;
- float *vertexcosnos;
+ DMCoNo *vertexcosnos;
/* lets prevent crashing... */
if (ob->type != OB_MESH || me->totvert == 0)
return NULL;
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
- vertexcosnos = MEM_callocN(6 * sizeof(float) * me->totvert, "vertexcosnos map");
+ vertexcosnos = MEM_callocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map");
if (dm->foreachMappedVert) {
dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos);
}
else {
- float *fp = vertexcosnos;
+ DMCoNo *v_co_no = vertexcosnos;
int a;
- for (a = 0; a < me->totvert; a++, fp += 6) {
- dm->getVertCo(dm, a, fp);
- dm->getVertNo(dm, a, fp + 3);
+ for (a = 0; a < me->totvert; a++, v_co_no++) {
+ dm->getVertCo(dm, a, v_co_no->co);
+ dm->getVertNo(dm, a, v_co_no->no);
}
}
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index dd27cc70ba3..83d1538ecbe 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -43,7 +43,6 @@
#include "DNA_object_types.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 9a2462e9724..4058809c275 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -76,7 +76,7 @@
/* --------------------- */
/* forward declarations */
-static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4],
+static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[4][4],
int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag);
/* ******************************************************************** */
@@ -706,7 +706,7 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua
#define DUPLILIST_FOR_RENDER 2
#define DUPLILIST_ANIMATED 4
-static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay,
+static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[4][4], int lay,
int persistent_id[MAX_DUPLI_RECUR], int level, int index, int type, short flag)
{
DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject");
@@ -930,7 +930,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
}
}
-static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR],
+static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[4][4], int persistent_id[MAX_DUPLI_RECUR],
int level, short flag)
{
Object *ob, *ob_iter;
@@ -1054,7 +1054,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
dm->release(dm);
}
-static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR],
+static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[4][4], int persistent_id[MAX_DUPLI_RECUR],
int level, short flag)
{
Object *ob, *ob_iter;
@@ -1240,7 +1240,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
dm->release(dm);
}
-static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], ParticleSystem *psys,
+static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[4][4],
+ int persistent_id[MAX_DUPLI_RECUR], ParticleSystem *psys,
int level, short flag)
{
GroupObject *go;
@@ -1479,7 +1480,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
/* blender internal needs this to be set to dupligroup to render
* groups correctly, but we don't want this hack for cycles */
- if(dupli_type_hack && GS(id->name) == ID_GR)
+ if (dupli_type_hack && GS(id->name) == ID_GR)
dupli_type = OB_DUPLIGROUP;
/* to give ipos in object correct offset */
@@ -1635,7 +1636,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int persiste
/* ------------- */
-static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4],
+static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[4][4],
int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag)
{
if ((ob->transflag & OB_DUPLI) == 0)
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 1970df54339..9155d67dc36 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -37,7 +37,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_bpath.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -640,7 +639,7 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info
}
}
-static void b_bone_deform(bPoseChanDeform *pdef_info, Bone *bone, float co[3], DualQuat *dq, float defmat[][3])
+static void b_bone_deform(bPoseChanDeform *pdef_info, Bone *bone, float co[3], DualQuat *dq, float defmat[3][3])
{
Mat4 *b_bone = pdef_info->b_bone_mats;
float (*mat)[4] = b_bone[0].mat;
@@ -722,7 +721,7 @@ float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3
}
}
-static void pchan_deform_mat_add(bPoseChannel *pchan, float weight, float bbonemat[][3], float mat[][3])
+static void pchan_deform_mat_add(bPoseChannel *pchan, float weight, float bbonemat[3][3], float mat[3][3])
{
float wmat[3][3];
@@ -736,7 +735,7 @@ static void pchan_deform_mat_add(bPoseChannel *pchan, float weight, float bbonem
}
static float dist_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, float vec[3], DualQuat *dq,
- float mat[][3], const float co[3])
+ float mat[3][3], const float co[3])
{
Bone *bone = pchan->bone;
float fac, contrib = 0.0;
@@ -783,7 +782,7 @@ static float dist_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, f
}
static void pchan_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, float weight, float vec[3], DualQuat *dq,
- float mat[][3], const float co[3], float *contrib)
+ float mat[3][3], const float co[3], float *contrib)
{
float cop[3], bbonemat[3][3];
DualQuat bbonedq;
@@ -1089,7 +1088,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
/* ************ END Armature Deform ******************* */
-void get_objectspace_bone_matrix(struct Bone *bone, float M_accumulatedMatrix[][4], int UNUSED(root),
+void get_objectspace_bone_matrix(struct Bone *bone, float M_accumulatedMatrix[4][4], int UNUSED(root),
int UNUSED(posed))
{
copy_m4_m4(M_accumulatedMatrix, bone->arm_mat);
@@ -1098,7 +1097,7 @@ void get_objectspace_bone_matrix(struct Bone *bone, float M_accumulatedMatrix[][
/* **************** Space to Space API ****************** */
/* Convert World-Space Matrix to Pose-Space Matrix */
-void BKE_armature_mat_world_to_pose(Object *ob, float inmat[][4], float outmat[][4])
+void BKE_armature_mat_world_to_pose(Object *ob, float inmat[4][4], float outmat[4][4])
{
float obmat[4][4];
@@ -1132,7 +1131,7 @@ void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outl
/* Simple helper, computes the offset bone matrix.
* offs_bone = yoffs(b-1) + root(b) + bonemat(b).
* Not exported, as it is only used in this file currently... */
-static void get_offset_bone_mat(Bone *bone, float offs_bone[][4])
+static void get_offset_bone_mat(Bone *bone, float offs_bone[4][4])
{
if (!bone->parent)
return;
@@ -1164,7 +1163,7 @@ static void get_offset_bone_mat(Bone *bone, float offs_bone[][4])
* pose-channel into its local space (i.e. 'visual'-keyframing).
* (note: I don't understand that, so I keep it :p --mont29).
*/
-void BKE_pchan_to_pose_mat(bPoseChannel *pchan, float rotscale_mat[][4], float loc_mat[][4])
+void BKE_pchan_to_pose_mat(bPoseChannel *pchan, float rotscale_mat[4][4], float loc_mat[4][4])
{
Bone *bone, *parbone;
bPoseChannel *parchan;
@@ -1253,7 +1252,7 @@ void BKE_pchan_to_pose_mat(bPoseChannel *pchan, float rotscale_mat[][4], float l
/* Convert Pose-Space Matrix to Bone-Space Matrix.
* NOTE: this cannot be used to convert to pose-space transforms of the supplied
* pose-channel into its local space (i.e. 'visual'-keyframing) */
-void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float outmat[][4])
+void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[4][4], float outmat[4][4])
{
float rotscale_mat[4][4], loc_mat[4][4], inmat_[4][4];
@@ -1269,7 +1268,7 @@ void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float
}
/* Convert Bone-Space Matrix to Pose-Space Matrix. */
-void BKE_armature_mat_bone_to_pose(bPoseChannel *pchan, float inmat[][4], float outmat[][4])
+void BKE_armature_mat_bone_to_pose(bPoseChannel *pchan, float inmat[4][4], float outmat[4][4])
{
float rotscale_mat[4][4], loc_mat[4][4], inmat_[4][4];
@@ -1298,7 +1297,7 @@ void BKE_armature_loc_pose_to_bone(bPoseChannel *pchan, const float inloc[3], fl
copy_v3_v3(outloc, nLocMat[3]);
}
-void BKE_armature_mat_pose_to_bone_ex(Object *ob, bPoseChannel *pchan, float inmat[][4], float outmat[][4])
+void BKE_armature_mat_pose_to_bone_ex(Object *ob, bPoseChannel *pchan, float inmat[4][4], float outmat[4][4])
{
bPoseChannel work_pchan = *pchan;
@@ -1316,7 +1315,7 @@ void BKE_armature_mat_pose_to_bone_ex(Object *ob, bPoseChannel *pchan, float inm
}
/* same as BKE_object_mat3_to_rot() */
-void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, float mat[][3], short use_compat)
+void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, float mat[3][3], short use_compat)
{
switch (pchan->rotmode) {
case ROT_MODE_QUAT:
@@ -1335,7 +1334,7 @@ void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, float mat[][3], short use_compat
/* Apply a 4x4 matrix to the pose bone,
* similar to BKE_object_apply_mat4() */
-void BKE_pchan_apply_mat4(bPoseChannel *pchan, float mat[][4], short use_compat)
+void BKE_pchan_apply_mat4(bPoseChannel *pchan, float mat[4][4], short use_compat)
{
float rot[3][3];
mat4_to_loc_rot_size(pchan->loc, rot, pchan->size, mat);
@@ -1345,7 +1344,7 @@ void BKE_pchan_apply_mat4(bPoseChannel *pchan, float mat[][4], short use_compat)
/* Remove rest-position effects from pose-transform for obtaining
* 'visual' transformation of pose-channel.
* (used by the Visual-Keyframing stuff) */
-void BKE_armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float arm_mat[][4])
+void BKE_armature_mat_pose_to_delta(float delta_mat[4][4], float pose_mat[4][4], float arm_mat[4][4])
{
float imat[4][4];
@@ -1425,7 +1424,7 @@ void BKE_rotMode_change_values(float quat[4], float eul[3], float axis[3], float
* *************************************************************************** */
/* Computes vector and roll based on a rotation.
* "mat" must contain only a rotation, and no scaling. */
-void mat3_to_vec_roll(float mat[][3], float r_vec[3], float *r_roll)
+void mat3_to_vec_roll(float mat[3][3], float r_vec[3], float *r_roll)
{
if (r_vec) {
copy_v3_v3(r_vec, mat[1]);
@@ -1444,7 +1443,7 @@ void mat3_to_vec_roll(float mat[][3], float r_vec[3], float *r_roll)
/* Calculates the rest matrix of a bone based
* On its vector and a roll around that vector */
-void vec_roll_to_mat3(const float vec[3], const float roll, float mat[][3])
+void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3])
{
float nor[3], axis[3], target[3] = {0, 1, 0};
float theta;
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index f0d201ea3f7..5c0856bc95b 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -54,9 +54,9 @@
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
+#include "DNA_windowmanager_types.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
#include "BLI_callbacks.h"
@@ -65,6 +65,7 @@
#include "IMB_moviecache.h"
#include "BKE_blender.h"
+#include "BKE_bpath.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_displist.h"
@@ -80,8 +81,11 @@
#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
+
#include "RE_pipeline.h"
+#include "BLF_api.h"
+
#include "BLO_undofile.h"
#include "BLO_readfile.h"
#include "BLO_writefile.h"
@@ -179,7 +183,7 @@ static void clean_paths(Main *main)
{
Scene *scene;
- BLI_bpath_traverse_main(main, clean_paths_visit_cb, BLI_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
+ BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
for (scene = main->scene.first; scene; scene = scene->id.next) {
BLI_clean(scene->r.pic);
@@ -230,6 +234,9 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
/* but use new Scene pointer */
curscene = bfd->curscene;
if (curscene == NULL) curscene = bfd->main->scene.first;
+ /* empty file, we add a scene to make Blender work */
+ if (curscene == NULL) curscene = BKE_scene_add(bfd->main, "Empty");
+
/* and we enforce curscene to be in current screen */
if (curscreen) curscreen->scene = curscene; /* can run in bgmode */
@@ -270,7 +277,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
G.fileflags = bfd->fileflags;
CTX_wm_manager_set(C, G.main->wm.first);
CTX_wm_screen_set(C, bfd->curscreen);
- CTX_data_scene_set(C, bfd->curscreen->scene);
+ CTX_data_scene_set(C, bfd->curscene);
CTX_wm_area_set(C, NULL);
CTX_wm_region_set(C, NULL);
CTX_wm_menu_set(C, NULL);
@@ -280,7 +287,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
if (CTX_data_scene(C) == NULL) {
/* in case we don't even have a local scene, add one */
if (!G.main->scene.first)
- BKE_scene_add("Scene");
+ BKE_scene_add(G.main, "Scene");
CTX_data_scene_set(C, G.main->scene.first);
CTX_wm_screen(C)->scene = CTX_data_scene(C);
@@ -310,23 +317,38 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
if (G.main->versionfile < 250)
do_versions_ipos_to_animato(G.main);
- if (recover && bfd->filename[0] && G.relbase_valid) {
+ G.main->recovered = 0;
+
+ /* startup.blend or recovered startup */
+ if (bfd->filename[0] == 0) {
+ G.main->name[0] = 0;
+ }
+ else if (recover && G.relbase_valid) {
/* in case of autosave or quit.blend, use original filename instead
* use relbase_valid to make sure the file is saved, else we get <memory2> in the filename */
filepath = bfd->filename;
+ G.main->recovered = 1;
+
+ /* these are the same at times, should never copy to the same location */
+ if (G.main->name != filepath)
+ BLI_strncpy(G.main->name, filepath, FILE_MAX);
}
-#if 0
- else if (!G.relbase_valid) {
- /* otherwise, use an empty string as filename, rather than <memory2> */
- filepath = "";
- }
-#endif
- /* these are the same at times, should never copy to the same location */
- if (G.main->name != filepath)
- BLI_strncpy(G.main->name, filepath, FILE_MAX);
-
/* baseflags, groups, make depsgraph, etc */
+ /* first handle case if other windows have different scenes visible */
+ if (mode == 0) {
+ wmWindowManager *wm = G.main->wm.first;
+
+ if (wm) {
+ wmWindow *win;
+
+ for (win = wm->windows.first; win; win = win->next) {
+ if (win->screen && win->screen->scene) /* zealous check... */
+ if (win->screen->scene != CTX_data_scene(C))
+ BKE_scene_set_background(G.main, win->screen->scene);
+ }
+ }
+ }
BKE_scene_set_background(G.main, CTX_data_scene(C));
if (mode != 'u') {
@@ -335,7 +357,6 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
MEM_freeN(bfd);
- (void)curscene; /* quiet warning */
}
static int handle_subversion_warning(Main *main, ReportList *reports)
@@ -393,6 +414,14 @@ void BKE_userdef_free(void)
BLI_freelistN(&U.addons);
}
+/* handle changes in settings that need recalc */
+void BKE_userdef_state(void)
+{
+ BLF_default_dpi(U.pixelsize * U.dpi);
+ U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72;
+
+}
+
int BKE_read_file(bContext *C, const char *filepath, ReportList *reports)
{
BlendFileData *bfd;
@@ -439,14 +468,57 @@ int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *report
BlendFileData *bfd;
bfd = BLO_read_from_memfile(CTX_data_main(C), G.main->name, memfile, reports);
- if (bfd)
+ if (bfd) {
+ /* remove the unused screens and wm */
+ while (bfd->main->wm.first)
+ BKE_libblock_free(&bfd->main->wm, bfd->main->wm.first);
+ while (bfd->main->screen.first)
+ BKE_libblock_free(&bfd->main->screen, bfd->main->screen.first);
+
setup_app_data(C, bfd, "<memory1>");
+ }
else
BKE_reports_prepend(reports, "Loading failed: ");
return (bfd ? 1 : 0);
}
+/* only read the userdef from a .blend */
+int BKE_read_file_userdef(const char *filepath, ReportList *reports)
+{
+ BlendFileData *bfd;
+ int retval = 0;
+
+ bfd = BLO_read_from_file(filepath, reports);
+ if (bfd->user) {
+ retval = BKE_READ_FILE_OK_USERPREFS;
+
+ /* only here free userdef themes... */
+ BKE_userdef_free();
+
+ U = *bfd->user;
+ MEM_freeN(bfd->user);
+ }
+ free_main(bfd->main);
+ MEM_freeN(bfd);
+
+ return retval;
+}
+
+/* only write the userdef in a .blend */
+int BKE_write_file_userdef(const char *filepath, ReportList *reports)
+{
+ Main *mainb = MEM_callocN(sizeof(Main), "empty main");
+ int retval = 0;
+
+ if (BLO_write_file(mainb, filepath, G_FILE_USERPREFS, reports, NULL)) {
+ retval = 1;
+ }
+
+ MEM_freeN(mainb);
+
+ return retval;
+}
/* ***************** testing for break ************* */
@@ -728,48 +800,39 @@ char *BKE_undo_menu_string(void)
return menu;
}
-/* saves quit.blend */
-void BKE_undo_save_quit(void)
+/* saves .blend using undo buffer, returns 1 == success */
+int BKE_undo_save_file(const char *filename)
{
UndoElem *uel;
MemFileChunk *chunk;
- char str[FILE_MAX];
const int flag = O_BINARY + O_WRONLY + O_CREAT + O_TRUNC + O_EXCL;
int file;
if ((U.uiflag & USER_GLOBALUNDO) == 0) {
- return;
+ return 0;
}
uel = curundo;
if (uel == NULL) {
fprintf(stderr, "No undo buffer to save recovery file\n");
- return;
- }
-
- /* no undo state to save */
- if (undobase.first == undobase.last) {
- return;
+ return 0;
}
- /* save the undo state as quit.blend */
- BLI_make_file_string("/", str, BLI_temporary_dir(), "quit.blend");
-
/* first try create the file, if it exists call without 'O_CREAT',
* to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */
errno = 0;
- file = BLI_open(str, flag, 0666);
+ file = BLI_open(filename, flag, 0666);
if (file == -1) {
if (errno == EEXIST) {
errno = 0;
- file = BLI_open(str, flag & ~O_CREAT, 0666);
+ file = BLI_open(filename, flag & ~O_CREAT, 0666);
}
}
if (file == -1) {
fprintf(stderr, "Unable to save '%s': %s\n",
- str, errno ? strerror(errno) : "Unknown error opening file");
- return;
+ filename, errno ? strerror(errno) : "Unknown error opening file");
+ return 0;
}
for (chunk = uel->memfile.chunks.first; chunk; chunk = chunk->next) {
@@ -777,16 +840,15 @@ void BKE_undo_save_quit(void)
break;
}
}
-
+
close(file);
if (chunk) {
fprintf(stderr, "Unable to save '%s': %s\n",
- str, errno ? strerror(errno) : "Unknown error writing file");
- }
- else {
- printf("Saved session recovery to '%s'\n", str);
+ filename, errno ? strerror(errno) : "Unknown error writing file");
+ return 0;
}
+ return 1;
}
/* sets curscene */
@@ -806,3 +868,131 @@ Main *BKE_undo_get_main(Scene **scene)
return mainp;
}
+/* ************** copy paste .blend, partial saves ********** */
+
+/* assumes data is in G.main */
+
+void BKE_copybuffer_begin(void)
+{
+ /* set all id flags to zero; */
+ flag_all_listbases_ids(LIB_NEED_EXPAND | LIB_DOIT, 0);
+}
+
+void BKE_copybuffer_tag_ID(ID *id)
+{
+ id->flag |= LIB_NEED_EXPAND | LIB_DOIT;
+}
+
+static void copybuffer_doit(void *UNUSED(handle), Main *UNUSED(bmain), void *vid)
+{
+ if (vid) {
+ ID *id = vid;
+ id->flag |= LIB_NEED_EXPAND | LIB_DOIT;
+ }
+}
+
+/* frees main in end */
+int BKE_copybuffer_save(char *filename, ReportList *reports)
+{
+ Main *mainb = MEM_callocN(sizeof(Main), "copybuffer");
+ ListBase *lbarray[MAX_LIBARRAY], *fromarray[MAX_LIBARRAY];
+ int a, retval;
+
+ BLO_main_expander(copybuffer_doit);
+ BLO_expand_main(NULL, G.main);
+
+ /* move over all tagged blocks */
+ set_listbasepointers(G.main, fromarray);
+ a = set_listbasepointers(mainb, lbarray);
+ while (a--) {
+ ID *id, *nextid;
+ ListBase *lb1 = lbarray[a], *lb2 = fromarray[a];
+
+ for (id = lb2->first; id; id = nextid) {
+ nextid = id->next;
+ if (id->flag & LIB_DOIT) {
+ BLI_remlink(lb2, id);
+ BLI_addtail(lb1, id);
+ }
+ }
+ }
+
+
+ /* save the buffer */
+ retval = BLO_write_file(mainb, filename, 0, reports, NULL);
+
+ /* move back the main, now sorted again */
+ set_listbasepointers(G.main, lbarray);
+ a = set_listbasepointers(mainb, fromarray);
+ while (a--) {
+ ID *id;
+ ListBase *lb1 = lbarray[a], *lb2 = fromarray[a];
+
+ while (lb2->first) {
+ id = lb2->first;
+ BLI_remlink(lb2, id);
+ BLI_addtail(lb1, id);
+ id_sort_by_name(lb1, id);
+ }
+ }
+
+ MEM_freeN(mainb);
+
+ /* set id flag to zero; */
+ flag_all_listbases_ids(LIB_NEED_EXPAND | LIB_DOIT, 0);
+
+ return retval;
+}
+
+/* return success (1) */
+int BKE_copybuffer_paste(bContext *C, char *libname, ReportList *reports)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Main *mainl = NULL;
+ Library *lib;
+ BlendHandle *bh;
+
+ bh = BLO_blendhandle_from_file(libname, reports);
+
+ if (bh == NULL) {
+ /* error reports will have been made by BLO_blendhandle_from_file() */
+ return 0;
+ }
+
+ BKE_scene_base_deselect_all(scene);
+
+ /* tag everything, all untagged data can be made local
+ * its also generally useful to know what is new
+ *
+ * take extra care flag_all_listbases_ids(LIB_LINK_TAG, 0) is called after! */
+ flag_all_listbases_ids(LIB_PRE_EXISTING, 1);
+
+ /* here appending/linking starts */
+ mainl = BLO_library_append_begin(bmain, &bh, libname);
+
+ BLO_library_append_all(mainl, bh);
+
+ BLO_library_append_end(C, mainl, &bh, 0, 0);
+
+ /* mark all library linked objects to be updated */
+ recalc_all_library_objects(bmain);
+ IMB_colormanagement_check_file_config(bmain);
+
+ /* append, rather than linking */
+ lib = BLI_findstring(&bmain->library, libname, offsetof(Library, filepath));
+ BKE_library_make_local(bmain, lib, 1);
+
+ /* important we unset, otherwise these object wont
+ * link into other scenes from this blend file */
+ flag_all_listbases_ids(LIB_PRE_EXISTING, 0);
+
+ /* recreate dependency graph to include new objects */
+ DAG_scene_sort(bmain, scene);
+ DAG_ids_flush_update(bmain, 0);
+
+ BLO_blendhandle_close(bh);
+ /* remove library... */
+
+ return 1;
+}
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
new file mode 100644
index 00000000000..24b13b062f3
--- /dev/null
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -0,0 +1,726 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell barton, Alex Fraser
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/bpath.c
+ * \ingroup bli
+ */
+
+/* TODO,
+ * currently there are some cases we don't support.
+ * - passing output paths to the visitor?, like render out.
+ * - passing sequence strips with many images.
+ * - passing directory paths - visitors don't know which path is a dir or a file.
+ * */
+
+#include <sys/stat.h>
+
+#include <string.h>
+#include <assert.h>
+
+/* path/file handling stuff */
+#ifndef WIN32
+# include <dirent.h>
+# include <unistd.h>
+#else
+# include <io.h>
+# include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_image_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_object_fluidsim.h"
+#include "DNA_object_force.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_text_types.h"
+#include "DNA_material_types.h"
+#include "DNA_node_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_smoke_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_font.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_report.h"
+#include "BKE_sequencer.h"
+#include "BKE_image.h" /* so we can check the image's type */
+
+#include "BKE_bpath.h" /* own include */
+
+static int checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
+{
+ ReportList *reports = (ReportList *)userdata;
+
+ if (!BLI_exists(path_src)) {
+ BKE_reportf(reports, RPT_WARNING, "Path '%s' not found", path_src);
+ }
+
+ return FALSE;
+}
+
+/* high level function */
+void BKE_bpath_missing_files_check(Main *bmain, ReportList *reports)
+{
+ BKE_bpath_traverse_main(bmain, checkMissingFiles_visit_cb, BKE_BPATH_TRAVERSE_ABS, reports);
+}
+
+typedef struct BPathRemap_Data {
+ const char *basedir;
+ ReportList *reports;
+
+ int count_tot;
+ int count_changed;
+ int count_failed;
+} BPathRemap_Data;
+
+static int makeFilesRelative_visit_cb(void *userdata, char *path_dst, const char *path_src)
+{
+ BPathRemap_Data *data = (BPathRemap_Data *)userdata;
+
+ data->count_tot++;
+
+ if (BLI_path_is_rel(path_src)) {
+ return FALSE; /* already relative */
+ }
+ else {
+ strcpy(path_dst, path_src);
+ BLI_path_rel(path_dst, data->basedir);
+ if (BLI_path_is_rel(path_dst)) {
+ data->count_changed++;
+ }
+ else {
+ BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made relative", path_src);
+ data->count_failed++;
+ }
+ return TRUE;
+ }
+}
+
+void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
+{
+ BPathRemap_Data data = {NULL};
+
+ if (basedir[0] == '\0') {
+ printf("%s: basedir='', this is a bug\n", __func__);
+ return;
+ }
+
+ data.basedir = basedir;
+ data.reports = reports;
+
+ BKE_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data);
+
+ BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
+ "Total files %d | Changed %d | Failed %d",
+ data.count_tot, data.count_changed, data.count_failed);
+}
+
+static int makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const char *path_src)
+{
+ BPathRemap_Data *data = (BPathRemap_Data *)userdata;
+
+ data->count_tot++;
+
+ if (BLI_path_is_rel(path_src) == FALSE) {
+ return FALSE; /* already absolute */
+ }
+ else {
+ strcpy(path_dst, path_src);
+ BLI_path_abs(path_dst, data->basedir);
+ if (BLI_path_is_rel(path_dst) == FALSE) {
+ data->count_changed++;
+ }
+ else {
+ BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src);
+ data->count_failed++;
+ }
+ return TRUE;
+ }
+}
+
+/* similar to BKE_bpath_relative_convert - keep in sync! */
+void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
+{
+ BPathRemap_Data data = {NULL};
+
+ if (basedir[0] == '\0') {
+ printf("%s: basedir='', this is a bug\n", __func__);
+ return;
+ }
+
+ data.basedir = basedir;
+ data.reports = reports;
+
+ BKE_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data);
+
+ BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
+ "Total files %d | Changed %d | Failed %d",
+ data.count_tot, data.count_changed, data.count_failed);
+}
+
+/**
+ * find this file recursively, use the biggest file so thumbnails don't get used by mistake
+ * \param filename_new: the path will be copied here, caller must initialize as empty string.
+ * \param dirname: subdir to search
+ * \param filename: set this filename
+ * \param filesize: filesize for the file
+ *
+ * \returns found: 1/0.
+ */
+#define MAX_RECUR 16
+static int findFileRecursive(char *filename_new,
+ const char *dirname,
+ const char *filename,
+ int *filesize,
+ int *recur_depth)
+{
+ /* file searching stuff */
+ DIR *dir;
+ struct dirent *de;
+ struct stat status;
+ char path[FILE_MAX];
+ int size;
+ int found = FALSE;
+
+ dir = opendir(dirname);
+
+ if (dir == NULL)
+ return found;
+
+ if (*filesize == -1)
+ *filesize = 0; /* dir opened fine */
+
+ while ((de = readdir(dir)) != NULL) {
+
+ if (strcmp(".", de->d_name) == 0 || strcmp("..", de->d_name) == 0)
+ continue;
+
+ BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
+
+ if (stat(path, &status) != 0)
+ continue; /* cant stat, don't bother with this file, could print debug info here */
+
+ if (S_ISREG(status.st_mode)) { /* is file */
+ if (strncmp(filename, de->d_name, FILE_MAX) == 0) { /* name matches */
+ /* open the file to read its size */
+ size = status.st_size;
+ if ((size > 0) && (size > *filesize)) { /* find the biggest file */
+ *filesize = size;
+ BLI_strncpy(filename_new, path, FILE_MAX);
+ found = TRUE;
+ }
+ }
+ }
+ else if (S_ISDIR(status.st_mode)) { /* is subdir */
+ if (*recur_depth <= MAX_RECUR) {
+ (*recur_depth)++;
+ found |= findFileRecursive(filename_new, path, filename, filesize, recur_depth);
+ (*recur_depth)--;
+ }
+ }
+ }
+ closedir(dir);
+ return found;
+}
+
+typedef struct BPathFind_Data {
+ const char *basedir;
+ char searchdir[FILE_MAX];
+ ReportList *reports;
+} BPathFind_Data;
+
+static int findMissingFiles_visit_cb(void *userdata, char *path_dst, const char *path_src)
+{
+ BPathFind_Data *data = (BPathFind_Data *)userdata;
+ char filename_new[FILE_MAX];
+
+ int filesize = -1;
+ int recur_depth = 0;
+ int found;
+
+ filename_new[0] = '\0';
+
+ found = findFileRecursive(filename_new,
+ data->searchdir, BLI_path_basename((char *)path_src),
+ &filesize, &recur_depth);
+
+ if (filesize == -1) { /* could not open dir */
+ BKE_reportf(data->reports, RPT_WARNING,
+ "Could not open directory '%s'",
+ BLI_path_basename(data->searchdir));
+ return FALSE;
+ }
+ else if (found == FALSE) {
+ BKE_reportf(data->reports, RPT_WARNING,
+ "Could not find '%s' in '%s'",
+ BLI_path_basename((char *)path_src), data->searchdir);
+ return FALSE;
+ }
+ else {
+ BLI_strncpy(path_dst, filename_new, FILE_MAX);
+ return TRUE;
+ }
+}
+
+void BKE_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportList *reports)
+{
+ struct BPathFind_Data data = {NULL};
+
+ data.reports = reports;
+ BLI_split_dir_part(searchpath, data.searchdir, sizeof(data.searchdir));
+
+ BKE_bpath_traverse_main(bmain, findMissingFiles_visit_cb, 0, (void *)&data);
+}
+
+/* Run a visitor on a string, replacing the contents of the string as needed. */
+static int rewrite_path_fixed(char *path, BPathVisitor visit_cb, const char *absbase, void *userdata)
+{
+ char path_src_buf[FILE_MAX];
+ const char *path_src;
+ char path_dst[FILE_MAX];
+
+ if (absbase) {
+ BLI_strncpy(path_src_buf, path, sizeof(path_src_buf));
+ BLI_path_abs(path_src_buf, absbase);
+ path_src = path_src_buf;
+ }
+ else {
+ path_src = path;
+ }
+
+ if (visit_cb(userdata, path_dst, path_src)) {
+ BLI_strncpy(path, path_dst, FILE_MAX);
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+static int rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR],
+ char path_file[FILE_MAXFILE],
+ BPathVisitor visit_cb,
+ const char *absbase,
+ void *userdata)
+{
+ char path_src[FILE_MAX];
+ char path_dst[FILE_MAX];
+
+ BLI_join_dirfile(path_src, sizeof(path_src), path_dir, path_file);
+
+ if (absbase) {
+ BLI_path_abs(path_src, absbase);
+ }
+
+ if (visit_cb(userdata, path_dst, (const char *)path_src)) {
+ BLI_split_dirfile(path_dst, path_dir, path_file, FILE_MAXDIR, FILE_MAXFILE);
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+static int rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *absbase, void *userdata)
+{
+ char path_src_buf[FILE_MAX];
+ const char *path_src;
+ char path_dst[FILE_MAX];
+
+ if (absbase) {
+ BLI_strncpy(path_src_buf, *path, sizeof(path_src_buf));
+ BLI_path_abs(path_src_buf, absbase);
+ path_src = path_src_buf;
+ }
+ else {
+ path_src = *path;
+ }
+
+ if (visit_cb(userdata, path_dst, path_src)) {
+ MEM_freeN((*path));
+ (*path) = BLI_strdup(path_dst);
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+/* Run visitor function 'visit' on all paths contained in 'id'. */
+void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
+{
+ const char *absbase = (flag & BKE_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL;
+
+ if ((flag & BKE_BPATH_TRAVERSE_SKIP_LIBRARY) && id->lib) {
+ return;
+ }
+
+ switch (GS(id->name)) {
+ case ID_IM:
+ {
+ Image *ima;
+ ima = (Image *)id;
+ if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+ if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+ rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data);
+ }
+ }
+ break;
+ }
+ case ID_BR:
+ {
+ Brush *brush = (Brush *)id;
+ if (brush->icon_filepath[0]) {
+ rewrite_path_fixed(brush->icon_filepath, visit_cb, absbase, bpath_user_data);
+ }
+ break;
+ }
+ case ID_OB:
+ {
+ Object *ob = (Object *)id;
+ ModifierData *md;
+ ParticleSystem *psys;
+
+#define BPATH_TRAVERSE_POINTCACHE(ptcaches) \
+ { \
+ PointCache *cache; \
+ for (cache = (ptcaches).first; cache; cache = cache->next) { \
+ if (cache->flag & PTCACHE_DISK_CACHE) { \
+ rewrite_path_fixed(cache->path, \
+ visit_cb, \
+ absbase, \
+ bpath_user_data); \
+ } \
+ } \
+ } (void)0
+
+ /* do via modifiers instead */
+#if 0
+ if (ob->fluidsimSettings) {
+ rewrite_path_fixed(ob->fluidsimSettings->surfdataPath, visit_cb, absbase, bpath_user_data);
+ }
+#endif
+
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Fluidsim) {
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
+ if (fluidmd->fss) {
+ rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data);
+ }
+ }
+ else if (md->type == eModifierType_Smoke) {
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
+ BPATH_TRAVERSE_POINTCACHE(smd->domain->ptcaches[0]);
+ }
+ }
+ else if (md->type == eModifierType_Cloth) {
+ ClothModifierData *clmd = (ClothModifierData *) md;
+ BPATH_TRAVERSE_POINTCACHE(clmd->ptcaches);
+ }
+ else if (md->type == eModifierType_Ocean) {
+ OceanModifierData *omd = (OceanModifierData *) md;
+ rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data);
+ }
+ }
+
+ if (ob->soft) {
+ BPATH_TRAVERSE_POINTCACHE(ob->soft->ptcaches);
+ }
+
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ BPATH_TRAVERSE_POINTCACHE(psys->ptcaches);
+ }
+
+#undef BPATH_TRAVERSE_POINTCACHE
+
+ break;
+ }
+ case ID_SO:
+ {
+ bSound *sound = (bSound *)id;
+ if (sound->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+ rewrite_path_fixed(sound->name, visit_cb, absbase, bpath_user_data);
+ }
+ break;
+ }
+ case ID_TXT:
+ if (((Text *)id)->name) {
+ rewrite_path_alloc(&((Text *)id)->name, visit_cb, absbase, bpath_user_data);
+ }
+ break;
+ case ID_VF:
+ {
+ VFont *vfont = (VFont *)id;
+ if (vfont->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+ if (BKE_vfont_is_builtin(vfont) == FALSE) {
+ rewrite_path_fixed(((VFont *)id)->name, visit_cb, absbase, bpath_user_data);
+ }
+ }
+ break;
+ }
+ case ID_MA:
+ {
+ Material *ma = (Material *)id;
+ bNodeTree *ntree = ma->nodetree;
+
+ if (ntree) {
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_SCRIPT) {
+ NodeShaderScript *nss = (NodeShaderScript *)node->storage;
+ rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
+ }
+ }
+ }
+ break;
+ }
+ case ID_NT:
+ {
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNode *node;
+
+ if (ntree->type == NTREE_SHADER) {
+ /* same as lines above */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_SCRIPT) {
+ NodeShaderScript *nss = (NodeShaderScript *)node->storage;
+ rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
+ }
+ }
+ }
+ break;
+ }
+ case ID_TE:
+ {
+ Tex *tex = (Tex *)id;
+ if (tex->type == TEX_VOXELDATA && TEX_VD_IS_SOURCE_PATH(tex->vd->file_format)) {
+ rewrite_path_fixed(tex->vd->source_path, visit_cb, absbase, bpath_user_data);
+ }
+ break;
+ }
+ case ID_SCE:
+ {
+ Scene *scene = (Scene *)id;
+ if (scene->ed) {
+ Sequence *seq;
+
+ SEQ_BEGIN(scene->ed, seq)
+ {
+ if (SEQ_HAS_PATH(seq)) {
+ if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM)) {
+ rewrite_path_fixed_dirfile(seq->strip->dir, seq->strip->stripdata->name,
+ visit_cb, absbase, bpath_user_data);
+ }
+ else if (seq->type == SEQ_TYPE_IMAGE) {
+ /* might want an option not to loop over all strips */
+ StripElem *se = seq->strip->stripdata;
+ int len = MEM_allocN_len(se) / sizeof(*se);
+ int i;
+
+ if (flag & BKE_BPATH_TRAVERSE_SKIP_MULTIFILE) {
+ /* only operate on one path */
+ len = MIN2(1, len);
+ }
+
+ for (i = 0; i < len; i++, se++) {
+ rewrite_path_fixed_dirfile(seq->strip->dir, se->name,
+ visit_cb, absbase, bpath_user_data);
+ }
+ }
+ else {
+ /* simple case */
+ rewrite_path_fixed(seq->strip->dir, visit_cb, absbase, bpath_user_data);
+ }
+ }
+
+ }
+ SEQ_END
+ }
+ break;
+ }
+ case ID_ME:
+ {
+ Mesh *me = (Mesh *)id;
+ if (me->ldata.external) {
+ rewrite_path_fixed(me->ldata.external->filename, visit_cb, absbase, bpath_user_data);
+ }
+ break;
+ }
+ 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);
+ }
+ break;
+ }
+ case ID_MC:
+ {
+ MovieClip *clip = (MovieClip *)id;
+ rewrite_path_fixed(clip->name, visit_cb, absbase, bpath_user_data);
+ break;
+ }
+ default:
+ /* Nothing to do for other IDs that don't contain file paths. */
+ break;
+ }
+}
+
+void BKE_bpath_traverse_id_list(Main *bmain, ListBase *lb, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
+{
+ ID *id;
+ for (id = lb->first; id; id = id->next) {
+ BKE_bpath_traverse_id(bmain, id, visit_cb, flag, bpath_user_data);
+ }
+}
+
+void BKE_bpath_traverse_main(Main *bmain, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a = set_listbasepointers(bmain, lbarray);
+ while (a--) {
+ BKE_bpath_traverse_id_list(bmain, lbarray[a], visit_cb, flag, bpath_user_data);
+ }
+}
+
+/* Rewrites a relative path to be relative to the main file - unless the path is
+ * absolute, in which case it is not altered. */
+int BKE_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *path_src)
+{
+ /* be sure there is low chance of the path being too short */
+ char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
+ const char *base_new = ((char **)pathbase_v)[0];
+ const char *base_old = ((char **)pathbase_v)[1];
+
+ if (BLI_path_is_rel(base_old)) {
+ printf("%s: error, old base path '%s' is not absolute.\n",
+ __func__, base_old);
+ return FALSE;
+ }
+
+ /* Make referenced file absolute. This would be a side-effect of
+ * BLI_cleanup_file, but we do it explicitly so we know if it changed. */
+ BLI_strncpy(filepath, path_src, FILE_MAX);
+ if (BLI_path_abs(filepath, base_old)) {
+ /* Path was relative and is now absolute. Remap.
+ * Important BLI_cleanup_dir runs before the path is made relative
+ * because it wont work for paths that start with "//../" */
+ BLI_cleanup_file(base_new, filepath);
+ BLI_path_rel(filepath, base_new);
+ BLI_strncpy(path_dst, filepath, FILE_MAX);
+ return TRUE;
+ }
+ else {
+ /* Path was not relative to begin with. */
+ return FALSE;
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+/**
+ * Backup/Restore/Free functions,
+ * \note These functions assume the data won't chane order.
+ */
+
+struct PathStore {
+ struct PathStore *next, *prev;
+} PathStore;
+
+static int bpath_list_append(void *userdata, char *UNUSED(path_dst), const char *path_src)
+{
+ /* store the path and string in a single alloc */
+ ListBase *ls = userdata;
+ size_t path_size = strlen(path_src) + 1;
+ struct PathStore *path_store = MEM_mallocN(sizeof(PathStore) + path_size, __func__);
+ char *filepath = (char *)(path_store + 1);
+
+ memcpy(filepath, path_src, path_size);
+ BLI_addtail(ls, path_store);
+ return FALSE;
+}
+
+static int bpath_list_restore(void *userdata, char *path_dst, const char *path_src)
+{
+ /* assume ls->first wont be NULL because the number of paths can't change!
+ * (if they do caller is wrong) */
+ ListBase *ls = userdata;
+ struct PathStore *path_store = ls->first;
+ const char *filepath = (char *)(path_store + 1);
+ int ret;
+
+ if (strcmp(path_src, filepath) == 0) {
+ ret = FALSE;
+ }
+ else {
+ BLI_strncpy(path_dst, filepath, FILE_MAX);
+ ret = TRUE;
+ }
+
+ BLI_freelinkN(ls, path_store);
+ return ret;
+}
+
+/* return ls_handle */
+void *BKE_bpath_list_backup(Main *bmain, const int flag)
+{
+ ListBase *ls = MEM_callocN(sizeof(ListBase), __func__);
+
+ BKE_bpath_traverse_main(bmain, bpath_list_append, flag, ls);
+
+ return ls;
+}
+
+void BKE_bpath_list_restore(Main *bmain, const int flag, void *ls_handle)
+{
+ ListBase *ls = ls_handle;
+
+ BKE_bpath_traverse_main(bmain, bpath_list_restore, flag, ls);
+}
+
+void BKE_bpath_list_free(void *ls_handle)
+{
+ ListBase *ls = ls_handle;
+ BLI_assert(ls->first == NULL); /* assumes we were used */
+ BLI_freelistN(ls);
+ MEM_freeN(ls);
+}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index f310895f590..405b1efb25d 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -39,18 +39,19 @@
#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_bpath.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"
@@ -644,8 +645,9 @@ void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
int BKE_brush_size_get(const Scene *scene, Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
-
- return (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
+ int size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
+
+ return (int)((float)size * U.pixelsize);
}
int BKE_brush_use_locked_size(const Scene *scene, Brush *brush)
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 54bbe4bf495..34adeb4fefb 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -40,12 +40,12 @@
#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_math.h"
-#include "BLI_pbvh.h"
#include "BLI_array.h"
#include "BLI_smallhash.h"
#include "BLI_utildefines.h"
#include "BLI_scanfill.h"
+#include "BKE_pbvh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 4641a02265a..f0043d9fa77 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -567,7 +567,9 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned
Scene *sce_iter;
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
- if (base->lay & self->lay)
+ /* Need to check for active layers, too.
+ Otherwise this check fails if the objects are not on the same layer - DG */
+ if ((base->lay & self->lay) || (base->lay & scene->lay))
add_collision_object(&objs, &numobj, &maxobj, base->object, self, 0, modifier_type);
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 97d750854f4..c3aab22fe5a 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -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], short from, short to)
+void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to)
{
float diff_mat[4][4];
float imat[4][4];
@@ -345,7 +345,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[][4]
/* ------------ General Target Matrix Tools ---------- */
/* function that sets the given matrix based on given vertex group in mesh */
-static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[][4])
+static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[4][4])
{
DerivedMesh *dm = NULL;
BMEditMesh *em = BMEdit_FromObject(ob);
@@ -441,7 +441,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
}
/* function that sets the given matrix based on given vertex group in lattice */
-static void contarget_get_lattice_mat(Object *ob, const char *substring, float mat[][4])
+static void contarget_get_lattice_mat(Object *ob, const char *substring, float mat[4][4])
{
Lattice *lt = (Lattice *)ob->data;
@@ -494,7 +494,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m
/* generic function to get the appropriate matrix for most target cases */
/* The cases where the target can be object data have not been implemented */
-static void constraint_target_to_mat4(Object *ob, const char *substring, float mat[][4], short from, short to, float headtail)
+static void constraint_target_to_mat4(Object *ob, const char *substring, float mat[4][4], short from, short to, float headtail)
{
/* Case OBJECT */
if (!strlen(substring)) {
@@ -890,7 +890,7 @@ static int basis_cross(int n, int m)
}
}
-static void vectomat(const float vec[3], const float target_up[3], short axis, short upflag, short flags, float m[][3])
+static void vectomat(const float vec[3], const float target_up[3], short axis, short upflag, short flags, float m[3][3])
{
float n[3];
float u[3]; /* vector specifying the up axis */
@@ -4610,7 +4610,7 @@ 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], float ctime)
+void get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime)
{
bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 754a4fbc0c8..1d199cdf1e2 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -36,7 +36,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_bpath.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -68,7 +67,7 @@
/* local */
static int cu_isectLL(const float v1[3], const float v2[3], const float v3[3], const float v4[3],
short cox, short coy,
- float *labda, float *mu, float vec[3]);
+ float *lambda, float *mu, float vec[3]);
void BKE_curve_unlink(Curve *cu)
{
@@ -1615,7 +1614,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, int forRende
static int cu_isectLL(const float v1[3], const float v2[3], const float v3[3], const float v4[3],
short cox, short coy,
- float *labda, float *mu, float vec[3])
+ float *lambda, float *mu, float vec[3])
{
/* return:
* -1: collinear
@@ -1629,22 +1628,22 @@ static int cu_isectLL(const float v1[3], const float v2[3], const float v3[3], c
if (deler == 0.0f)
return -1;
- *labda = (v1[coy] - v3[coy]) * (v3[cox] - v4[cox]) - (v1[cox] - v3[cox]) * (v3[coy] - v4[coy]);
- *labda = -(*labda / deler);
+ *lambda = (v1[coy] - v3[coy]) * (v3[cox] - v4[cox]) - (v1[cox] - v3[cox]) * (v3[coy] - v4[coy]);
+ *lambda = -(*lambda / deler);
deler = v3[coy] - v4[coy];
if (deler == 0) {
deler = v3[cox] - v4[cox];
- *mu = -(*labda * (v2[cox] - v1[cox]) + v1[cox] - v3[cox]) / deler;
+ *mu = -(*lambda * (v2[cox] - v1[cox]) + v1[cox] - v3[cox]) / deler;
}
else {
- *mu = -(*labda * (v2[coy] - v1[coy]) + v1[coy] - v3[coy]) / deler;
+ *mu = -(*lambda * (v2[coy] - v1[coy]) + v1[coy] - v3[coy]) / deler;
}
- vec[cox] = *labda * (v2[cox] - v1[cox]) + v1[cox];
- vec[coy] = *labda * (v2[coy] - v1[coy]) + v1[coy];
+ vec[cox] = *lambda * (v2[cox] - v1[cox]) + v1[cox];
+ vec[coy] = *lambda * (v2[coy] - v1[coy]) + v1[coy];
- if (*labda >= 0.0f && *labda <= 1.0f && *mu >= 0.0f && *mu <= 1.0f) {
- if (*labda == 0.0f || *labda == 1.0f || *mu == 0.0f || *mu == 1.0f)
+ if (*lambda >= 0.0f && *lambda <= 1.0f && *mu >= 0.0f && *mu <= 1.0f) {
+ if (*lambda == 0.0f || *lambda == 1.0f || *mu == 0.0f || *mu == 1.0f)
return 1;
return 2;
}
@@ -1654,7 +1653,7 @@ static int cu_isectLL(const float v1[3], const float v2[3], const float v3[3], c
static short bevelinside(BevList *bl1, BevList *bl2)
{
- /* is bl2 INSIDE bl1 ? with left-right method and "labda's" */
+ /* is bl2 INSIDE bl1 ? with left-right method and "lambda's" */
/* returns '1' if correct hole */
BevPoint *bevp, *prevbevp;
float min, max, vec[3], hvec1[3], hvec2[3], lab, mu;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index b2f8db0dcce..0f352dede23 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -2104,7 +2104,7 @@ int CustomData_set_layer_name(const CustomData *data, int type, int n, const cha
if (layer_index < 0) return 0;
if (!name) return 0;
- strcpy(data->layers[layer_index].name, name);
+ BLI_strncpy(data->layers[layer_index].name, name, sizeof(data->layers[layer_index].name));
return 1;
}
@@ -2854,10 +2854,11 @@ void CustomData_validate_layer_name(const CustomData *data, int type, const char
* deleted, so assign the active layer to name
*/
index = CustomData_get_active_layer_index(data, type);
- strcpy(outname, data->layers[index].name);
+ BLI_strncpy(outname, data->layers[index].name, MAX_CUSTOMDATA_LAYER_NAME);
+ }
+ else {
+ BLI_strncpy(outname, name, MAX_CUSTOMDATA_LAYER_NAME);
}
- else
- strcpy(outname, name);
}
int CustomData_verify_versions(struct CustomData *data, int index)
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 3ed759392b6..6ba140fcec1 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -2482,30 +2482,51 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s
}
-static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay)
+/* struct returned by DagSceneLayer */
+typedef struct DagSceneLayer {
+ struct DagSceneLayer *next, *prev;
+ Scene *scene;
+ unsigned int layer;
+} DagSceneLayer;
+
+/* returns visible scenes with valid DAG */
+static void dag_current_scene_layers(Main *bmain, ListBase *lb)
{
wmWindowManager *wm;
wmWindow *win;
+
+ lb->first = lb->last = NULL;
- /* only one scene supported currently, making more scenes work
- * correctly requires changes beyond just the dependency graph */
-
- *sce = NULL;
- *lay = 0;
-
+ /* if we have a windowmanager, look into windows */
if ((wm = bmain->wm.first)) {
- /* if we have a windowmanager, look into windows */
+
+ flag_listbase_ids(&bmain->scene, LIB_DOIT, 1);
+
for (win = wm->windows.first; win; win = win->next) {
- if (win->screen) {
- if (*sce == NULL) *sce = win->screen->scene;
- *lay |= BKE_screen_visible_layers(win->screen, win->screen->scene);
+ if (win->screen && win->screen->scene->theDag) {
+ Scene *scene = win->screen->scene;
+
+ if (scene->id.flag & LIB_DOIT) {
+ DagSceneLayer *dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer");
+
+ BLI_addtail(lb, dsl);
+
+ dsl->scene = scene;
+ dsl->layer = BKE_screen_visible_layers(win->screen, scene);
+
+ scene->id.flag &= ~LIB_DOIT;
+ }
}
}
}
else {
/* if not, use the first sce */
- *sce = bmain->scene.first;
- if (*sce) *lay = (*sce)->lay;
+ DagSceneLayer *dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer");
+
+ BLI_addtail(lb, dsl);
+
+ dsl->scene = bmain->scene.first;
+ dsl->layer = dsl->scene->lay;
/* XXX for background mode, we should get the scene
* from somewhere, for the -S option, but it's in
@@ -2515,29 +2536,36 @@ static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay
void DAG_ids_flush_update(Main *bmain, int time)
{
- Scene *sce;
- unsigned int lay;
-
- dag_current_scene_layers(bmain, &sce, &lay);
+ ListBase listbase;
+ DagSceneLayer *dsl;
+
+ /* get list of visible scenes and layers */
+ dag_current_scene_layers(bmain, &listbase);
- if (sce)
- DAG_scene_flush_update(bmain, sce, lay, time);
+ for (dsl = listbase.first; dsl; dsl = dsl->next)
+ DAG_scene_flush_update(bmain, dsl->scene, dsl->layer, time);
+
+ BLI_freelistN(&listbase);
}
void DAG_on_visible_update(Main *bmain, const short do_time)
{
- Scene *scene;
- Base *base;
- Object *ob;
- Group *group;
- GroupObject *go;
- DagNode *node;
- unsigned int lay, oblay;
-
- dag_current_scene_layers(bmain, &scene, &lay);
-
- if (scene && scene->theDag) {
+ ListBase listbase;
+ DagSceneLayer *dsl;
+
+ /* get list of visible scenes and layers */
+ dag_current_scene_layers(bmain, &listbase);
+
+ for (dsl = listbase.first; dsl; dsl = dsl->next) {
+ Scene *scene = dsl->scene;
Scene *sce_iter;
+ Base *base;
+ Object *ob;
+ Group *group;
+ GroupObject *go;
+ DagNode *node;
+ unsigned int lay = dsl->layer, oblay;
+
/* derivedmeshes and displists are not saved to file so need to be
* remade, tag them so they get remade in the scene update loop,
* note armature poses or object matrices are preserved and do not
@@ -2574,6 +2602,8 @@ void DAG_on_visible_update(Main *bmain, const short do_time)
DAG_scene_update_flags(bmain, scene, lay, do_time);
scene->lay_updated |= lay;
}
+
+ BLI_freelistN(&listbase);
/* hack to get objects updating on layer changes */
DAG_id_type_tag(bmain, ID_OB);
@@ -2758,14 +2788,15 @@ static void dag_id_flush_update(Scene *sce, ID *id)
void DAG_ids_flush_tagged(Main *bmain)
{
+ ListBase listbase;
+ DagSceneLayer *dsl;
ListBase *lbarray[MAX_LIBARRAY];
- Scene *sce;
- unsigned int lay;
int a, do_flush = FALSE;
+
+ /* get list of visible scenes and layers */
+ dag_current_scene_layers(bmain, &listbase);
- dag_current_scene_layers(bmain, &sce, &lay);
-
- if (!sce || !sce->theDag)
+ if (listbase.first == NULL)
return;
/* loop over all ID types */
@@ -2780,7 +2811,10 @@ void DAG_ids_flush_tagged(Main *bmain)
if (id && bmain->id_tag_update[id->name[0]]) {
for (; id; id = id->next) {
if (id->flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA)) {
- dag_id_flush_update(sce, id);
+
+ for (dsl = listbase.first; dsl; dsl = dsl->next)
+ dag_id_flush_update(dsl->scene, id);
+
do_flush = TRUE;
}
}
@@ -2788,8 +2822,12 @@ void DAG_ids_flush_tagged(Main *bmain)
}
/* flush changes to other objects */
- if (do_flush)
- DAG_scene_flush_update(bmain, sce, lay, 0);
+ if (do_flush) {
+ for (dsl = listbase.first; dsl; dsl = dsl->next)
+ DAG_scene_flush_update(bmain, dsl->scene, dsl->layer, 0);
+ }
+
+ BLI_freelistN(&listbase);
}
void DAG_ids_check_recalc(Main *bmain, Scene *scene, int time)
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index ed85e5b627b..56b9db94108 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -397,7 +397,7 @@ void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface)
}
else {
strcpy(surface->output_name, "dp_");
- strcpy(surface->output_name2, surface->output_name);
+ BLI_strncpy(surface->output_name2, surface->output_name, sizeof(surface->output_name2));
surface->flags &= ~MOD_DPAINT_ANTIALIAS;
surface->depth_clamp = 0.0f;
}
@@ -1193,7 +1193,68 @@ void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct Dyn
/* Copy data */
if (tpmd->canvas) {
+ DynamicPaintSurface *surface;
tpmd->canvas->pmd = tpmd;
+ /* free default surface */
+ if (tpmd->canvas->surfaces.first)
+ dynamicPaint_freeSurface(tpmd->canvas->surfaces.first);
+
+ /* copy existing surfaces */
+ for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
+ DynamicPaintSurface *t_surface = dynamicPaint_createNewSurface(tpmd->canvas, NULL);
+
+ /* surface settings */
+ t_surface->brush_group = surface->brush_group;
+ MEM_freeN(t_surface->effector_weights);
+ t_surface->effector_weights = MEM_dupallocN(surface->effector_weights);
+
+ BLI_strncpy(t_surface->name, surface->name, sizeof(t_surface->name));
+ t_surface->format = surface->format;
+ t_surface->type = surface->type;
+ t_surface->disp_type = surface->disp_type;
+ t_surface->image_fileformat = surface->image_fileformat;
+ t_surface->effect_ui = surface->effect_ui;
+ t_surface->preview_id = surface->preview_id;
+ t_surface->init_color_type = surface->init_color_type;
+ t_surface->flags = surface->flags;
+ t_surface->effect = surface->effect;
+
+ t_surface->image_resolution = surface->image_resolution;
+ t_surface->substeps = surface->substeps;
+ t_surface->start_frame = surface->start_frame;
+ t_surface->end_frame = surface->end_frame;
+
+ copy_v4_v4(t_surface->init_color, surface->init_color);
+ t_surface->init_texture = surface->init_texture;
+ BLI_strncpy(t_surface->init_layername, surface->init_layername, sizeof(t_surface->init_layername));
+
+ t_surface->dry_speed = surface->dry_speed;
+ t_surface->diss_speed = surface->diss_speed;
+ t_surface->color_dry_threshold = surface->color_dry_threshold;
+ t_surface->depth_clamp = surface->depth_clamp;
+ t_surface->disp_factor = surface->disp_factor;
+
+
+ t_surface->spread_speed = surface->spread_speed;
+ t_surface->color_spread_speed = surface->color_spread_speed;
+ t_surface->shrink_speed = surface->shrink_speed;
+ t_surface->drip_vel = surface->drip_vel;
+ t_surface->drip_acc = surface->drip_acc;
+
+ t_surface->influence_scale = surface->influence_scale;
+ t_surface->radius_scale = surface->radius_scale;
+
+ t_surface->wave_damping = surface->wave_damping;
+ t_surface->wave_speed = surface->wave_speed;
+ t_surface->wave_timescale = surface->wave_timescale;
+ t_surface->wave_spring = surface->wave_spring;
+
+ BLI_strncpy(t_surface->uvlayer_name, surface->uvlayer_name, sizeof(t_surface->uvlayer_name));
+ BLI_strncpy(t_surface->image_output_path, surface->image_output_path, sizeof(t_surface->image_output_path));
+ BLI_strncpy(t_surface->output_name, surface->output_name, sizeof(t_surface->output_name));
+ BLI_strncpy(t_surface->output_name2, surface->output_name2, sizeof(t_surface->output_name2));
+ }
+ dynamicPaint_resetPreview(tpmd->canvas);
}
else if (tpmd->brush) {
DynamicPaintBrushSettings *brush = pmd->brush, *t_brush = tpmd->brush;
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 321a61ce238..bb8df834d0f 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -39,8 +39,8 @@
#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_math.h"
-#include "BLI_pbvh.h"
+#include "BKE_pbvh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
@@ -71,24 +71,24 @@ extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate)
{
- BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__);
+ BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__);
- tm->bm = bm;
+ em->bm = bm;
if (do_tessellate) {
- BMEdit_RecalcTessellation(tm);
+ BMEdit_RecalcTessellation(em);
}
- return tm;
+ return em;
}
-BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
+BMEditMesh *BMEdit_Copy(BMEditMesh *em)
{
- BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), __func__);
- *tm2 = *tm;
+ BMEditMesh *em_copy = MEM_callocN(sizeof(BMEditMesh), __func__);
+ *em_copy = *em;
- tm2->derivedCage = tm2->derivedFinal = NULL;
+ em_copy->derivedCage = em_copy->derivedFinal = NULL;
- tm2->bm = BM_mesh_copy(tm->bm);
+ em_copy->bm = BM_mesh_copy(em->bm);
/* The tessellation is NOT calculated on the copy here,
* because currently all the callers of this function use
@@ -97,22 +97,22 @@ BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
* reasons, in that case it makes more sense to do the
* tessellation only when/if that copy ends up getting
* used.*/
- tm2->looptris = NULL;
+ em_copy->looptris = NULL;
- tm2->vert_index = NULL;
- tm2->edge_index = NULL;
- tm2->face_index = NULL;
+ em_copy->vert_index = NULL;
+ em_copy->edge_index = NULL;
+ em_copy->face_index = NULL;
- return tm2;
+ return em_copy;
}
-static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
+static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
{
/* use this to avoid locking pthread for _every_ polygon
* and calling the fill function */
#define USE_TESSFACE_SPEEDUP
- BMesh *bm = tm->bm;
+ BMesh *bm = em->bm;
BMLoop *(*looptris)[3] = NULL;
BLI_array_declare(looptris);
BMIter iter, liter;
@@ -125,26 +125,26 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
#if 0
/* note, we could be clever and re-use this array but would need to ensure
* its realloced at some point, for now just free it */
- if (tm->looptris) MEM_freeN(tm->looptris);
+ if (em->looptris) MEM_freeN(em->looptris);
- /* Use tm->tottri when set, this means no reallocs while transforming,
+ /* Use em->tottri when set, this means no reallocs while transforming,
* (unless scanfill fails), otherwise... */
/* 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(looptris, (tm->tottri && tm->tottri < bm->totface * 3) ? tm->tottri : bm->totface);
+ BLI_array_reserve(looptris, (em->tottri && em->tottri < bm->totface * 3) ? em->tottri : bm->totface);
#else
/* this means no reallocs for quad dominant models, for */
- if ( (tm->looptris != NULL) &&
- (tm->tottri != 0) &&
+ 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 */
- (tm->tottri <= bm->totface * 3))
+ (em->tottri <= bm->totface * 3))
{
- looptris = tm->looptris;
+ looptris = em->looptris;
}
else {
- if (tm->looptris) MEM_freeN(tm->looptris);
+ if (em->looptris) MEM_freeN(em->looptris);
BLI_array_reserve(looptris, bm->totface);
}
@@ -237,8 +237,8 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
}
}
- tm->tottri = i;
- tm->looptris = looptris;
+ em->tottri = i;
+ em->looptris = looptris;
#undef USE_TESSFACE_SPEEDUP
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index a7d0152a799..0c83bb8d39a 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -183,7 +183,7 @@ bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, int setactive)
gpl->thickness = 3;
/* auto-name */
- strcpy(gpl->info, name);
+ BLI_strncpy(gpl->info, name, sizeof(gpl->info));
BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
/* make this one the active one */
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index f09f128e874..7f0475cf155 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -68,7 +68,6 @@
#include "BLI_blenlib.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "BKE_bmfont.h"
#include "BKE_colortools.h"
@@ -1400,7 +1399,9 @@ static void timecode_simple_string(char *text, size_t text_size, const int cfra,
}
}
-/* could allow access externally - 512 is for long names, 64 is for id names */
+#define STAMP_NAME_SIZE ((MAX_ID_NAME - 2) + 16)
+/* could allow access externally - 512 is for long names,
+ * STAMP_NAME_SIZE is for id names, allowing them some room for description */
typedef struct StampData {
char file[512];
char note[512];
@@ -1408,12 +1409,13 @@ typedef struct StampData {
char marker[512];
char time[512];
char frame[512];
- char camera[64];
- char cameralens[64];
- char scene[64];
- char strip[64];
- char rendertime[64];
+ char camera[STAMP_NAME_SIZE];
+ char cameralens[STAMP_NAME_SIZE];
+ char scene[STAMP_NAME_SIZE];
+ char strip[STAMP_NAME_SIZE];
+ char rendertime[STAMP_NAME_SIZE];
} StampData;
+#undef STAMP_NAME_SIZE
static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int do_prefix)
{
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 782d796b8a7..ad95f09826a 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -1078,7 +1078,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int
if (key->slurph && key->type != KEY_RELATIVE) {
const float ctime_scaled = key->ctime / 100.0f;
float delta = (float)key->slurph / tot;
- float cfra = (float)scene->r.cfra;
+ float cfra = (float)scene->r.cfra + scene->r.subframe;
int step, a;
if (tot > 100 && slurph_opt) {
@@ -1176,7 +1176,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const in
if (key->slurph && key->type != KEY_RELATIVE) {
const float ctime_scaled = key->ctime / 100.0f;
float delta = (float)key->slurph / tot;
- float cfra = (float)scene->r.cfra;
+ float cfra = (float)scene->r.cfra + scene->r.subframe;
Nurb *nu;
int i = 0, remain = 0;
int step, a;
@@ -1258,7 +1258,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int
if (key->slurph && key->type != KEY_RELATIVE) {
const float ctime_scaled = key->ctime / 100.0f;
float delta = (float)key->slurph / tot;
- float cfra = (float)scene->r.cfra;
+ float cfra = (float)scene->r.cfra + scene->r.subframe;
int a;
for (a = 0; a < tot; a++, cfra += delta) {
@@ -1373,7 +1373,7 @@ float *do_ob_key(Scene *scene, Object *ob)
}
else {
/* do shapekey local drivers */
- float ctime = (float)scene->r.cfra; // XXX this needs to be checked
+ float ctime = (float)scene->r.cfra + scene->r.subframe;
BKE_animsys_evaluate_animdata(scene, &key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index a15ca7cb5ce..d98188d8a6f 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -37,7 +37,6 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -753,7 +752,7 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target,
/* orco is original not-animated or deformed reference point */
/* result written in vec and mat */
void curve_deform_vector(Scene *scene, Object *cuOb, Object *target,
- float orco[3], float vec[3], float mat[][3], int no_rot_axis)
+ float orco[3], float vec[3], float mat[3][3], int no_rot_axis)
{
CurveDeform cd;
float quat[4];
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index db96567a4da..d21a12b9e6a 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -71,7 +71,7 @@
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
+#include "BKE_bpath.h"
#include "BKE_animsys.h"
#include "BKE_camera.h"
@@ -137,9 +137,9 @@ void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id)
{
char *bpath_user_data[2] = {bmain->name, lib->filepath};
- BLI_bpath_traverse_id(bmain, id,
- BLI_bpath_relocate_visitor,
- BLI_BPATH_TRAVERSE_SKIP_MULTIFILE,
+ BKE_bpath_traverse_id(bmain, id,
+ BKE_bpath_relocate_visitor,
+ BKE_BPATH_TRAVERSE_SKIP_MULTIFILE,
bpath_user_data);
}
@@ -153,6 +153,14 @@ void id_lib_extern(ID *id)
}
}
+/* ensure we have a real user */
+void id_us_ensure_real(ID *id)
+{
+ if (ID_REAL_USERS(id) <= 0) {
+ id->us = MAX2(id->us, 0) + 1;
+ }
+}
+
void id_us_plus(ID *id)
{
if (id) {
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 445ea2d4b3b..3bfd4f4f760 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -52,7 +52,6 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "BLI_string.h"
#include "BKE_animsys.h"
@@ -1857,7 +1856,7 @@ static void convert_tfacematerial(Main *main, Material *ma)
mat_new = BKE_material_copy(ma);
if (mat_new) {
/* rename the material*/
- strcpy(mat_new->id.name, idname);
+ BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name));
id_us_min((ID *)mat_new);
mat_nr = mesh_addmaterial(me, mat_new);
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 805e77cf84f..5c882fd97d6 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -50,8 +50,6 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
-
#include "BKE_global.h"
#include "BKE_main.h"
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 036f8f5e673..55cf2743bfa 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -46,7 +46,6 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BLI_scanfill.h"
@@ -3009,9 +3008,9 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart,
else {
int i;
MLoop *l_iter = loopstart;
- float area, polynorm_local[3], (*vertexcos)[3];
+ float area, polynorm_local[3];
+ float (*vertexcos)[3] = BLI_array_alloca(vertexcos, mpoly->totloop);
const float *no = polynormal ? polynormal : polynorm_local;
- BLI_array_fixedstack_declare(vertexcos, BM_DEFAULT_NGON_STACK_SIZE, mpoly->totloop, __func__);
/* pack vertex cos into an array for area_poly_v3 */
for (i = 0; i < mpoly->totloop; i++, l_iter++) {
@@ -3026,8 +3025,6 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart,
/* finally calculate the area */
area = area_poly_v3(mpoly->totloop, vertexcos, no);
- BLI_array_fixedstack_free(vertexcos);
-
return area;
}
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 25b70ce1793..2aeda614f07 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -621,16 +621,6 @@ int modifiers_isPreview(Object *ob)
return FALSE;
}
-int modifiers_indexInObject(Object *ob, ModifierData *md_seek)
-{
- int i = 0;
- ModifierData *md;
-
- for (md = ob->modifiers.first; (md && md_seek != md); md = md->next, i++) ;
- if (!md) return -1; /* modifier isn't in the object */
- return i;
-}
-
void modifier_freeTemporaryData(ModifierData *md)
{
if (md->type == eModifierType_Armature) {
diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c
index 381e4350391..7df7561a1a1 100644
--- a/source/blender/blenkernel/intern/modifiers_bmesh.c
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -40,7 +40,11 @@
#include "BKE_bmesh.h"
#include "BKE_tessmesh.h"
-/* main function for copying DerivedMesh data into BMesh */
+/**
+ * The main function for copying DerivedMesh data into BMesh.
+ *
+ * \note The mesh may already have geometry. see 'is_init'
+ */
void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
{
MVert *mv, *mvert;
@@ -56,6 +60,14 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
BLI_array_declare(edges);
int i, j, k, totvert, totedge /* , totface */ /* UNUSED */ ;
int is_init = (bm->totvert == 0) && (bm->totedge == 0) && (bm->totface == 0);
+ char has_orig_hflag = 0;
+
+ if (is_init == FALSE) {
+ /* check if we have an origflag */
+ has_orig_hflag |= CustomData_has_layer(&bm->vdata, CD_ORIGINDEX) ? BM_VERT : 0;
+ has_orig_hflag |= CustomData_has_layer(&bm->edata, CD_ORIGINDEX) ? BM_EDGE : 0;
+ has_orig_hflag |= CustomData_has_layer(&bm->pdata, CD_ORIGINDEX) ? BM_FACE : 0;
+ }
/*merge custom data layout*/
CustomData_bmesh_merge(&dm->vertData, &bm->vdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_VERT);
@@ -85,10 +97,15 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
BM_elem_index_set(v, i); /* set_inline */
CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data);
+ vtable[i] = v;
/* add bevel weight */
BM_elem_float_data_set(&bm->vdata, v, CD_BWEIGHT, (float)mv->bweight / 255.0f);
- vtable[i] = v;
+
+ if (UNLIKELY(has_orig_hflag & BM_VERT)) {
+ int *orig_index = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_ORIGINDEX);
+ *orig_index = ORIGINDEX_NONE;
+ }
}
MEM_freeN(mvert);
if (is_init) bm->elem_index_dirty &= ~BM_VERT;
@@ -109,6 +126,11 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (float)me->crease / 255.0f);
/* add bevel weight */
BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (float)me->bweight / 255.0f);
+
+ if (UNLIKELY(has_orig_hflag & BM_EDGE)) {
+ int *orig_index = CustomData_bmesh_get(&bm->edata, e->head.data, CD_ORIGINDEX);
+ *orig_index = ORIGINDEX_NONE;
+ }
}
MEM_freeN(medge);
if (is_init) bm->elem_index_dirty &= ~BM_EDGE;
@@ -158,6 +180,11 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
else {
BM_face_normal_update(f);
}
+
+ if (UNLIKELY(has_orig_hflag & BM_FACE)) {
+ int *orig_index = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_ORIGINDEX);
+ *orig_index = ORIGINDEX_NONE;
+ }
}
if (is_init) bm->elem_index_dirty &= ~BM_FACE;
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index c737dccc5d2..06d7cf55d49 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -43,9 +43,9 @@
#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_pbvh.h"
#include "BLI_utildefines.h"
+#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 9ea1c3e8c74..bf4e32ef122 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -57,14 +57,14 @@
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
#include "DNA_object_types.h"
+#include "DNA_property_types.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_math.h"
-#include "BLI_pbvh.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
+#include "BKE_pbvh.h"
#include "BKE_main.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
@@ -739,6 +739,50 @@ void BKE_object_unlink(Object *ob)
}
}
+/* actual check for internal data, not context or flags */
+int BKE_object_is_in_editmode(Object *ob)
+{
+ if (ob->data == NULL)
+ return 0;
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ if (me->edit_btmesh)
+ return 1;
+ }
+ else if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+
+ if (arm->edbo)
+ return 1;
+ }
+ else if (ob->type == OB_FONT) {
+ Curve *cu = ob->data;
+
+ if (cu->editfont)
+ return 1;
+ }
+ else if (ob->type == OB_MBALL) {
+ MetaBall *mb = ob->data;
+
+ if (mb->editelems)
+ return 1;
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+
+ if (lt->editlatt)
+ return 1;
+ }
+ else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
+ Curve *cu = ob->data;
+
+ if (cu->editnurb)
+ return 1;
+ }
+ return 0;
+}
+
int BKE_object_exists_check(Object *obtest)
{
Object *ob;
@@ -1498,14 +1542,14 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
/* *************** CALC ****************** */
-void BKE_object_scale_to_mat3(Object *ob, float mat[][3])
+void BKE_object_scale_to_mat3(Object *ob, float mat[3][3])
{
float vec[3];
mul_v3_v3v3(vec, ob->size, ob->dscale);
size_to_mat3(mat, vec);
}
-void BKE_object_rot_to_mat3(Object *ob, float mat[][3])
+void BKE_object_rot_to_mat3(Object *ob, float mat[3][3], short use_drot)
{
float rmat[3][3], dmat[3][3];
@@ -1536,10 +1580,13 @@ void BKE_object_rot_to_mat3(Object *ob, float mat[][3])
}
/* combine these rotations */
- mul_m3_m3m3(mat, dmat, rmat);
+ if (use_drot)
+ mul_m3_m3m3(mat, dmat, rmat);
+ else
+ copy_m3_m3(mat, rmat);
}
-void BKE_object_mat3_to_rot(Object *ob, float mat[][3], short use_compat)
+void BKE_object_mat3_to_rot(Object *ob, float mat[3][3], short use_compat)
{
switch (ob->rotmode) {
case ROT_MODE_QUAT:
@@ -1642,7 +1689,7 @@ void BKE_object_tfm_protected_restore(Object *ob,
}
/* see BKE_pchan_apply_mat4() for the equivalent 'pchan' function */
-void BKE_object_apply_mat4(Object *ob, float mat[][4], const short use_compat, const short use_parent)
+void BKE_object_apply_mat4(Object *ob, float mat[4][4], const short use_compat, const short use_parent)
{
float rot[3][3];
@@ -1671,7 +1718,7 @@ void BKE_object_apply_mat4(Object *ob, float mat[][4], const short use_compat, c
/* BKE_object_mat3_to_rot handles delta rotations */
}
-void BKE_object_to_mat3(Object *ob, float mat[][3]) /* no parent */
+void BKE_object_to_mat3(Object *ob, float mat[3][3]) /* no parent */
{
float smat[3][3];
float rmat[3][3];
@@ -1681,11 +1728,11 @@ void BKE_object_to_mat3(Object *ob, float mat[][3]) /* no parent */
BKE_object_scale_to_mat3(ob, smat);
/* rot */
- BKE_object_rot_to_mat3(ob, rmat);
+ BKE_object_rot_to_mat3(ob, rmat, TRUE);
mul_m3_m3m3(mat, rmat, smat);
}
-void BKE_object_to_mat4(Object *ob, float mat[][4])
+void BKE_object_to_mat4(Object *ob, float mat[4][4])
{
float tmat[3][3];
@@ -1699,7 +1746,7 @@ void BKE_object_to_mat4(Object *ob, float mat[][4])
/* extern */
int enable_cu_speed = 1;
-static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
+static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
{
Curve *cu;
float vec[4], dir[3], quat[4], radius, ctime;
@@ -1783,7 +1830,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
}
}
-static void ob_parbone(Object *ob, Object *par, float mat[][4])
+static void ob_parbone(Object *ob, Object *par, float mat[4][4])
{
bPoseChannel *pchan;
float vec[3];
@@ -1913,7 +1960,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
}
}
-static void ob_parvert3(Object *ob, Object *par, float mat[][4])
+static void ob_parvert3(Object *ob, Object *par, float mat[4][4])
{
float cmat[3][3], v1[3], v2[3], v3[3], q[4];
@@ -1941,7 +1988,7 @@ static void ob_parvert3(Object *ob, Object *par, float mat[][4])
}
}
-static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul)
+static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[4][4], float slowmat[4][4], int simul)
{
float totmat[4][4];
float tmat[4][4];
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 5f5a713064d..b2851962b49 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -55,7 +55,6 @@
#include "BLI_rand.h"
#include "BLI_threads.h"
#include "BLI_linklist.h"
-#include "BLI_bpath.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
@@ -680,7 +679,7 @@ static float psys_render_projected_area(ParticleSystem *psys, const float center
return area;
}
-void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset)
+void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset)
{
ParticleRenderData *data;
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
@@ -1919,7 +1918,7 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in
/* Path Cache */
/************************************************/
-static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, float flat, short type, short axis, float obmat[][4], int smooth_start)
+static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, float flat, short type, short axis, float obmat[4][4], int smooth_start)
{
float kink[3] = {1.f, 0.f, 0.f}, par_vec[3], q1[4] = {1.f, 0.f, 0.f, 0.f};
float t, dt = 1.f, result[3];
@@ -3351,7 +3350,7 @@ static void key_from_object(Object *ob, ParticleKey *key)
}
#endif
-static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat[][4])
+static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat[4][4])
{
float det, w1, w2, d1[2], d2[2];
@@ -3392,7 +3391,7 @@ static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat
cross_v3_v3v3(mat[0], mat[1], mat[2]);
}
-static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float mat[][4], int orco)
+static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float mat[4][4], int orco)
{
float v[3][3];
MFace *mface;
@@ -3425,7 +3424,7 @@ static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float m
triatomat(v[0], v[1], v[2], (osface) ? osface->uv : NULL, mat);
}
-void psys_mat_hair_to_object(Object *UNUSED(ob), DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4])
+void psys_mat_hair_to_object(Object *UNUSED(ob), DerivedMesh *dm, short from, ParticleData *pa, float hairmat[4][4])
{
float vec[3];
@@ -3440,7 +3439,7 @@ void psys_mat_hair_to_object(Object *UNUSED(ob), DerivedMesh *dm, short from, Pa
copy_v3_v3(hairmat[3], vec);
}
-void psys_mat_hair_to_orco(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4])
+void psys_mat_hair_to_orco(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[4][4])
{
float vec[3], orco[3];
@@ -3462,7 +3461,7 @@ void psys_vec_rot_to_face(DerivedMesh *dm, ParticleData *pa, float vec[3])
mul_mat3_m4_v3(mat, vec);
}
-void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4])
+void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[4][4])
{
float facemat[4][4];
@@ -4502,7 +4501,7 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part,
psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, 0, 0, 0, orco, 0);
}
-void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale)
+void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[4][4], float *scale)
{
Object *ob = sim->ob;
ParticleSystem *psys = sim->psys;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 90889d7c09e..090082b333d 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -23,7 +23,8 @@
* Contributor(s): Raul Fernandez Hernandez (Farsthary), Stephen Swhitehorn.
*
* Adaptive time step
- * Copyright 2011 AutoCRC
+ * Classical SPH
+ * Copyright 2011-2012 AutoCRC
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -1889,7 +1890,6 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
bpa->data.acc[0]=bpa->data.acc[1]=bpa->data.acc[2]=0.0f;
}
-
if (part->type == PART_HAIR) {
pa->lifetime = 100.0f;
}
@@ -2390,33 +2390,36 @@ typedef struct SPHRangeData {
SPHNeighbor neighbors[SPH_NEIGHBORS];
int tot_neighbors;
- float density, near_density;
- float h;
+ float* data;
ParticleSystem *npsys;
ParticleData *pa;
+ float h;
float massfac;
int use_size;
} SPHRangeData;
-typedef struct SPHData {
- ParticleSystem *psys[10];
- ParticleData *pa;
- float mass;
- EdgeHash *eh;
- float *gravity;
- /* Average distance to neighbors (other particles in the support domain),
- * for calculating the Courant number (adaptive time step). */
- int pass;
- float element_size;
- float flow[3];
-
- /* Integrator callbacks. This allows different SPH implementations. */
- void (*force_cb) (void *sphdata_v, ParticleKey *state, float *force, float *impulse);
- void (*density_cb) (void *rangedata_v, int index, float squared_dist);
-} SPHData;
+static void sph_evaluate_func(BVHTree *tree, ParticleSystem **psys, float co[3], SPHRangeData *pfr, float interaction_radius, BVHTree_RangeQuery callback)
+{
+ int i;
+
+ pfr->tot_neighbors = 0;
+
+ for (i=0; i < 10 && psys[i]; i++) {
+ pfr->npsys = psys[i];
+ pfr->massfac = psys[i]->part->mass;
+ pfr->use_size = psys[i]->part->flag & PART_SIZEMASS;
+ if (tree) {
+ BLI_bvhtree_range_query(tree, co, interaction_radius, callback, pfr);
+ break;
+ }
+ else {
+ BLI_bvhtree_range_query(psys[i]->bvhtree, co, interaction_radius, callback, pfr);
+ }
+ }
+}
static void sph_density_accum_cb(void *userdata, int index, float squared_dist)
{
SPHRangeData *pfr = (SPHRangeData *)userdata;
@@ -2446,8 +2449,8 @@ static void sph_density_accum_cb(void *userdata, int index, float squared_dist)
if (pfr->use_size)
q *= npa->size;
- pfr->density += q*q;
- pfr->near_density += q*q*q;
+ pfr->data[0] += q*q;
+ pfr->data[1] += q*q*q;
}
/*
@@ -2500,8 +2503,10 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa
float inv_mass = 1.0f/mass;
float spring_constant = fluid->spring_k;
-
- float h = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.f*pa->size : 1.f); /* 4.0 seems to be a pretty good value */
+
+ /* 4.0 seems to be a pretty good value */
+ float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f);
+ float h = interaction_radius * sphdata->hfac;
float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.f); /* 4.77 is an experimentally determined density factor */
float rest_length = fluid->rest_length * (fluid->flag & SPH_FAC_REST_LENGTH ? 2.588f * pa->size : 1.f);
@@ -2512,24 +2517,23 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa
float vec[3];
float vel[3];
float co[3];
+ float data[2];
+ float density, near_density;
int i, spring_index, index = pa - psys[0]->particles;
- pfr.tot_neighbors = 0;
- pfr.density = pfr.near_density = 0.f;
+ data[0] = data[1] = 0;
+ pfr.data = data;
pfr.h = h;
pfr.pa = pa;
- for (i=0; i<10 && psys[i]; i++) {
- pfr.npsys = psys[i];
- pfr.massfac = psys[i]->part->mass*inv_mass;
- pfr.use_size = psys[i]->part->flag & PART_SIZEMASS;
+ sph_evaluate_func( NULL, psys, state->co, &pfr, interaction_radius, sph_density_accum_cb);
- BLI_bvhtree_range_query(psys[i]->bvhtree, state->co, h, sphdata->density_cb, &pfr);
- }
+ density = data[0];
+ near_density = data[1];
- pressure = stiffness * (pfr.density - rest_density);
- near_pressure = stiffness_near_fac * pfr.near_density;
+ pressure = stiffness * (density - rest_density);
+ near_pressure = stiffness_near_fac * near_density;
pfn = pfr.neighbors;
for (i=0; i<pfr.tot_neighbors; i++, pfn++) {
@@ -2593,14 +2597,207 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa
/* Artificial buoyancy force in negative gravity direction */
if (fluid->buoyancy > 0.f && gravity)
- madd_v3_v3fl(force, gravity, fluid->buoyancy * (pfr.density-rest_density));
+ madd_v3_v3fl(force, gravity, fluid->buoyancy * (density-rest_density));
if (sphdata->pass == 0 && psys[0]->part->time_flag & PART_TIME_AUTOSF)
sph_particle_courant(sphdata, &pfr);
sphdata->pass++;
}
-static void sph_solver_init(ParticleSimulationData *sim, SPHData *sphdata)
+/* powf is really slow for raising to integer powers. */
+MINLINE float pow2(float x)
+{
+ return x * x;
+}
+MINLINE float pow3(float x)
+{
+ return pow2(x) * x;
+}
+MINLINE float pow4(float x)
+{
+ return pow2(pow2(x));
+}
+MINLINE float pow7(float x)
+{
+ return pow2(pow3(x)) * x;
+}
+
+static void sphclassical_density_accum_cb(void *userdata, int index, float UNUSED(squared_dist))
+{
+ SPHRangeData *pfr = (SPHRangeData *)userdata;
+ ParticleData *npa = pfr->npsys->particles + index;
+ float q;
+ float qfac = 21.0f / (256.f * (float)M_PI);
+ float rij, rij_h;
+ float vec[3];
+
+ /* Exclude particles that are more than 2h away. Can't use squared_dist here
+ * because it is not accurate enough. Use current state, i.e. the output of
+ * basic_integrate() - z0r */
+ sub_v3_v3v3(vec, npa->state.co, pfr->pa->state.co);
+ rij = len_v3(vec);
+ rij_h = rij / pfr->h;
+ if (rij_h > 2.0f)
+ return;
+
+ /* Smoothing factor. Utilise the Wendland kernel. gnuplot:
+ * q1(x) = (2.0 - x)**4 * ( 1.0 + 2.0 * x)
+ * plot [0:2] q1(x) */
+ q = qfac / pow3(pfr->h) * pow4(2.0f - rij_h) * ( 1.0f + 2.0f * rij_h);
+ q *= pfr->massfac;
+
+ if (pfr->use_size)
+ q *= pfr->pa->size;
+
+ pfr->data[0] += q;
+ pfr->data[1] += q / npa->sphdensity;
+}
+
+static void sphclassical_neighbour_accum_cb(void *userdata, int index, float UNUSED(squared_dist))
+{
+ SPHRangeData *pfr = (SPHRangeData *)userdata;
+ ParticleData *npa = pfr->npsys->particles + index;
+ float rij, rij_h;
+ float vec[3];
+
+ if (pfr->tot_neighbors >= SPH_NEIGHBORS)
+ return;
+
+ /* Exclude particles that are more than 2h away. Can't use squared_dist here
+ * because it is not accurate enough. Use current state, i.e. the output of
+ * basic_integrate() - z0r */
+ sub_v3_v3v3(vec, npa->state.co, pfr->pa->state.co);
+ rij = len_v3(vec);
+ rij_h = rij / pfr->h;
+ if (rij_h > 2.0f)
+ return;
+
+ pfr->neighbors[pfr->tot_neighbors].index = index;
+ pfr->neighbors[pfr->tot_neighbors].psys = pfr->npsys;
+ pfr->tot_neighbors++;
+}
+static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *force, float *UNUSED(impulse))
+{
+ SPHData *sphdata = (SPHData *)sphdata_v;
+ ParticleSystem **psys = sphdata->psys;
+ ParticleData *pa = sphdata->pa;
+ SPHFluidSettings *fluid = psys[0]->part->fluid;
+ SPHRangeData pfr;
+ SPHNeighbor *pfn;
+ float *gravity = sphdata->gravity;
+
+ float dq, u, rij, dv[3];
+ float pressure, npressure;
+
+ float visc = fluid->viscosity_omega;
+
+ float interaction_radius;
+ float h, hinv;
+ /* 4.77 is an experimentally determined density factor */
+ float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.0f);
+
+ float stiffness = fluid->stiffness_k;
+
+ ParticleData *npa;
+ float vec[3];
+ float co[3];
+ float pressureTerm;
+
+ int i;
+
+ float qfac2 = 42.0f / (256.0f * (float)M_PI);
+ float rij_h;
+
+ /* 4.0 here is to be consistent with previous formulation/interface */
+ interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f);
+ h = interaction_radius * sphdata->hfac;
+ hinv = 1.0f / h;
+
+ pfr.h = h;
+ pfr.pa = pa;
+
+ sph_evaluate_func(NULL, psys, state->co, &pfr, interaction_radius, sphclassical_neighbour_accum_cb);
+ pressure = stiffness * (pow7(pa->sphdensity / rest_density) - 1.0f);
+
+ /* multiply by mass so that we return a force, not accel */
+ qfac2 *= sphdata->mass / pow3(pfr.h);
+
+ pfn = pfr.neighbors;
+ for (i = 0; i < pfr.tot_neighbors; i++, pfn++) {
+ npa = pfn->psys->particles + pfn->index;
+ if (npa == pa) {
+ /* we do not contribute to ourselves */
+ continue;
+ }
+
+ /* Find vector to neighbour. Exclude particles that are more than 2h
+ * away. Can't use current state here because it may have changed on
+ * another thread - so do own mini integration. Unlike basic_integrate,
+ * SPH integration depends on neighbouring particles. - z0r */
+ madd_v3_v3v3fl(co, npa->prev_state.co, npa->prev_state.vel, state->time);
+ sub_v3_v3v3(vec, co, state->co);
+ rij = normalize_v3(vec);
+ rij_h = rij / pfr.h;
+ if (rij_h > 2.0f)
+ continue;
+
+ npressure = stiffness * (pow7(npa->sphdensity / rest_density) - 1.0f);
+
+ /* First derivative of smoothing factor. Utilise the Wendland kernel.
+ * gnuplot:
+ * q2(x) = 2.0 * (2.0 - x)**4 - 4.0 * (2.0 - x)**3 * (1.0 + 2.0 * x)
+ * plot [0:2] q2(x)
+ * Particles > 2h away are excluded above. */
+ dq = qfac2 * (2.0f * pow4(2.0f - rij_h) - 4.0f * pow3(2.0f - rij_h) * (1.0f + 2.0f * rij_h) );
+
+ if (pfn->psys->part->flag & PART_SIZEMASS)
+ dq *= npa->size;
+
+ pressureTerm = pressure / pow2(pa->sphdensity) + npressure / pow2(npa->sphdensity);
+
+ /* Note that 'minus' is removed, because vec = vecBA, not vecAB.
+ * This applies to the viscosity calculation below, too. */
+ madd_v3_v3fl(force, vec, pressureTerm * dq);
+
+ /* Viscosity */
+ if (visc > 0.0f) {
+ sub_v3_v3v3(dv, npa->prev_state.vel, pa->prev_state.vel);
+ u = dot_v3v3(vec, dv);
+ /* Apply parameters */
+ u *= -dq * hinv * visc / (0.5f * npa->sphdensity + 0.5f * pa->sphdensity);
+ madd_v3_v3fl(force, vec, u);
+ }
+ }
+
+ /* Artificial buoyancy force in negative gravity direction */
+ if (fluid->buoyancy > 0.f && gravity)
+ madd_v3_v3fl(force, gravity, fluid->buoyancy * (pa->sphdensity - rest_density));
+
+ if (sphdata->pass == 0 && psys[0]->part->time_flag & PART_TIME_AUTOSF)
+ sph_particle_courant(sphdata, &pfr);
+ sphdata->pass++;
+}
+
+static void sphclassical_calc_dens(ParticleData *pa, float UNUSED(dfra), SPHData *sphdata)
+{
+ ParticleSystem **psys = sphdata->psys;
+ SPHFluidSettings *fluid = psys[0]->part->fluid;
+ /* 4.0 seems to be a pretty good value */
+ float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * psys[0]->part->size : 1.0f);
+ SPHRangeData pfr;
+ float data[2];
+
+ data[0] = 0;
+ data[1] = 0;
+ pfr.data = data;
+ pfr.h = interaction_radius * sphdata->hfac;
+ pfr.pa = pa;
+
+ sph_evaluate_func( NULL, psys, pa->state.co, &pfr, interaction_radius, sphclassical_density_accum_cb);
+ pa->sphdensity = MIN2(MAX2(data[0], fluid->rest_density * 0.9f), fluid->rest_density * 1.1f);
+}
+
+void psys_sph_init(ParticleSimulationData *sim, SPHData *sphdata)
{
ParticleTarget *pt;
int i;
@@ -2621,17 +2818,46 @@ static void sph_solver_init(ParticleSimulationData *sim, SPHData *sphdata)
sphdata->pa = NULL;
sphdata->mass = 1.0f;
- sphdata->force_cb = sph_force_cb;
- sphdata->density_cb = sph_density_accum_cb;
+ if (sim->psys->part->fluid->solver == SPH_SOLVER_DDR) {
+ sphdata->force_cb = sph_force_cb;
+ sphdata->density_cb = sph_density_accum_cb;
+ sphdata->hfac = 1.0f;
+ }
+ else {
+ /* SPH_SOLVER_CLASSICAL */
+ sphdata->force_cb = sphclassical_force_cb;
+ sphdata->density_cb = sphclassical_density_accum_cb;
+ sphdata->hfac = 0.5f;
+ }
+
}
-static void sph_solver_finalise(SPHData *sphdata)
+void psys_sph_finalise(SPHData *sphdata)
{
if (sphdata->eh) {
BLI_edgehash_free(sphdata->eh, NULL);
sphdata->eh = NULL;
}
}
+/* Sample the density field at a point in space. */
+void psys_sph_density(BVHTree *tree, SPHData *sphdata, float co[3], float vars[2])
+{
+ ParticleSystem **psys = sphdata->psys;
+ SPHFluidSettings *fluid = psys[0]->part->fluid;
+ /* 4.0 seems to be a pretty good value */
+ float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * psys[0]->part->size : 1.0f);
+ SPHRangeData pfr;
+ float density[2];
+
+ density[0] = density[1] = 0.0f;
+ pfr.data = density;
+ pfr.h = interaction_radius*sphdata->hfac;
+
+ sph_evaluate_func(tree, psys, co, &pfr, interaction_radius, sphdata->density_cb);
+
+ vars[0] = pfr.data[0];
+ vars[1] = pfr.data[1];
+}
static void sph_integrate(ParticleSimulationData *sim, ParticleData *pa, float dfra, SPHData *sphdata)
{
@@ -3781,18 +4007,19 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
/* Code for an adaptive time step based on the Courant-Friedrichs-Lewy
* condition. */
-#define MIN_TIMESTEP 1.0f / 101.0f
+static const float MIN_TIMESTEP = 1.0f / 101.0f;
/* Tolerance of 1.5 means the last subframe neither favors growing nor
* shrinking (e.g if it were 1.3, the last subframe would tend to be too
* small). */
-#define TIMESTEP_EXPANSION_TOLERANCE 1.5f
+static const float TIMESTEP_EXPANSION_FACTOR = 0.1f;
+static const float TIMESTEP_EXPANSION_TOLERANCE = 1.5f;
/* Calculate the speed of the particle relative to the local scale of the
* simulation. This should be called once per particle during a simulation
* step, after the velocity has been updated. element_size defines the scale of
* the simulation, and is typically the distance to neighboring particles. */
static void update_courant_num(ParticleSimulationData *sim, ParticleData *pa,
- float dtime, SPHData *sphdata)
+ float dtime, SPHData *sphdata)
{
float relative_vel[3];
float speed;
@@ -3802,14 +4029,31 @@ static void update_courant_num(ParticleSimulationData *sim, ParticleData *pa,
if (sim->courant_num < speed * dtime / sphdata->element_size)
sim->courant_num = speed * dtime / sphdata->element_size;
}
+static float get_base_time_step(ParticleSettings *part)
+{
+ return 1.0f / (float) (part->subframes + 1);
+}
/* Update time step size to suit current conditions. */
static float update_timestep(ParticleSystem *psys, ParticleSimulationData *sim, float t_frac)
{
+ float dt_target;
if (sim->courant_num == 0.0f)
- psys->dt_frac = 1.0f;
+ dt_target = 1.0f;
+ else
+ dt_target = psys->dt_frac * (psys->part->courant_target / sim->courant_num);
+
+ /* Make sure the time step is reasonable. For some reason, the CLAMP macro
+ * doesn't work here. The time step becomes too large. - z0r */
+ if (dt_target < MIN_TIMESTEP)
+ dt_target = MIN_TIMESTEP;
+ else if (dt_target > get_base_time_step(psys->part))
+ dt_target = get_base_time_step(psys->part);
+
+ /* Decrease time step instantly, but increase slowly. */
+ if (dt_target > psys->dt_frac)
+ psys->dt_frac = interpf(dt_target, psys->dt_frac, TIMESTEP_EXPANSION_FACTOR);
else
- psys->dt_frac *= (psys->part->courant_target / sim->courant_num);
- CLAMP(psys->dt_frac, MIN_TIMESTEP, 1.0f);
+ psys->dt_frac = dt_target;
/* Sync with frame end if it's close. */
if (t_frac == 1.0f)
@@ -3973,31 +4217,72 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
case PART_PHYS_FLUID:
{
SPHData sphdata;
- sph_solver_init(sim, &sphdata);
+ ParticleSettings *part = sim->psys->part;
+ psys_sph_init(sim, &sphdata);
- #pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
- LOOP_DYNAMIC_PARTICLES {
- /* do global forces & effectors */
- basic_integrate(sim, p, pa->state.time, cfra);
+ if (part->fluid->flag & SPH_SOLVER_DDR) {
+ /* Apply SPH forces using double-density relaxation algorithm
+ * (Clavat et. al.) */
+ #pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
+ LOOP_DYNAMIC_PARTICLES {
+ /* do global forces & effectors */
+ basic_integrate(sim, p, pa->state.time, cfra);
- /* actual fluids calculations */
- sph_integrate(sim, pa, pa->state.time, &sphdata);
+ /* actual fluids calculations */
+ sph_integrate(sim, pa, pa->state.time, &sphdata);
- if (sim->colliders)
- collision_check(sim, p, pa->state.time, cfra);
-
- /* SPH particles are not physical particles, just interpolation
- * particles, thus rotation has not a direct sense for them */
- basic_rotate(part, pa, pa->state.time, timestep);
+ if (sim->colliders)
+ collision_check(sim, p, pa->state.time, cfra);
+
+ /* SPH particles are not physical particles, just interpolation
+ * particles, thus rotation has not a direct sense for them */
+ basic_rotate(part, pa, pa->state.time, timestep);
+
+ #pragma omp critical
+ if (part->time_flag & PART_TIME_AUTOSF)
+ update_courant_num(sim, pa, dtime, &sphdata);
+ }
+
+ sph_springs_modify(psys, timestep);
- #pragma omp critical
- if (part->time_flag & PART_TIME_AUTOSF)
- update_courant_num(sim, pa, dtime, &sphdata);
}
+ else {
+ /* SPH_SOLVER_CLASSICAL */
+ /* Apply SPH forces using classical algorithm (due to Gingold
+ * and Monaghan). Note that, unlike double-density relaxation,
+ * this algorthim is separated into distinct loops. */
+
+ #pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
+ LOOP_DYNAMIC_PARTICLES {
+ basic_integrate(sim, p, pa->state.time, cfra);
+ }
+
+ /* calculate summation density */
+ #pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
+ LOOP_DYNAMIC_PARTICLES {
+ sphclassical_calc_dens(pa, pa->state.time, &sphdata);
+ }
+
+ /* do global forces & effectors */
+ #pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
+ LOOP_DYNAMIC_PARTICLES {
+ /* actual fluids calculations */
+ sph_integrate(sim, pa, pa->state.time, &sphdata);
+
+ if (sim->colliders)
+ collision_check(sim, p, pa->state.time, cfra);
+
+ /* SPH particles are not physical particles, just interpolation
+ * particles, thus rotation has not a direct sense for them */
+ basic_rotate(part, pa, pa->state.time, timestep);
- sph_springs_modify(psys, timestep);
+ #pragma omp critical
+ if (part->time_flag & PART_TIME_AUTOSF)
+ update_courant_num(sim, pa, dtime, &sphdata);
+ }
+ }
- sph_solver_finalise(&sphdata);
+ psys_sph_finalise(&sphdata);
break;
}
}
@@ -4309,14 +4594,14 @@ static void system_step(ParticleSimulationData *sim, float cfra)
if (!(part->time_flag & PART_TIME_AUTOSF)) {
/* Constant time step */
- psys->dt_frac = 1.0f / (float) (part->subframes + 1);
+ psys->dt_frac = get_base_time_step(part);
}
else if ((int)cfra == startframe) {
- /* Variable time step; use a very conservative value at the start.
- * If it doesn't need to be so small, it will quickly grow. */
- psys->dt_frac = 1.0;
+ /* Variable time step; initialise to subframes */
+ psys->dt_frac = get_base_time_step(part);
}
else if (psys->dt_frac < MIN_TIMESTEP) {
+ /* Variable time step; subsequent frames */
psys->dt_frac = MIN_TIMESTEP;
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
new file mode 100644
index 00000000000..3a4e8afca76
--- /dev/null
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -0,0 +1,1909 @@
+/*
+ * ***** 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 *****
+ */
+
+/** \file blender/blenlib/intern/pbvh.c
+ * \ingroup bli
+ */
+
+#include "DNA_meshdata_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "BKE_pbvh.h"
+#include "BKE_ccg.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
+#include "BKE_global.h" /* for BKE_mesh_calc_normals */
+#include "BKE_paint.h"
+#include "BKE_subsurf.h"
+
+#include "GPU_buffers.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 {
+ PBVHNode *node;
+ int revisiting;
+} PBVHStack;
+
+typedef struct PBVHIter {
+ PBVH *bvh;
+ BLI_pbvh_SearchCallback scb;
+ void *search_data;
+
+ PBVHStack *stack;
+ int stacksize;
+
+ PBVHStack stackfixed[STACK_FIXED_DEPTH];
+ int stackspace;
+} PBVHIter;
+
+static 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])
+{
+ int i;
+ for (i = 0; i < 3; ++i) {
+ bb->bmin[i] = min_ff(bb->bmin[i], co[i]);
+ bb->bmax[i] = max_ff(bb->bmax[i], co[i]);
+ }
+}
+
+/* Expand the bounding box to include another bounding box */
+static void BB_expand_with_bb(BB *bb, BB *bb2)
+{
+ int i;
+ for (i = 0; i < 3; ++i) {
+ bb->bmin[i] = min_ff(bb->bmin[i], bb2->bmin[i]);
+ bb->bmax[i] = max_ff(bb->bmax[i], bb2->bmax[i]);
+ }
+}
+
+/* Return 0, 1, or 2 to indicate the widest axis of the bounding box */
+static int BB_widest_axis(BB *bb)
+{
+ float dim[3];
+ int i;
+
+ for (i = 0; i < 3; ++i)
+ dim[i] = bb->bmax[i] - bb->bmin[i];
+
+ if (dim[0] > dim[1]) {
+ if (dim[0] > dim[2])
+ return 0;
+ else
+ return 2;
+ }
+ else {
+ if (dim[1] > dim[2])
+ return 1;
+ else
+ return 2;
+ }
+}
+
+static void BBC_update_centroid(BBC *bbc)
+{
+ int i;
+ for (i = 0; i < 3; ++i)
+ bbc->bcentroid[i] = (bbc->bmin[i] + bbc->bmax[i]) * 0.5f;
+}
+
+/* Not recursive */
+static void update_node_vb(PBVH *bvh, PBVHNode *node)
+{
+ BB vb;
+
+ BB_reset(&vb);
+
+ if (node->flag & PBVH_Leaf) {
+ PBVHVertexIter vd;
+
+ BLI_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
+ {
+ BB_expand(&vb, vd.co);
+ }
+ BLI_pbvh_vertex_iter_end;
+ }
+ else {
+ BB_expand_with_bb(&vb,
+ &bvh->nodes[node->children_offset].vb);
+ BB_expand_with_bb(&vb,
+ &bvh->nodes[node->children_offset + 1].vb);
+ }
+
+ node->vb = vb;
+}
+
+//void BLI_pbvh_node_BB_reset(PBVHNode *node)
+//{
+// BB_reset(&node->vb);
+//}
+//
+//void BLI_pbvh_node_BB_expand(PBVHNode *node, float co[3])
+//{
+// BB_expand(&node->vb, co);
+//}
+
+static int face_materials_match(const MFace *f1, const MFace *f2)
+{
+ return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
+ (f1->mat_nr == f2->mat_nr));
+}
+
+static int grid_materials_match(const DMFlagMat *f1, const DMFlagMat *f2)
+{
+ return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
+ (f1->mat_nr == f2->mat_nr));
+}
+
+/* Adapted from BLI_kdopbvh.c */
+/* Returns the index of the first element on the right of the partition */
+static int partition_indices(int *prim_indices, int lo, int hi, int axis,
+ float mid, BBC *prim_bbc)
+{
+ int i = lo, j = hi;
+ for (;; ) {
+ for (; prim_bbc[prim_indices[i]].bcentroid[axis] < mid; i++) ;
+ for (; mid < prim_bbc[prim_indices[j]].bcentroid[axis]; j--) ;
+
+ if (!(i < j))
+ return i;
+
+ SWAP(int, prim_indices[i], prim_indices[j]);
+ i++;
+ }
+}
+
+/* Returns the index of the first element on the right of the partition */
+static int partition_indices_material(PBVH *bvh, int lo, int hi)
+{
+ const MFace *faces = bvh->faces;
+ const DMFlagMat *flagmats = bvh->grid_flag_mats;
+ const int *indices = bvh->prim_indices;
+ const void *first;
+ int i = lo, j = hi;
+
+ if (bvh->faces)
+ first = &faces[bvh->prim_indices[lo]];
+ else
+ first = &flagmats[bvh->prim_indices[lo]];
+
+ for (;; ) {
+ if (bvh->faces) {
+ for (; face_materials_match(first, &faces[indices[i]]); i++) ;
+ for (; !face_materials_match(first, &faces[indices[j]]); j--) ;
+ }
+ else {
+ for (; grid_materials_match(first, &flagmats[indices[i]]); i++) ;
+ for (; !grid_materials_match(first, &flagmats[indices[j]]); j--) ;
+ }
+
+ if (!(i < j))
+ return i;
+
+ SWAP(int, bvh->prim_indices[i], bvh->prim_indices[j]);
+ i++;
+ }
+}
+
+static void grow_nodes(PBVH *bvh, int totnode)
+{
+ if (totnode > bvh->node_mem_count) {
+ PBVHNode *prev = bvh->nodes;
+ bvh->node_mem_count *= 1.33;
+ if (bvh->node_mem_count < totnode)
+ bvh->node_mem_count = totnode;
+ bvh->nodes = MEM_callocN(sizeof(PBVHNode) * bvh->node_mem_count,
+ "bvh nodes");
+ memcpy(bvh->nodes, prev, bvh->totnode * sizeof(PBVHNode));
+ MEM_freeN(prev);
+ }
+
+ bvh->totnode = totnode;
+}
+
+/* Add a vertex to the map, with a positive value for unique vertices and
+ * a negative value for additional vertices */
+static int map_insert_vert(PBVH *bvh, GHash *map,
+ unsigned int *face_verts,
+ unsigned int *uniq_verts, int vertex)
+{
+ void *value, *key = SET_INT_IN_POINTER(vertex);
+
+ if (!BLI_ghash_haskey(map, key)) {
+ if (BLI_BITMAP_GET(bvh->vert_bitmap, vertex)) {
+ value = SET_INT_IN_POINTER(~(*face_verts));
+ ++(*face_verts);
+ }
+ else {
+ BLI_BITMAP_SET(bvh->vert_bitmap, vertex);
+ value = SET_INT_IN_POINTER(*uniq_verts);
+ ++(*uniq_verts);
+ }
+
+ BLI_ghash_insert(map, key, value);
+ return GET_INT_FROM_POINTER(value);
+ }
+ else
+ return GET_INT_FROM_POINTER(BLI_ghash_lookup(map, key));
+}
+
+/* Find vertices used by the faces in this node and update the draw buffers */
+static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
+{
+ GHashIterator *iter;
+ GHash *map;
+ int i, j, totface;
+
+ map = BLI_ghash_int_new("build_mesh_leaf_node gh");
+
+ node->uniq_verts = node->face_verts = 0;
+ totface = node->totprim;
+
+ node->face_vert_indices = MEM_callocN(sizeof(int) * 4 * totface,
+ "bvh node face vert indices");
+
+ for (i = 0; i < totface; ++i) {
+ MFace *f = bvh->faces + node->prim_indices[i];
+ int sides = f->v4 ? 4 : 3;
+
+ for (j = 0; j < sides; ++j) {
+ node->face_vert_indices[i][j] =
+ map_insert_vert(bvh, map, &node->face_verts,
+ &node->uniq_verts, (&f->v1)[j]);
+ }
+ }
+
+ node->vert_indices = MEM_callocN(sizeof(int) *
+ (node->uniq_verts + node->face_verts),
+ "bvh node vert indices");
+
+ /* Build the vertex list, unique verts first */
+ for (iter = BLI_ghashIterator_new(map), i = 0;
+ BLI_ghashIterator_isDone(iter) == FALSE;
+ BLI_ghashIterator_step(iter), ++i)
+ {
+ void *value = BLI_ghashIterator_getValue(iter);
+ int ndx = GET_INT_FROM_POINTER(value);
+
+ if (ndx < 0)
+ ndx = -ndx + node->uniq_verts - 1;
+
+ node->vert_indices[ndx] =
+ GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(iter));
+ }
+
+ BLI_ghashIterator_free(iter);
+
+ for (i = 0; i < totface; ++i) {
+ MFace *f = bvh->faces + node->prim_indices[i];
+ int sides = f->v4 ? 4 : 3;
+
+ for (j = 0; j < sides; ++j) {
+ if (node->face_vert_indices[i][j] < 0)
+ node->face_vert_indices[i][j] =
+ -node->face_vert_indices[i][j] +
+ node->uniq_verts - 1;
+ }
+ }
+
+ if (!G.background) {
+ node->draw_buffers =
+ GPU_build_mesh_buffers(node->face_vert_indices,
+ bvh->faces, bvh->verts,
+ node->prim_indices,
+ node->totprim);
+ }
+
+ node->flag |= PBVH_UpdateDrawBuffers;
+
+ BLI_ghash_free(map, NULL, NULL);
+}
+
+static void build_grids_leaf_node(PBVH *bvh, PBVHNode *node)
+{
+ if (!G.background) {
+ node->draw_buffers =
+ GPU_build_grid_buffers(node->prim_indices,
+ node->totprim, bvh->grid_hidden, bvh->gridkey.grid_size);
+ }
+ node->flag |= PBVH_UpdateDrawBuffers;
+}
+
+static void update_vb(PBVH *bvh, PBVHNode *node, BBC *prim_bbc,
+ int offset, int count)
+{
+ int i;
+
+ BB_reset(&node->vb);
+ for (i = offset + count - 1; i >= offset; --i) {
+ BB_expand_with_bb(&node->vb, (BB *)(&prim_bbc[bvh->prim_indices[i]]));
+ }
+ node->orig_vb = node->vb;
+}
+
+static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
+ int offset, int count)
+{
+ bvh->nodes[node_index].flag |= PBVH_Leaf;
+
+ bvh->nodes[node_index].prim_indices = bvh->prim_indices + offset;
+ bvh->nodes[node_index].totprim = count;
+
+ /* Still need vb for searches */
+ update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
+
+ if (bvh->faces)
+ build_mesh_leaf_node(bvh, bvh->nodes + node_index);
+ else
+ build_grids_leaf_node(bvh, bvh->nodes + node_index);
+}
+
+/* Return zero if all primitives in the node can be drawn with the
+ * same material (including flat/smooth shading), non-zerootherwise */
+static int leaf_needs_material_split(PBVH *bvh, int offset, int count)
+{
+ int i, prim;
+
+ if (count <= 1)
+ return 0;
+
+ if (bvh->faces) {
+ const MFace *first = &bvh->faces[bvh->prim_indices[offset]];
+
+ for (i = offset + count - 1; i > offset; --i) {
+ prim = bvh->prim_indices[i];
+ if (!face_materials_match(first, &bvh->faces[prim]))
+ return 1;
+ }
+ }
+ else {
+ const DMFlagMat *first = &bvh->grid_flag_mats[bvh->prim_indices[offset]];
+
+ for (i = offset + count - 1; i > offset; --i) {
+ prim = bvh->prim_indices[i];
+ if (!grid_materials_match(first, &bvh->grid_flag_mats[prim]))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+/* Recursively build a node in the tree
+ *
+ * vb is the voxel box around all of the primitives contained in
+ * this node.
+ *
+ * cb is the bounding box around all the centroids of the primitives
+ * contained in this node
+ *
+ * offset and start indicate a range in the array of primitive indices
+ */
+
+static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
+ int offset, int count)
+{
+ int i, axis, end, below_leaf_limit;
+ BB cb_backing;
+
+ /* Decide whether this is a leaf or not */
+ below_leaf_limit = count <= bvh->leaf_limit;
+ if (below_leaf_limit) {
+ if (!leaf_needs_material_split(bvh, offset, count)) {
+ build_leaf(bvh, node_index, prim_bbc, offset, count);
+ return;
+ }
+ }
+
+ /* Add two child nodes */
+ bvh->nodes[node_index].children_offset = bvh->totnode;
+ grow_nodes(bvh, bvh->totnode + 2);
+
+ /* Update parent node bounding box */
+ update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
+
+ if (!below_leaf_limit) {
+ /* Find axis with widest range of primitive centroids */
+ if (!cb) {
+ cb = &cb_backing;
+ BB_reset(cb);
+ for (i = offset + count - 1; i >= offset; --i)
+ BB_expand(cb, prim_bbc[bvh->prim_indices[i]].bcentroid);
+ }
+ axis = BB_widest_axis(cb);
+
+ /* Partition primitives along that axis */
+ end = partition_indices(bvh->prim_indices,
+ offset, offset + count - 1,
+ axis,
+ (cb->bmax[axis] + cb->bmin[axis]) * 0.5f,
+ prim_bbc);
+ }
+ else {
+ /* Partition primitives by material */
+ end = partition_indices_material(bvh, offset, offset + count - 1);
+ }
+
+ /* Build children */
+ build_sub(bvh, bvh->nodes[node_index].children_offset, NULL,
+ prim_bbc, offset, end - offset);
+ build_sub(bvh, bvh->nodes[node_index].children_offset + 1, NULL,
+ prim_bbc, end, offset + count - end);
+}
+
+static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
+{
+ int i;
+
+ if (totprim != bvh->totprim) {
+ bvh->totprim = totprim;
+ if (bvh->nodes) MEM_freeN(bvh->nodes);
+ if (bvh->prim_indices) MEM_freeN(bvh->prim_indices);
+ bvh->prim_indices = MEM_callocN(sizeof(int) * totprim,
+ "bvh prim indices");
+ for (i = 0; i < totprim; ++i)
+ bvh->prim_indices[i] = i;
+ bvh->totnode = 0;
+ if (bvh->node_mem_count < 100) {
+ bvh->node_mem_count = 100;
+ bvh->nodes = MEM_callocN(sizeof(PBVHNode) *
+ bvh->node_mem_count,
+ "bvh initial nodes");
+ }
+ }
+
+ bvh->totnode = 1;
+ build_sub(bvh, 0, cb, prim_bbc, 0, 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)
+{
+ BBC *prim_bbc = NULL;
+ BB cb;
+ int i, j;
+
+ bvh->type = PBVH_FACES;
+ bvh->faces = faces;
+ bvh->verts = verts;
+ bvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
+ bvh->totvert = totvert;
+ bvh->leaf_limit = LEAF_LIMIT;
+ bvh->vdata = vdata;
+
+ BB_reset(&cb);
+
+ /* For each face, store the AABB and the AABB centroid */
+ prim_bbc = MEM_mallocN(sizeof(BBC) * totface, "prim_bbc");
+
+ for (i = 0; i < totface; ++i) {
+ MFace *f = faces + i;
+ const int sides = f->v4 ? 4 : 3;
+ BBC *bbc = prim_bbc + i;
+
+ BB_reset((BB *)bbc);
+
+ for (j = 0; j < sides; ++j)
+ BB_expand((BB *)bbc, verts[(&f->v1)[j]].co);
+
+ BBC_update_centroid(bbc);
+
+ BB_expand(&cb, bbc->bcentroid);
+ }
+
+ if (totface)
+ pbvh_build(bvh, &cb, prim_bbc, totface);
+
+ MEM_freeN(prim_bbc);
+ MEM_freeN(bvh->vert_bitmap);
+}
+
+/* Do a full rebuild with on Grids data structure */
+void BLI_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;
+ BB cb;
+ int gridsize = key->grid_size;
+ int i, j;
+
+ bvh->type = PBVH_GRIDS;
+ bvh->grids = grids;
+ bvh->gridadj = gridadj;
+ bvh->gridfaces = gridfaces;
+ bvh->grid_flag_mats = flagmats;
+ bvh->totgrid = totgrid;
+ bvh->gridkey = *key;
+ bvh->grid_hidden = grid_hidden;
+ bvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1);
+
+ BB_reset(&cb);
+
+ /* For each grid, store the AABB and the AABB centroid */
+ prim_bbc = MEM_mallocN(sizeof(BBC) * totgrid, "prim_bbc");
+
+ for (i = 0; i < totgrid; ++i) {
+ CCGElem *grid = grids[i];
+ BBC *bbc = prim_bbc + i;
+
+ BB_reset((BB *)bbc);
+
+ for (j = 0; j < gridsize * gridsize; ++j)
+ BB_expand((BB *)bbc, CCG_elem_offset_co(key, grid, j));
+
+ BBC_update_centroid(bbc);
+
+ BB_expand(&cb, bbc->bcentroid);
+ }
+
+ if (totgrid)
+ pbvh_build(bvh, &cb, prim_bbc, totgrid);
+
+ MEM_freeN(prim_bbc);
+}
+
+PBVH *BLI_pbvh_new(void)
+{
+ PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
+
+ return bvh;
+}
+
+void BLI_pbvh_free(PBVH *bvh)
+{
+ PBVHNode *node;
+ int i;
+
+ for (i = 0; i < bvh->totnode; ++i) {
+ node = &bvh->nodes[i];
+
+ if (node->flag & PBVH_Leaf) {
+ if (node->draw_buffers)
+ GPU_free_buffers(node->draw_buffers);
+ if (node->vert_indices)
+ MEM_freeN(node->vert_indices);
+ if (node->face_vert_indices)
+ MEM_freeN(node->face_vert_indices);
+ }
+ }
+
+ if (bvh->deformed) {
+ if (bvh->verts) {
+ /* if pbvh was deformed, new memory was allocated for verts/faces -- free it */
+
+ MEM_freeN(bvh->verts);
+ if (bvh->faces)
+ MEM_freeN(bvh->faces);
+ }
+ }
+
+ if (bvh->nodes)
+ MEM_freeN(bvh->nodes);
+
+ if (bvh->prim_indices)
+ MEM_freeN(bvh->prim_indices);
+
+ MEM_freeN(bvh);
+}
+
+static void pbvh_iter_begin(PBVHIter *iter, PBVH *bvh, BLI_pbvh_SearchCallback scb, void *search_data)
+{
+ iter->bvh = bvh;
+ iter->scb = scb;
+ iter->search_data = search_data;
+
+ iter->stack = iter->stackfixed;
+ iter->stackspace = STACK_FIXED_DEPTH;
+
+ iter->stack[0].node = bvh->nodes;
+ iter->stack[0].revisiting = 0;
+ iter->stacksize = 1;
+}
+
+static void pbvh_iter_end(PBVHIter *iter)
+{
+ if (iter->stackspace > STACK_FIXED_DEPTH)
+ MEM_freeN(iter->stack);
+}
+
+static void pbvh_stack_push(PBVHIter *iter, PBVHNode *node, int revisiting)
+{
+ if (iter->stacksize == iter->stackspace) {
+ PBVHStack *newstack;
+
+ iter->stackspace *= 2;
+ newstack = MEM_callocN(sizeof(PBVHStack) * iter->stackspace, "PBVHStack");
+ memcpy(newstack, iter->stack, sizeof(PBVHStack) * iter->stacksize);
+
+ if (iter->stackspace > STACK_FIXED_DEPTH)
+ MEM_freeN(iter->stack);
+ iter->stack = newstack;
+ }
+
+ iter->stack[iter->stacksize].node = node;
+ iter->stack[iter->stacksize].revisiting = revisiting;
+ iter->stacksize++;
+}
+
+static PBVHNode *pbvh_iter_next(PBVHIter *iter)
+{
+ PBVHNode *node;
+ int revisiting;
+
+ /* purpose here is to traverse tree, visiting child nodes before their
+ * parents, this order is necessary for e.g. computing bounding boxes */
+
+ while (iter->stacksize) {
+ /* pop node */
+ iter->stacksize--;
+ node = iter->stack[iter->stacksize].node;
+
+ /* on a mesh with no faces this can happen
+ * can remove this check if we know meshes have at least 1 face */
+ if (node == NULL)
+ return NULL;
+
+ revisiting = iter->stack[iter->stacksize].revisiting;
+
+ /* revisiting node already checked */
+ if (revisiting)
+ return node;
+
+ if (iter->scb && !iter->scb(node, iter->search_data))
+ continue; /* don't traverse, outside of search zone */
+
+ if (node->flag & PBVH_Leaf) {
+ /* immediately hit leaf node */
+ return node;
+ }
+ else {
+ /* come back later when children are done */
+ pbvh_stack_push(iter, node, 1);
+
+ /* push two child nodes on the stack */
+ pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, 0);
+ pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, 0);
+ }
+ }
+
+ return NULL;
+}
+
+static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
+{
+ PBVHNode *node;
+
+ while (iter->stacksize) {
+ /* pop node */
+ iter->stacksize--;
+ node = iter->stack[iter->stacksize].node;
+
+ /* on a mesh with no faces this can happen
+ * can remove this check if we know meshes have at least 1 face */
+ if (node == NULL) return NULL;
+
+ if (iter->scb && !iter->scb(node, iter->search_data)) continue; /* don't traverse, outside of search zone */
+
+ if (node->flag & PBVH_Leaf) {
+ /* immediately hit leaf node */
+ return node;
+ }
+ else {
+ pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, 0);
+ pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, 0);
+ }
+ }
+
+ return NULL;
+}
+
+void BLI_pbvh_search_gather(PBVH *bvh,
+ BLI_pbvh_SearchCallback scb, void *search_data,
+ PBVHNode ***r_array, int *r_tot)
+{
+ PBVHIter iter;
+ PBVHNode **array = NULL, **newarray, *node;
+ int tot = 0, space = 0;
+
+ pbvh_iter_begin(&iter, bvh, scb, search_data);
+
+ while ((node = pbvh_iter_next(&iter))) {
+ if (node->flag & PBVH_Leaf) {
+ if (tot == space) {
+ /* resize array if needed */
+ space = (tot == 0) ? 32 : space * 2;
+ newarray = MEM_callocN(sizeof(PBVHNode) * space, "PBVHNodeSearch");
+
+ if (array) {
+ memcpy(newarray, array, sizeof(PBVHNode) * tot);
+ MEM_freeN(array);
+ }
+
+ array = newarray;
+ }
+
+ array[tot] = node;
+ tot++;
+ }
+ }
+
+ pbvh_iter_end(&iter);
+
+ if (tot == 0 && array) {
+ MEM_freeN(array);
+ array = NULL;
+ }
+
+ *r_array = array;
+ *r_tot = tot;
+}
+
+void BLI_pbvh_search_callback(PBVH *bvh,
+ BLI_pbvh_SearchCallback scb, void *search_data,
+ BLI_pbvh_HitCallback hcb, void *hit_data)
+{
+ PBVHIter iter;
+ PBVHNode *node;
+
+ pbvh_iter_begin(&iter, bvh, scb, search_data);
+
+ while ((node = pbvh_iter_next(&iter)))
+ if (node->flag & PBVH_Leaf)
+ hcb(node, hit_data);
+
+ pbvh_iter_end(&iter);
+}
+
+typedef struct node_tree {
+ PBVHNode *data;
+
+ struct node_tree *left;
+ struct node_tree *right;
+} node_tree;
+
+static void node_tree_insert(node_tree *tree, node_tree *new_node)
+{
+ if (new_node->data->tmin < tree->data->tmin) {
+ if (tree->left) {
+ node_tree_insert(tree->left, new_node);
+ }
+ else {
+ tree->left = new_node;
+ }
+ }
+ else {
+ if (tree->right) {
+ node_tree_insert(tree->right, new_node);
+ }
+ else {
+ tree->right = new_node;
+ }
+ }
+}
+
+static void traverse_tree(node_tree *tree, BLI_pbvh_HitOccludedCallback hcb, void *hit_data, float *tmin)
+{
+ if (tree->left) traverse_tree(tree->left, hcb, hit_data, tmin);
+
+ hcb(tree->data, hit_data, tmin);
+
+ if (tree->right) traverse_tree(tree->right, hcb, hit_data, tmin);
+}
+
+static void free_tree(node_tree *tree)
+{
+ if (tree->left) {
+ free_tree(tree->left);
+ tree->left = 0;
+ }
+
+ if (tree->right) {
+ free_tree(tree->right);
+ tree->right = 0;
+ }
+
+ free(tree);
+}
+
+float BLI_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)
+{
+ PBVHIter iter;
+ PBVHNode *node;
+ node_tree *tree = 0;
+
+ pbvh_iter_begin(&iter, bvh, scb, search_data);
+
+ while ((node = pbvh_iter_next_occluded(&iter))) {
+ if (node->flag & PBVH_Leaf) {
+ node_tree *new_node = malloc(sizeof(node_tree));
+
+ new_node->data = node;
+
+ new_node->left = NULL;
+ new_node->right = NULL;
+
+ if (tree) {
+ node_tree_insert(tree, new_node);
+ }
+ else {
+ tree = new_node;
+ }
+ }
+ }
+
+ pbvh_iter_end(&iter);
+
+ if (tree) {
+ float tmin = FLT_MAX;
+ traverse_tree(tree, hcb, hit_data, &tmin);
+ free_tree(tree);
+ }
+}
+
+static int update_search_cb(PBVHNode *node, void *data_v)
+{
+ int flag = GET_INT_FROM_POINTER(data_v);
+
+ if (node->flag & PBVH_Leaf)
+ return (node->flag & flag);
+
+ return 1;
+}
+
+static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
+ int totnode, float (*face_nors)[3])
+{
+ float (*vnor)[3];
+ int n;
+
+ if (bvh->type != PBVH_FACES)
+ return;
+
+ /* could be per node to save some memory, but also means
+ * we have to store for each vertex which node it is in */
+ vnor = MEM_callocN(sizeof(float) * 3 * bvh->totvert, "bvh temp vnors");
+
+ /* subtle assumptions:
+ * - We know that for all edited vertices, the nodes with faces
+ * adjacent to these vertices have been marked with PBVH_UpdateNormals.
+ * This is true because if the vertex is inside the brush radius, the
+ * bounding box of it's adjacent faces will be as well.
+ * - However this is only true for the vertices that have actually been
+ * edited, not for all vertices in the nodes marked for update, so we
+ * can only update vertices marked with ME_VERT_PBVH_UPDATE.
+ */
+
+ #pragma omp parallel for private(n) schedule(static)
+ for (n = 0; n < totnode; n++) {
+ PBVHNode *node = nodes[n];
+
+ if ((node->flag & PBVH_UpdateNormals)) {
+ int i, j, totface, *faces;
+
+ faces = node->prim_indices;
+ totface = node->totprim;
+
+ for (i = 0; i < totface; ++i) {
+ MFace *f = bvh->faces + faces[i];
+ float fn[3];
+ unsigned int *fv = &f->v1;
+ int sides = (f->v4) ? 4 : 3;
+
+ if (f->v4)
+ normal_quad_v3(fn, bvh->verts[f->v1].co, bvh->verts[f->v2].co,
+ bvh->verts[f->v3].co, bvh->verts[f->v4].co);
+ else
+ normal_tri_v3(fn, bvh->verts[f->v1].co, bvh->verts[f->v2].co,
+ bvh->verts[f->v3].co);
+
+ for (j = 0; j < sides; ++j) {
+ int v = fv[j];
+
+ if (bvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
+ /* this seems like it could be very slow but profile
+ * does not show this, so just leave it for now? */
+ #pragma omp atomic
+ vnor[v][0] += fn[0];
+ #pragma omp atomic
+ vnor[v][1] += fn[1];
+ #pragma omp atomic
+ vnor[v][2] += fn[2];
+ }
+ }
+
+ if (face_nors)
+ copy_v3_v3(face_nors[faces[i]], fn);
+ }
+ }
+ }
+
+ #pragma omp parallel for private(n) schedule(static)
+ for (n = 0; n < totnode; n++) {
+ PBVHNode *node = nodes[n];
+
+ if (node->flag & PBVH_UpdateNormals) {
+ int i, *verts, totvert;
+
+ verts = node->vert_indices;
+ totvert = node->uniq_verts;
+
+ for (i = 0; i < totvert; ++i) {
+ const int v = verts[i];
+ MVert *mvert = &bvh->verts[v];
+
+ if (mvert->flag & ME_VERT_PBVH_UPDATE) {
+ float no[3];
+
+ copy_v3_v3(no, vnor[v]);
+ normalize_v3(no);
+ normal_float_to_short_v3(mvert->no, no);
+
+ mvert->flag &= ~ME_VERT_PBVH_UPDATE;
+ }
+ }
+
+ node->flag &= ~PBVH_UpdateNormals;
+ }
+ }
+
+ MEM_freeN(vnor);
+}
+
+static void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes,
+ int totnode, int flag)
+{
+ int n;
+
+ /* update BB, redraw flag */
+ #pragma omp parallel for private(n) schedule(static)
+ for (n = 0; n < totnode; n++) {
+ PBVHNode *node = nodes[n];
+
+ if ((flag & PBVH_UpdateBB) && (node->flag & PBVH_UpdateBB))
+ /* don't clear flag yet, leave it for flushing later */
+ update_node_vb(bvh, node);
+
+ if ((flag & PBVH_UpdateOriginalBB) && (node->flag & PBVH_UpdateOriginalBB))
+ node->orig_vb = node->vb;
+
+ if ((flag & PBVH_UpdateRedraw) && (node->flag & PBVH_UpdateRedraw))
+ node->flag &= ~PBVH_UpdateRedraw;
+ }
+}
+
+static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
+{
+ PBVHNode *node;
+ int n;
+
+ /* can't be done in parallel with OpenGL */
+ for (n = 0; n < totnode; n++) {
+ node = nodes[n];
+
+ if (node->flag & PBVH_RebuildDrawBuffers) {
+ GPU_free_buffers(node->draw_buffers);
+ switch (bvh->type) {
+ case PBVH_GRIDS:
+ node->draw_buffers =
+ GPU_build_grid_buffers(node->prim_indices,
+ node->totprim,
+ bvh->grid_hidden,
+ bvh->gridkey.grid_size);
+ break;
+ case PBVH_FACES:
+ node->draw_buffers =
+ GPU_build_mesh_buffers(node->face_vert_indices,
+ bvh->faces, bvh->verts,
+ node->prim_indices,
+ node->totprim);
+ break;
+ }
+
+ node->flag &= ~PBVH_RebuildDrawBuffers;
+ }
+
+ if (node->flag & PBVH_UpdateDrawBuffers) {
+ switch (bvh->type) {
+ case PBVH_GRIDS:
+ GPU_update_grid_buffers(node->draw_buffers,
+ bvh->grids,
+ bvh->grid_flag_mats,
+ node->prim_indices,
+ node->totprim,
+ &bvh->gridkey,
+ bvh->show_diffuse_color);
+ break;
+ case PBVH_FACES:
+ GPU_update_mesh_buffers(node->draw_buffers,
+ bvh->verts,
+ node->vert_indices,
+ node->uniq_verts +
+ node->face_verts,
+ CustomData_get_layer(bvh->vdata,
+ CD_PAINT_MASK),
+ node->face_vert_indices,
+ bvh->show_diffuse_color);
+ break;
+ }
+
+ node->flag &= ~PBVH_UpdateDrawBuffers;
+ }
+ }
+}
+
+static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
+{
+ int update = 0;
+
+ /* difficult to multithread well, we just do single threaded recursive */
+ if (node->flag & PBVH_Leaf) {
+ if (flag & PBVH_UpdateBB) {
+ update |= (node->flag & PBVH_UpdateBB);
+ node->flag &= ~PBVH_UpdateBB;
+ }
+
+ if (flag & PBVH_UpdateOriginalBB) {
+ update |= (node->flag & PBVH_UpdateOriginalBB);
+ node->flag &= ~PBVH_UpdateOriginalBB;
+ }
+
+ return update;
+ }
+ else {
+ update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset, flag);
+ update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset + 1, flag);
+
+ if (update & PBVH_UpdateBB)
+ update_node_vb(bvh, node);
+ if (update & PBVH_UpdateOriginalBB)
+ node->orig_vb = node->vb;
+ }
+
+ return update;
+}
+
+void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3])
+{
+ PBVHNode **nodes;
+ int totnode;
+
+ if (!bvh->nodes)
+ return;
+
+ BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(flag),
+ &nodes, &totnode);
+
+ if (flag & PBVH_UpdateNormals)
+ pbvh_update_normals(bvh, nodes, totnode, face_nors);
+
+ if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw))
+ pbvh_update_BB_redraw(bvh, nodes, totnode, flag);
+
+ if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB))
+ pbvh_flush_bb(bvh, bvh->nodes, flag);
+
+ if (nodes) MEM_freeN(nodes);
+}
+
+void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
+{
+ PBVHIter iter;
+ PBVHNode *node;
+ BB bb;
+
+ BB_reset(&bb);
+
+ pbvh_iter_begin(&iter, bvh, NULL, NULL);
+
+ while ((node = pbvh_iter_next(&iter)))
+ if (node->flag & PBVH_UpdateRedraw)
+ BB_expand_with_bb(&bb, &node->vb);
+
+ pbvh_iter_end(&iter);
+
+ copy_v3_v3(bb_min, bb.bmin);
+ copy_v3_v3(bb_max, bb.bmax);
+}
+
+void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface)
+{
+ PBVHIter iter;
+ PBVHNode *node;
+ GHashIterator *hiter;
+ GHash *map;
+ void *face, **faces;
+ unsigned i;
+ int tot;
+
+ map = BLI_ghash_ptr_new("pbvh_get_grid_updates gh");
+
+ pbvh_iter_begin(&iter, bvh, NULL, NULL);
+
+ while ((node = pbvh_iter_next(&iter))) {
+ if (node->flag & PBVH_UpdateNormals) {
+ for (i = 0; i < node->totprim; ++i) {
+ face = bvh->gridfaces[node->prim_indices[i]];
+ if (!BLI_ghash_lookup(map, face))
+ BLI_ghash_insert(map, face, face);
+ }
+
+ if (clear)
+ node->flag &= ~PBVH_UpdateNormals;
+ }
+ }
+
+ pbvh_iter_end(&iter);
+
+ tot = BLI_ghash_size(map);
+ if (tot == 0) {
+ *totface = 0;
+ *gridfaces = NULL;
+ BLI_ghash_free(map, NULL, NULL);
+ return;
+ }
+
+ faces = MEM_callocN(sizeof(void *) * tot, "PBVH Grid Faces");
+
+ for (hiter = BLI_ghashIterator_new(map), i = 0;
+ !BLI_ghashIterator_isDone(hiter);
+ BLI_ghashIterator_step(hiter), ++i)
+ {
+ faces[i] = BLI_ghashIterator_getKey(hiter);
+ }
+
+ BLI_ghashIterator_free(hiter);
+
+ BLI_ghash_free(map, NULL, NULL);
+
+ *totface = tot;
+ *gridfaces = faces;
+}
+
+/***************************** PBVH Access ***********************************/
+
+PBVHType BLI_pbvh_type(const PBVH *bvh)
+{
+ return bvh->type;
+}
+
+BLI_bitmap *BLI_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)
+{
+ BLI_assert(bvh->type == PBVH_GRIDS);
+ *key = bvh->gridkey;
+}
+
+/***************************** Node Access ***********************************/
+
+void BLI_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)
+{
+ node->flag |= PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
+}
+
+void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
+{
+ BLI_assert(node->flag & PBVH_Leaf);
+
+ if (fully_hidden)
+ node->flag |= PBVH_FullyHidden;
+ else
+ node->flag &= ~PBVH_FullyHidden;
+}
+
+void BLI_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)
+{
+ int tot;
+
+ switch (bvh->type) {
+ case PBVH_GRIDS:
+ tot = node->totprim * bvh->gridkey.grid_area;
+ if (totvert) *totvert = tot;
+ if (uniquevert) *uniquevert = tot;
+ break;
+ case PBVH_FACES:
+ if (totvert) *totvert = node->uniq_verts + node->face_verts;
+ if (uniquevert) *uniquevert = node->uniq_verts;
+ break;
+ }
+}
+
+void BLI_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:
+ if (grid_indices) *grid_indices = node->prim_indices;
+ if (totgrid) *totgrid = node->totprim;
+ if (maxgrid) *maxgrid = bvh->totgrid;
+ if (gridsize) *gridsize = bvh->gridkey.grid_size;
+ if (griddata) *griddata = bvh->grids;
+ if (gridadj) *gridadj = bvh->gridadj;
+ break;
+ case PBVH_FACES:
+ if (grid_indices) *grid_indices = NULL;
+ if (totgrid) *totgrid = 0;
+ if (maxgrid) *maxgrid = 0;
+ if (gridsize) *gridsize = 0;
+ if (griddata) *griddata = NULL;
+ if (gridadj) *gridadj = NULL;
+ break;
+ }
+}
+
+void BLI_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])
+{
+ 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)
+{
+ if (node->proxy_count > 0) {
+ if (proxies) *proxies = node->proxies;
+ if (proxy_count) *proxy_count = node->proxy_count;
+ }
+ else {
+ if (proxies) *proxies = 0;
+ if (proxy_count) *proxy_count = 0;
+ }
+}
+
+/********************************* Raycast ***********************************/
+
+typedef struct {
+ IsectRayAABBData ray;
+ int original;
+} RaycastData;
+
+static int ray_aabb_intersect(PBVHNode *node, void *data_v)
+{
+ RaycastData *rcd = data_v;
+ float bb_min[3], bb_max[3];
+
+ if (rcd->original)
+ BLI_pbvh_node_get_original_BB(node, bb_min, bb_max);
+ else
+ BLI_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,
+ const float ray_start[3], const float ray_normal[3],
+ int original)
+{
+ RaycastData rcd;
+
+ 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);
+}
+
+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)
+{
+ float dist;
+
+ if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist, NULL, 0.1f) && dist < *fdist) ||
+ (t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist, NULL, 0.1f) && dist < *fdist))
+ {
+ *fdist = dist;
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+static int pbvh_faces_node_raycast(PBVH *bvh, const PBVHNode *node,
+ float (*origco)[3],
+ const float ray_start[3],
+ const float ray_normal[3], float *dist)
+{
+ const MVert *vert = bvh->verts;
+ const int *faces = node->prim_indices;
+ int i, hit = 0, totface = node->totprim;
+
+ for (i = 0; i < totface; ++i) {
+ const MFace *f = bvh->faces + faces[i];
+ const int *face_verts = node->face_vert_indices[i];
+
+ if (paint_is_face_hidden(f, vert))
+ continue;
+
+ if (origco) {
+ /* intersect with backuped original coordinates */
+ hit |= ray_face_intersection(ray_start, ray_normal,
+ origco[face_verts[0]],
+ origco[face_verts[1]],
+ origco[face_verts[2]],
+ f->v4 ? origco[face_verts[3]] : NULL,
+ dist);
+ }
+ else {
+ /* intersect with current coordinates */
+ hit |= ray_face_intersection(ray_start, ray_normal,
+ vert[f->v1].co,
+ vert[f->v2].co,
+ vert[f->v3].co,
+ f->v4 ? vert[f->v4].co : NULL,
+ dist);
+ }
+ }
+
+ return hit;
+}
+
+static int pbvh_grids_node_raycast(PBVH *bvh, PBVHNode *node,
+ float (*origco)[3],
+ const float ray_start[3],
+ const float ray_normal[3], float *dist)
+{
+ int totgrid = node->totprim;
+ int gridsize = bvh->gridkey.grid_size;
+ int i, x, y, hit = 0;
+
+ for (i = 0; i < totgrid; ++i) {
+ CCGElem *grid = bvh->grids[node->prim_indices[i]];
+ BLI_bitmap gh;
+
+ if (!grid)
+ continue;
+
+ gh = bvh->grid_hidden[node->prim_indices[i]];
+
+ for (y = 0; y < gridsize - 1; ++y) {
+ for (x = 0; x < gridsize - 1; ++x) {
+ /* check if grid face is hidden */
+ if (gh) {
+ if (paint_is_grid_face_hidden(gh, gridsize, x, y))
+ continue;
+ }
+
+ if (origco) {
+ hit |= ray_face_intersection(ray_start, ray_normal,
+ origco[y * gridsize + x],
+ origco[y * gridsize + x + 1],
+ origco[(y + 1) * gridsize + x + 1],
+ origco[(y + 1) * gridsize + x],
+ dist);
+ }
+ else {
+ hit |= ray_face_intersection(ray_start, ray_normal,
+ CCG_grid_elem_co(&bvh->gridkey, grid, x, y),
+ CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y),
+ CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1),
+ CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
+ dist);
+ }
+ }
+ }
+
+ if (origco)
+ origco += gridsize * gridsize;
+ }
+
+ return hit;
+}
+
+int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
+ const float ray_start[3], const float ray_normal[3],
+ float *dist)
+{
+ int hit = 0;
+
+ if (node->flag & PBVH_FullyHidden)
+ return 0;
+
+ switch (bvh->type) {
+ case PBVH_FACES:
+ hit |= pbvh_faces_node_raycast(bvh, node, origco,
+ ray_start, ray_normal, dist);
+ break;
+ case PBVH_GRIDS:
+ hit |= pbvh_grids_node_raycast(bvh, node, origco,
+ ray_start, ray_normal, dist);
+ break;
+ }
+
+ return hit;
+}
+
+//#include <GL/glew.h>
+
+void BLI_pbvh_node_draw(PBVHNode *node, void *setMaterial)
+{
+#if 0
+ /* XXX: Just some quick code to show leaf nodes in different colors */
+ float col[3]; int i;
+
+ if (0) { //is_partial) {
+ col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6;
+ }
+ else {
+ srand((long long)node);
+ for (i = 0; i < 3; ++i)
+ col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7;
+ }
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col);
+
+ glColor3f(1, 0, 0);
+#endif
+
+ if (!(node->flag & PBVH_FullyHidden))
+ GPU_draw_buffers(node->draw_buffers, setMaterial);
+}
+
+typedef enum {
+ ISECT_INSIDE,
+ ISECT_OUTSIDE,
+ ISECT_INTERSECT
+} PlaneAABBIsect;
+
+/* Adapted from:
+ * http://www.gamedev.net/community/forums/topic.asp?topic_id=512123
+ * Returns true if the AABB is at least partially within the frustum
+ * (ok, not a real frustum), false otherwise.
+ */
+static PlaneAABBIsect test_planes_aabb(const float bb_min[3],
+ const float bb_max[3],
+ const float (*planes)[4])
+{
+ float vmin[3], vmax[3];
+ PlaneAABBIsect ret = ISECT_INSIDE;
+ int i, axis;
+
+ for (i = 0; i < 4; ++i) {
+ for (axis = 0; axis < 3; ++axis) {
+ if (planes[i][axis] > 0) {
+ vmin[axis] = bb_min[axis];
+ vmax[axis] = bb_max[axis];
+ }
+ else {
+ vmin[axis] = bb_max[axis];
+ vmax[axis] = bb_min[axis];
+ }
+ }
+
+ if (dot_v3v3(planes[i], vmin) + planes[i][3] > 0)
+ return ISECT_OUTSIDE;
+ else if (dot_v3v3(planes[i], vmax) + planes[i][3] >= 0)
+ ret = ISECT_INTERSECT;
+ }
+
+ return ret;
+}
+
+int BLI_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);
+ return test_planes_aabb(bb_min, bb_max, data) != ISECT_OUTSIDE;
+}
+
+int BLI_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);
+ return test_planes_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
+}
+
+static void pbvh_node_check_diffuse_changed(PBVH *bvh, PBVHNode *node)
+{
+ if (!node->draw_buffers)
+ return;
+
+ if (GPU_buffers_diffuse_changed(node->draw_buffers, bvh->show_diffuse_color))
+ node->flag |= PBVH_UpdateDrawBuffers;
+}
+
+void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
+ DMSetMaterial setMaterial)
+{
+ 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),
+ &nodes, &totnode);
+
+ pbvh_update_normals(bvh, nodes, totnode, face_nors);
+ pbvh_update_draw_buffers(bvh, nodes, totnode);
+
+ if (nodes) MEM_freeN(nodes);
+
+ if (planes) {
+ BLI_pbvh_search_callback(bvh, BLI_pbvh_node_planes_contain_AABB,
+ planes, BLI_pbvh_node_draw, setMaterial);
+ }
+ else {
+ BLI_pbvh_search_callback(bvh, NULL, NULL, BLI_pbvh_node_draw, setMaterial);
+ }
+}
+
+void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces,
+ DMFlagMat *flagmats, BLI_bitmap *grid_hidden)
+{
+ int a;
+
+ bvh->grids = grids;
+ bvh->gridadj = gridadj;
+ bvh->gridfaces = gridfaces;
+
+ if (flagmats != bvh->grid_flag_mats || bvh->grid_hidden != grid_hidden) {
+ bvh->grid_flag_mats = flagmats;
+ bvh->grid_hidden = grid_hidden;
+
+ for (a = 0; a < bvh->totnode; ++a)
+ BLI_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]);
+ }
+}
+
+float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3]
+{
+ int a;
+ float (*vertCos)[3] = NULL;
+
+ if (pbvh->verts) {
+ float *co;
+ MVert *mvert = pbvh->verts;
+
+ vertCos = MEM_callocN(3 * pbvh->totvert * sizeof(float), "BLI_pbvh_get_vertCoords");
+ co = (float *)vertCos;
+
+ for (a = 0; a < pbvh->totvert; a++, mvert++, co += 3) {
+ copy_v3_v3(co, mvert->co);
+ }
+ }
+
+ return vertCos;
+}
+
+void BLI_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
+{
+ int a;
+
+ if (!pbvh->deformed) {
+ if (pbvh->verts) {
+ /* if pbvh is not already deformed, verts/faces points to the */
+ /* original data and applying new coords to this arrays would lead to */
+ /* unneeded deformation -- duplicate verts/faces to avoid this */
+
+ pbvh->verts = MEM_dupallocN(pbvh->verts);
+ pbvh->faces = MEM_dupallocN(pbvh->faces);
+
+ pbvh->deformed = 1;
+ }
+ }
+
+ if (pbvh->verts) {
+ MVert *mvert = pbvh->verts;
+ /* copy new verts coords */
+ for (a = 0; a < pbvh->totvert; ++a, ++mvert) {
+ copy_v3_v3(mvert->co, vertCos[a]);
+ mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+
+ /* coordinates are new -- normals should also be updated */
+ 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]);
+
+ BLI_pbvh_update(pbvh, PBVH_UpdateBB, NULL);
+ BLI_pbvh_update(pbvh, PBVH_UpdateOriginalBB, NULL);
+
+ }
+}
+
+int BLI_pbvh_isDeformed(PBVH *pbvh)
+{
+ return pbvh->deformed;
+}
+/* Proxies */
+
+PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
+{
+ int index, totverts;
+
+ #pragma omp critical
+ {
+
+ index = node->proxy_count;
+
+ node->proxy_count++;
+
+ if (node->proxies)
+ node->proxies = MEM_reallocN(node->proxies, node->proxy_count * sizeof(PBVHProxyNode));
+ else
+ node->proxies = MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy");
+
+ BLI_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)
+{
+ #pragma omp critical
+ {
+ int p;
+
+ for (p = 0; p < node->proxy_count; p++) {
+ MEM_freeN(node->proxies[p].co);
+ node->proxies[p].co = 0;
+ }
+
+ MEM_freeN(node->proxies);
+ node->proxies = 0;
+
+ node->proxy_count = 0;
+ }
+}
+
+void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot)
+{
+ PBVHNode **array = NULL, **newarray, *node;
+ int tot = 0, space = 0;
+ int n;
+
+ for (n = 0; n < pbvh->totnode; n++) {
+ node = pbvh->nodes + n;
+
+ if (node->proxy_count > 0) {
+ if (tot == space) {
+ /* resize array if needed */
+ space = (tot == 0) ? 32 : space * 2;
+ newarray = MEM_callocN(sizeof(PBVHNode) * space, "BLI_pbvh_gather_proxies");
+
+ if (array) {
+ memcpy(newarray, array, sizeof(PBVHNode) * tot);
+ MEM_freeN(array);
+ }
+
+ array = newarray;
+ }
+
+ array[tot] = node;
+ tot++;
+ }
+ }
+
+ if (tot == 0 && array) {
+ MEM_freeN(array);
+ array = NULL;
+ }
+
+ *r_array = array;
+ *r_tot = tot;
+}
+
+void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
+ PBVHVertexIter *vi, int mode)
+{
+ struct CCGElem **grids;
+ struct MVert *verts;
+ int *grid_indices, *vert_indices;
+ int totgrid, gridsize, uniq_verts, totvert;
+
+ vi->grid = 0;
+ vi->no = 0;
+ 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);
+ vi->key = &bvh->gridkey;
+
+ vi->grids = grids;
+ vi->grid_indices = grid_indices;
+ vi->totgrid = (grids) ? totgrid : 1;
+ vi->gridsize = gridsize;
+
+ if (mode == PBVH_ITER_ALL)
+ vi->totvert = totvert;
+ else
+ vi->totvert = uniq_verts;
+ vi->vert_indices = vert_indices;
+ vi->mverts = verts;
+
+ vi->gh = NULL;
+ if (vi->grids && mode == PBVH_ITER_UNIQUE)
+ vi->grid_hidden = bvh->grid_hidden;
+
+ vi->mask = NULL;
+ if (!vi->grids)
+ vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK);
+}
+
+void pbvh_show_diffuse_color_set(PBVH *bvh, int show_diffuse_color)
+{
+ bvh->show_diffuse_color = show_diffuse_color;
+}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 965a1e2b4a6..2eadfe73858 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -2782,7 +2782,8 @@ static PointCache *ptcache_copy(PointCache *cache, int copy_data)
ncache->mem_cache.last = NULL;
ncache->cached_frames = NULL;
- ncache->flag= 0;
+ /* flag is a mix of user settings and simulator/baking state */
+ ncache->flag= ncache->flag & (PTCACHE_DISK_CACHE|PTCACHE_EXTERNAL|PTCACHE_IGNORE_LIBPATH);
ncache->simframe= 0;
}
else {
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
index 8da4f11fed3..c4658712ecb 100644
--- a/source/blender/blenkernel/intern/property.c
+++ b/source/blender/blenkernel/intern/property.c
@@ -287,7 +287,7 @@ void BKE_bproperty_add(bProperty *prop, const char *str)
}
/* reads value of property, sets it in chars in str */
-void BKE_bproperty_set_valstr(bProperty *prop, char *str)
+void BKE_bproperty_set_valstr(bProperty *prop, char str[MAX_PROPSTRING])
{
// extern int Gdfra; /* sector.c */
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index d925d736358..185aeac5452 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -52,6 +52,8 @@ static const char *report_type_str(int type)
return TIP_("Info");
case RPT_OPERATOR:
return TIP_("Operator");
+ case RPT_PROPERTY:
+ return TIP_("Property");
case RPT_WARNING:
return TIP_("Warning");
case RPT_ERROR:
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 8fcd5ca56d0..5e6d7647d1d 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -145,7 +145,8 @@ Scene *BKE_scene_copy(Scene *sce, int type)
if (type == SCE_COPY_EMPTY) {
ListBase lb;
- scen = BKE_scene_add(sce->id.name + 2);
+ /* XXX. main should become an arg */
+ scen = BKE_scene_add(G.main, sce->id.name + 2);
lb = scen->r.layers;
scen->r = sce->r;
@@ -379,9 +380,8 @@ void BKE_scene_free(Scene *sce)
BKE_color_managed_view_settings_free(&sce->view_settings);
}
-Scene *BKE_scene_add(const char *name)
+static Scene *scene_add(Main *bmain, const char *name)
{
- Main *bmain = G.main;
Scene *sce;
ParticleEditSettings *pset;
int a;
@@ -439,6 +439,7 @@ Scene *BKE_scene_add(const char *name)
sce->r.bake_osa = 5;
sce->r.bake_flag = R_BAKE_CLEAR;
sce->r.bake_normal_space = R_BAKE_SPACE_TANGENT;
+ sce->r.bake_rays_number = 256;
sce->r.scemode = R_DOCOMP | R_DOSEQ | R_EXTENSION;
sce->r.stamp = R_STAMP_TIME | R_STAMP_FRAME | R_STAMP_DATE | R_STAMP_CAMERA | R_STAMP_SCENE | R_STAMP_FILENAME | R_STAMP_RENDERTIME;
sce->r.stamp_font_id = 12;
@@ -612,6 +613,11 @@ Scene *BKE_scene_add(const char *name)
return sce;
}
+Scene *BKE_scene_add(Main *bmain, const char *name)
+{
+ return scene_add(bmain, name);
+}
+
Base *BKE_scene_base_find(Scene *scene, Object *ob)
{
return BLI_findptr(&scene->base, ob, offsetof(Base, object));
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 0b7fdaa7c1d..3bff209f53c 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -1745,7 +1745,7 @@ static void transform_image(int x, int y, ImBuf *ibuf1, ImBuf *out, float scale
/* interpolate */
switch (interpolation) {
case 0:
- neareast_interpolation(ibuf1, out, xt, yt, xi, yi);
+ nearest_interpolation(ibuf1, out, xt, yt, xi, yi);
break;
case 1:
bilinear_interpolation(ibuf1, out, xt, yt, xi, yi);
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index acce3740c98..1467d24f323 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -191,7 +191,9 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const int do_cache
((ID *)seq->sound)->us--;
}
- /* clipboard has no scene and will never have a sound handle or be active */
+ /* clipboard has no scene and will never have a sound handle or be active
+ * same goes to sequences copy for proxy rebuild job
+ */
if (scene) {
Editing *ed = scene->ed;
@@ -1451,7 +1453,7 @@ void BKE_sequencer_proxy_rebuild_finish(SeqIndexBuildContext *context, short sto
IMB_anim_index_rebuild_finish(context->index_context, stop);
}
- seq_free_sequence_recurse(context->scene, context->seq);
+ seq_free_sequence_recurse(NULL, context->seq);
MEM_freeN(context);
}
@@ -2409,8 +2411,9 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
/* opengl offscreen render */
BKE_scene_update_for_newframe(context.bmain, scene, scene->lay);
- ibuf = sequencer_view3d_cb(scene, camera, context.rectx, context.recty,
- IB_rect, context.scene->r.seq_prev_type, TRUE, FALSE, err_out);
+ ibuf = sequencer_view3d_cb(scene, camera, context.rectx, context.recty, IB_rect,
+ context.scene->r.seq_prev_type, context.scene->r.seq_flag & R_SEQ_SOLID_TEX,
+ TRUE, FALSE, err_out);
if (ibuf == NULL) {
fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
}
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 53dfbdcfb85..c9cf5d561e5 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -924,7 +924,8 @@ static void clampBoundsInDomain(SmokeDomainSettings *sds, int min[3], int max[3]
}
}
-static void em_allocateData(EmissionMap *em, int use_velocity) {
+static void em_allocateData(EmissionMap *em, int use_velocity)
+{
int i, res[3];
for (i = 0; i < 3; i++) {
@@ -941,7 +942,8 @@ static void em_allocateData(EmissionMap *em, int use_velocity) {
em->velocity = MEM_callocN(sizeof(float) * em->total_cells * 3, "smoke_flow_velocity");
}
-static void em_freeData(EmissionMap *em) {
+static void em_freeData(EmissionMap *em)
+{
if (em->influence)
MEM_freeN(em->influence);
if (em->velocity)
@@ -2509,7 +2511,8 @@ float smoke_get_velocity_at(struct Object *ob, float position[3], float velocity
return -1.0f;
}
-int smoke_get_data_flags(SmokeDomainSettings *sds) {
+int smoke_get_data_flags(SmokeDomainSettings *sds)
+{
int flags = 0;
if (smoke_has_heat(sds->fluid)) flags |= SM_ACTIVE_HEAT;
if (smoke_has_fuel(sds->fluid)) flags |= SM_ACTIVE_FIRE;
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index 09440591826..f6599cc9648 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -35,7 +35,6 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index f76b480c423..7c58c7b21ed 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -50,8 +50,8 @@
#include "BLI_edgehash.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
-#include "BLI_pbvh.h"
+#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 6d0313f6334..149842bc038 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -42,7 +42,6 @@
#include "BLI_math.h"
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 30b48401046..801fecc9f7c 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -3462,15 +3462,15 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf
BKE_tracking_stabilization_data_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat);
invert_m4(mat);
- if (filter == TRACKING_FILTER_NEAREAST)
- interpolation = neareast_interpolation;
+ if (filter == TRACKING_FILTER_NEAREST)
+ interpolation = nearest_interpolation;
else if (filter == TRACKING_FILTER_BILINEAR)
interpolation = bilinear_interpolation;
else if (filter == TRACKING_FILTER_BICUBIC)
interpolation = bicubic_interpolation;
else
/* fallback to default interpolation method */
- interpolation = neareast_interpolation;
+ interpolation = nearest_interpolation;
for (j = 0; j < tmpibuf->y; j++) {
for (i = 0; i < tmpibuf->x; i++) {
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 4bde895cf7d..ad101c41dc5 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -40,7 +40,6 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 0f861a7ed37..cf2a165c2b2 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -497,8 +497,15 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000;
c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000;
c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024;
+
+#if 0
+ /* this options are not set in ffmpeg.c and leads to artifacts with MPEG-4
+ * see #33586: Encoding to mpeg4 makes first frame(s) blocky
+ */
c->rc_initial_buffer_occupancy = rd->ffcodecdata.rc_buffer_size * 3 / 4;
c->rc_buffer_aggressivity = 1.0;
+#endif
+
c->me_method = ME_EPZS;
codec = avcodec_find_encoder(c->codec_id);