diff options
Diffstat (limited to 'source/blender/blenkernel')
173 files changed, 12690 insertions, 10365 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 9ef4ffe52df..ea5b9e8367f 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -69,17 +69,6 @@ * as it is and stick with using BMesh and CDDM. */ -/* TODO (Probably) - * - * o Make drawMapped* functions take a predicate function that - * determines whether to draw the edge (this predicate can - * also set color, etc). This will be slightly more general - * and allow some of the functions to be collapsed. - * o Once accessor functions are added then single element draw - * functions can be implemented using primitive accessors. - * o Add function to dispatch to renderer instead of using - * conversion to DLM. - */ #include "DNA_customdata_types.h" #include "DNA_meshdata_types.h" @@ -382,7 +371,8 @@ struct DerivedMesh { void (*drawMappedFaces)(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), - void *userData, int useColors); + void *userData, int useColors, + int (*setMaterial)(int, void *attribs)); /* Draw mapped faces using MTFace * o Drawing options too complicated to enumerate, look at code. @@ -606,6 +596,7 @@ DerivedMesh *getEditDerivedBMesh(struct BMEditMesh *em, struct Object *ob, DerivedMesh *mesh_create_derived_index_render(struct Scene *scene, struct Object *ob, CustomDataMask dataMask, int index); /* same as above but wont use render settings */ +DerivedMesh *mesh_create_derived(struct Mesh *me, struct Object *ob, float (*vertCos)[3]); DerivedMesh *mesh_create_derived_view(struct Scene *scene, struct Object *ob, CustomDataMask dataMask); DerivedMesh *mesh_create_derived_no_deform(struct Scene *scene, struct Object *ob, @@ -617,13 +608,18 @@ DerivedMesh *mesh_create_derived_no_deform_render(struct Scene *scene, struct Ob /* for gameengine */ DerivedMesh *mesh_create_derived_no_virtual(struct Scene *scene, struct Object *ob, float (*vertCos)[3], CustomDataMask dataMask); +DerivedMesh *mesh_create_derived_physics(struct Scene *scene, struct Object *ob, float (*vertCos)[3], + CustomDataMask dataMask); +DerivedMesh *editbmesh_get_derived(struct BMEditMesh *em, float (*vertexCos)[3]); DerivedMesh *editbmesh_get_derived_base(struct Object *, struct BMEditMesh *em); DerivedMesh *editbmesh_get_derived_cage(struct Scene *scene, struct Object *, struct BMEditMesh *em, CustomDataMask dataMask); DerivedMesh *editbmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *, struct BMEditMesh *em, DerivedMesh **final_r, CustomDataMask dataMask); +float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *numVerts_r))[3]; +int editbmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm); void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct BMEditMesh *em, CustomDataMask dataMask); /* returns an array of deform matrices for crazyspace correction, and the @@ -631,6 +627,11 @@ void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct BMEditMesh * int editbmesh_get_first_deform_matrices(struct Scene *, struct Object *, struct BMEditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3]); +/* returns an array of deform matrices for crazyspace correction when sculpting, + and the number of modifiers left */ +int sculpt_get_deform_matrices(struct Scene *scene, struct Object *ob, + float (**deformmats)[3][3], float (**deformcos)[3]); + void weight_to_rgb(float input, float *fr, float *fg, float *fb); /* convert layers requested by a GLSL material to actually available layers in @@ -647,7 +648,7 @@ typedef struct DMVertexAttribs { } mcol[MAX_MCOL]; struct { - float (*array)[3]; + float (*array)[4]; int emOffset, glIndex; } tang; diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 4d3f000c863..59da97d8b09 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -1,9 +1,4 @@ -/* BKE_action.h May 2001 - * - * Blender kernel action and pose functionality - * - * Reevan McKay - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -33,6 +28,14 @@ #ifndef BKE_ACTION_H #define BKE_ACTION_H +/** \file BKE_action.h + * \ingroup bke + * \brief Blender kernel action and pose functionality. + * \author Reevan McKay + * \author Ton Roosendaal (full recode 2005) + * \author Joshua Leung (full recode 2009) + * \since may 2001 + */ #include "DNA_listBase.h" @@ -117,6 +120,8 @@ void action_groups_remove_channel(struct bAction *act, struct FCurve *fcu); /* Find a group with the given name */ struct bActionGroup *action_groups_find_named(struct bAction *act, const char name[]); +/* Clear all 'temp' flags on all groups */ +void action_groups_clear_tempflags(struct bAction *act); /* Pose API ----------------- */ diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index e82eb0ed0c9..25165eeaee7 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_anim.h (mar-2001 nzc); - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,11 @@ #ifndef BKE_ANIM_H #define BKE_ANIM_H +/** \file BKE_anim.h + * \ingroup bke + * \author nzc + * \since March 2001 + */ struct Path; struct Object; struct PartEff; diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index af5e31b1efa..a469d05ee26 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -28,6 +28,11 @@ #ifndef BKE_ANIM_SYS_H #define BKE_ANIM_SYS_H +/** \file BKE_animsys.h + * \ingroup bke + * \author Joshua Leung + */ + struct ID; struct ListBase; struct Main; @@ -56,10 +61,13 @@ struct AnimData *BKE_id_add_animdata(struct ID *id); void BKE_free_animdata(struct ID *id); /* Copy AnimData */ -struct AnimData *BKE_copy_animdata(struct AnimData *adt); +struct AnimData *BKE_copy_animdata(struct AnimData *adt, const short do_action); /* Copy AnimData */ -int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from); +int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from, const short do_action); + +/* Copy AnimData Actions */ +void BKE_copy_animdata_id_action(struct ID *id); /* Make Local */ void BKE_animdata_make_local(struct AnimData *adt); @@ -92,11 +100,19 @@ void BKE_keyingsets_free(struct ListBase *list); /* Path Fixing API */ /* Fix all the paths for the given ID+AnimData */ -void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, char *prefix, char *oldName, char *newName, int oldSubscript, int newSubscript, int verify_paths); +void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, const char *prefix, char *oldName, char *newName, int oldSubscript, int newSubscript, int verify_paths); /* Fix all the paths for the entire database... */ void BKE_all_animdata_fix_paths_rename(char *prefix, char *oldName, char *newName); +/* -------------------------------------- */ + +/* Move animation data from src to destination if it's paths are based on basepaths */ +void BKE_animdata_separate_by_basepath(struct ID *srcID, struct ID *dstID, struct ListBase *basepaths); + +/* Move F-Curves from src to destination if it's path is based on basepath */ +void action_move_fcurves_by_basepath(struct bAction *srcAct, struct bAction *dstAct, const char basepath[]); + /* ************************************* */ /* Batch AnimData API */ diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 242de4d788b..efa87532859 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_armature.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,12 @@ #ifndef BKE_ARMATURE_H #define BKE_ARMATURE_H +/** \file BKE_armature.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ + struct Bone; struct Main; struct bArmature; @@ -73,14 +77,14 @@ typedef struct PoseTree extern "C" { #endif -struct bArmature *add_armature(char *name); +struct bArmature *add_armature(const char *name); struct bArmature *get_armature(struct Object *ob); void free_bonelist (struct ListBase *lb); void free_armature(struct bArmature *arm); void make_local_armature(struct bArmature *arm); struct bArmature *copy_armature(struct bArmature *arm); -int bone_autoside_name (char *name, int strip_number, short axis, float head, float tail); +int bone_autoside_name (char name[32], int strip_number, short axis, float head, float tail); struct Bone *get_named_bone (struct bArmature *arm, const char *name); @@ -91,6 +95,7 @@ void where_is_armature_bone(struct Bone *bone, struct Bone *prevbone); void armature_rebuild_pose(struct Object *ob, struct bArmature *arm); void where_is_pose (struct Scene *scene, struct Object *ob); void where_is_pose_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, int do_extra); +void where_is_pose_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); @@ -104,8 +109,10 @@ void armature_mat_pose_to_bone(struct bPoseChannel *pchan, float inmat[][4], flo void armature_loc_pose_to_bone(struct bPoseChannel *pchan, float *inloc, float *outloc); void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float arm_mat[][4]); -void pchan_apply_mat4(struct bPoseChannel *pchan, float mat[][4]); +void pchan_mat3_to_rot(struct bPoseChannel *pchan, float mat[][3], short use_compat); +void pchan_apply_mat4(struct bPoseChannel *pchan, float mat[][4], short use_comat); void pchan_to_mat4(struct bPoseChannel *pchan, float chan_mat[4][4]); +void pchan_calc_mat(struct bPoseChannel *pchan); /* 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); @@ -117,6 +124,10 @@ typedef struct Mat4 { Mat4 *b_bone_spline_setup(struct bPoseChannel *pchan, int rest); +/* like EBONE_VISIBLE */ +#define PBONE_VISIBLE(arm, bone) (((bone)->layer & (arm)->layer) && !((bone)->flag & BONE_HIDDEN_P)) +#define _BONE_VISIBLE(arm, bone) (((bone)->layer & (arm)->layer) && !((bone)->flag & BONE_HIDDEN_P)) + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_array_mallocn.h b/source/blender/blenkernel/BKE_array_mallocn.h new file mode 100644 index 00000000000..42c4c2ebdd0 --- /dev/null +++ b/source/blender/blenkernel/BKE_array_mallocn.h @@ -0,0 +1,87 @@ +/* + * $Id$ + * + * ***** 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): none yet. + * + * ***** END GPL LICENSE BLOCK ***** +*/ + +#ifndef BKE_ARRAY_MALLOCN_H +#define BKE_ARRAY_MALLOCN_H + +/** \file BKE_array_mallocn.h + * \ingroup bke + * \brief little array macro library. + */ + +/* example of usage: + +int *arr = NULL; +V_DECLARE(arr); +int i; + +for (i=0; i<10; i++) { + V_GROW(arr); + arr[i] = something; +} +V_FREE(arr); + +arrays are buffered, using double-buffering (so on each reallocation, +the array size is doubled). supposedly this should give good Big Oh +behaviour, though it may not be the best in practice. +*/ + +#define V_DECLARE(vec) int _##vec##_count=0; void *_##vec##_tmp + +/*in the future, I plan on having V_DECLARE allocate stack memory it'll + use at first, and switch over to heap when it needs more. that'll mess + up cases where you'd want to use this API to build a dynamic list for + non-local use, so all such cases should use this macro.*/ +#define V_DYNDECLARE(vec) V_DECLARE(vec) + +/*this returns the entire size of the array, including any buffering.*/ +#define V_SIZE(vec) ((signed int)((vec)==NULL ? 0 : MEM_allocN_len(vec) / sizeof(*vec))) + +/*this returns the logical size of the array, not including buffering.*/ +#define V_COUNT(vec) _##vec##_count + +/*grow the array by one. zeroes the new elements.*/ +#define V_GROW(vec) \ + V_SIZE(vec) > _##vec##_count ? _##vec##_count++ : \ + ((_##vec##_tmp = MEM_callocN(sizeof(*vec)*(_##vec##_count*2+2), #vec " " __FILE__ " ")),\ + (void)(vec && memcpy(_##vec##_tmp, vec, sizeof(*vec) * _##vec##_count)),\ + (void)(vec && (MEM_freeN(vec),1)),\ + (vec = _##vec##_tmp),\ + _##vec##_count++) + +#define V_FREE(vec) if (vec) MEM_freeN(vec); + +/*resets the logical size of an array to zero, but doesn't + free the memory.*/ +#define V_RESET(vec) _##vec##_count=0 + +/*set the count of the array*/ +#define V_SETCOUNT(vec, count) _##vec##_count = (count) + +#endif // BKE_ARRAY_MALLOCN_H diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 8820edc3adf..44ce6060f1b 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -1,8 +1,4 @@ -/** - * blenlib/BKE_blender.h (mar-2001 nzc) - * - * Blender util stuff? - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -33,10 +29,32 @@ #ifndef BKE_BLENDER_H #define BKE_BLENDER_H +/** \file BKE_blender.h + * \ingroup bke + * \since March 2001 + * \author nzc + * \brief Blender util stuff + */ + #ifdef __cplusplus extern "C" { #endif +/* these lines are grep'd, watch out for our not-so-awesome regex + * and keep comment above the defines. + * Use STRINGIFY() rather then defining with quotes */ +#define BLENDER_VERSION 256 +#define BLENDER_SUBVERSION 2 + +#define BLENDER_MINVERSION 250 +#define BLENDER_MINSUBVERSION 0 + +/* used by packaging tools */ + /* can be left blank, otherwise a,b,c... etc with no quotes */ +#define BLENDER_VERSION_CHAR a + /* alpha/beta/rc/releases */ +#define BLENDER_VERSION_CYCLE beta + struct ListBase; struct MemFile; struct bContext; @@ -44,14 +62,13 @@ struct ReportList; struct Scene; struct Main; -#define BLENDER_VERSION 253 -#define BLENDER_SUBVERSION 1 +int BKE_read_file(struct bContext *C, const char *filepath, struct ReportList *reports); -#define BLENDER_MINVERSION 250 -#define BLENDER_MINSUBVERSION 0 +#define BKE_READ_FILE_FAIL 0 /* no load */ +#define BKE_READ_FILE_OK 1 /* OK */ +#define BKE_READ_FILE_OK_USERPREFS 2 /* OK, and with new user settings */ -int BKE_read_file(struct bContext *C, char *dir, void *type_r, struct ReportList *reports); -int BKE_read_file_from_memory(struct bContext *C, char* filebuf, int filelength, void *type_r, struct ReportList *reports); +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); void free_blender(void); @@ -65,9 +82,10 @@ void set_blender_test_break_cb(void (*func)(void) ); int blender_test_break(void); /* global undo */ -extern void BKE_write_undo(struct bContext *C, char *name); +extern void BKE_write_undo(struct bContext *C, const char *name); extern void BKE_undo_step(struct bContext *C, int step); extern void BKE_undo_name(struct bContext *C, const char *name); +extern int BKE_undo_valid(const char *name); extern void BKE_reset_undo(void); extern char *BKE_undo_menu_string(void); extern void BKE_undo_number(struct bContext *C, int nr); diff --git a/source/blender/blenkernel/BKE_bmesh.h b/source/blender/blenkernel/BKE_bmesh.h index c05a940b0f5..e347f8fe76e 100644 --- a/source/blender/blenkernel/BKE_bmesh.h +++ b/source/blender/blenkernel/BKE_bmesh.h @@ -1,8 +1,4 @@ -/** - * BKE_bmesh.h jan 2007 - * - * (old) BMesh modeler structure and functions. - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -37,7 +33,15 @@ #ifndef BKE_BMESH_H #define BKE_BMESH_H +/** \file BKE_bmesh.h + * \ingroup bke + * \since January 2007 + * \brief BMesh modeler structure and functions. + * + */ + #include "DNA_listBase.h" +#include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_mempool.h" #include "BLI_memarena.h" diff --git a/source/blender/blenkernel/BKE_bmeshCustomData.h b/source/blender/blenkernel/BKE_bmeshCustomData.h index d2b72019b68..aabfcfaa0f6 100644 --- a/source/blender/blenkernel/BKE_bmeshCustomData.h +++ b/source/blender/blenkernel/BKE_bmeshCustomData.h @@ -1,8 +1,4 @@ -/** - * BKE_bmesh.h jan 2007 - * - * BMesh modeler structure and functions. - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -38,6 +34,12 @@ #ifndef BKE_BMESHCUSTOMDATA_H #define BKE_BMESHCUSTOMDATA_H +/** \file BKE_bmeshCustomData.h + * \ingroup bke + * \since January 2007 + * \brief BMesh modeler structure and functions - custom data. + */ + struct BLI_mempool; /*Custom Data Types and defines diff --git a/source/blender/blenkernel/BKE_bmfont.h b/source/blender/blenkernel/BKE_bmfont.h index 6a47dcbd6c4..ef7323fc4c3 100644 --- a/source/blender/blenkernel/BKE_bmfont.h +++ b/source/blender/blenkernel/BKE_bmfont.h @@ -1,8 +1,4 @@ -/** - * blenlib/BKE_bmfont.h (mar-2001 nzc) - * - * - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -33,6 +29,12 @@ #ifndef BKE_BMFONT_H #define BKE_BMFONT_H +/** \file BKE_bmfont.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/blenkernel/BKE_bmfont_types.h b/source/blender/blenkernel/BKE_bmfont_types.h index 77a618c1be4..658302e9f1d 100644 --- a/source/blender/blenkernel/BKE_bmfont_types.h +++ b/source/blender/blenkernel/BKE_bmfont_types.h @@ -1,8 +1,4 @@ -/** - * blenlib/BKE_bmfont_types.h (mar-2001 nzc) - * - * - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -33,6 +29,11 @@ #ifndef BKE_BMFONT_TYPES_H #define BKE_BMFONT_TYPES_H +/** \file BKE_bmfont_types.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ #define is_power_of_two(N) ((N ^ (N - 1)) == (2 * N - 1)) /* Moved to IMB_imbuf_types.h where it will live close to the ImBuf type. diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h index ffd803f21a5..36ca0cde87d 100644 --- a/source/blender/blenkernel/BKE_boids.h +++ b/source/blender/blenkernel/BKE_boids.h @@ -1,6 +1,4 @@ -/* BKE_particle.h - * - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -32,6 +30,12 @@ #ifndef BKE_BOIDS_H #define BKE_BOIDS_H +/** \file BKE_boids.h + * \ingroup bke + * \since 2009 + * \author Janne Karhu + */ + #include "DNA_boid_types.h" typedef struct BoidBrainData { diff --git a/source/blender/blenkernel/BKE_booleanops_mesh.h b/source/blender/blenkernel/BKE_booleanops_mesh.h index 7c2d619659a..aecd3385662 100644 --- a/source/blender/blenkernel/BKE_booleanops_mesh.h +++ b/source/blender/blenkernel/BKE_booleanops_mesh.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -29,6 +29,10 @@ #ifndef BKE_PyBooleanOps_h #define BKE_PyBooleanOps_h +/** \file BKE_booleanops_mesh.h + * \ingroup bke + */ + #include "CSG_BooleanOps.h" /** diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 0e406a16d0c..a9d379e6c69 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,12 +31,16 @@ #ifndef BKE_BRUSH_H #define BKE_BRUSH_H +/** \file BKE_brush.h + * \ingroup bke + */ + struct ID; struct Brush; struct ImBuf; struct Scene; struct wmOperator; -enum CurveMappingPreset; +// enum CurveMappingPreset; /* datablock functions */ struct Brush *add_brush(const char *name); @@ -56,13 +60,16 @@ int brush_texture_delete(struct Brush *brush); int brush_clone_image_set_nr(struct Brush *brush, int nr); int brush_clone_image_delete(struct Brush *brush); +/* jitter */ +void brush_jitter_pos(struct Brush *brush, float *pos, float *jitterpos); + /* brush curve */ void brush_curve_preset(struct Brush *b, /*enum CurveMappingPreset*/int preset); float brush_curve_strength_clamp(struct Brush *br, float p, const float len); float brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */ /* sampling */ -void brush_sample_tex(struct Brush *brush, float *xy, float *rgba); +void brush_sample_tex(struct Brush *brush, float *xy, float *rgba, const int thread); void brush_imbuf_new(struct Brush *brush, short flt, short texfalloff, int size, struct ImBuf **imbuf); @@ -106,5 +113,8 @@ void brush_set_unprojected_radius(struct Brush *brush, float value); float brush_alpha(struct Brush *brush); void brush_set_alpha(struct Brush *brush, float value); +/* debugging only */ +void brush_debug_print_state(struct Brush *br); + #endif diff --git a/source/blender/blenkernel/BKE_bullet.h b/source/blender/blenkernel/BKE_bullet.h index b695bdc91ae..76358c4485b 100644 --- a/source/blender/blenkernel/BKE_bullet.h +++ b/source/blender/blenkernel/BKE_bullet.h @@ -1,4 +1,4 @@ -/** +/* * * $Id$ * @@ -30,6 +30,10 @@ #ifndef BKE_BULLET_H #define BKE_BULLET_H +/** \file BKE_bullet.h + * \ingroup bke + */ + struct BulletSoftBody; diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 5a1db432589..29487713ad4 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -1,5 +1,4 @@ -/** - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -30,6 +29,10 @@ #ifndef BKE_BVHUTILS_H #define BKE_BVHUTILS_H +/** \file BKE_bvhutils.h + * \ingroup bke + */ + #include "BLI_kdopbvh.h" #include "BLI_linklist.h" @@ -65,6 +68,7 @@ typedef struct BVHTreeFromMesh /* Private data */ int cached; + void *em_evil; /* var only for snapping */ } BVHTreeFromMesh; diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 1d65d254ae6..c1161e7c65b 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -27,9 +27,11 @@ * ***** END GPL LICENSE BLOCK ***** */ -/* CDDerivedMesh interface. - * CDDerivedMesh (CD = Custom Data) is a DerivedMesh backend which stores - * mesh elements (vertices, edges and faces) as layers of custom element data. +/** \file BKE_cdderivedmesh.h + * \ingroup bke + * \section aboutcdderivedmesh CDDerivedMesh interface + * CDDerivedMesh (CD = Custom Data) is a DerivedMesh backend which stores + * mesh elements (vertices, edges and faces) as layers of custom element data. */ #ifndef BKE_CDDERIVEDMESH_H @@ -114,6 +116,9 @@ void CDDM_calc_edges(struct DerivedMesh *dm); faces*/ void CDDM_calc_edges_poly(struct DerivedMesh *dm); +/*reconstitute face triangulation*/ +void CDDM_recalc_tesselation(struct DerivedMesh *dm); + /* lowers the number of vertices/edges/faces in a CDDerivedMesh * the layer data stays the same size */ @@ -140,7 +145,7 @@ struct MVert *CDDM_get_verts(struct DerivedMesh *dm); struct MEdge *CDDM_get_edges(struct DerivedMesh *dm); struct MFace *CDDM_get_tessfaces(struct DerivedMesh *dm); struct MLoop *CDDM_get_loops(struct DerivedMesh *dm); -struct MPoly *CDDM_get_faces(struct DerivedMesh *dm); +struct MPoly *CDDM_get_polys(struct DerivedMesh *dm); /*Assigns news m*** layers to the cddm. Note that you must handle freeing the old ones yourself. Also you must ensure dm->num****Data diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 034bedbb07d..1ee51cd2122 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -1,6 +1,4 @@ -/** - * BKE_cloth.h - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,11 @@ #ifndef BKE_CLOTH_H #define BKE_CLOTH_H +/** \file BKE_cloth.h + * \ingroup bke + * \author Daniel Genrich + */ + #include <float.h> struct Object; @@ -220,9 +223,9 @@ void clmdSetInterruptCallBack ( int ( *f ) ( void ) ); // needed for modifier.c void cloth_free_modifier_extern ( struct ClothModifierData *clmd ); -void cloth_free_modifier ( struct Object *ob, struct ClothModifierData *clmd ); +void cloth_free_modifier ( struct ClothModifierData *clmd ); void cloth_init ( struct ClothModifierData *clmd ); -struct DerivedMesh *clothModifier_do ( struct ClothModifierData *clmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, int useRenderParams, int isFinalCalc ); +struct DerivedMesh *clothModifier_do ( struct ClothModifierData *clmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm); void cloth_update_normals ( ClothVertex *verts, int nVerts, struct MFace *face, int totface ); int cloth_uses_vgroup(struct ClothModifierData *clmd); @@ -252,7 +255,7 @@ typedef enum */ typedef struct { - char *name; + const char *name; CM_SOLVER_ID id; int ( *init ) ( struct Object *ob, struct ClothModifierData *clmd ); int ( *solver ) ( struct Object *ob, float framenr, struct ClothModifierData *clmd, struct ListBase *effectors ); diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index d7ae7df9342..b54d4275719 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -1,6 +1,4 @@ -/** - * BKE_cloth.h - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,11 @@ #ifndef BKE_COLLISIONS_H #define BKE_COLLISIONS_H +/** \file BKE_collision.h + * \ingroup bke + * \author Daniel Genrich + */ + #include <math.h> #include <float.h> #include <stdlib.h> @@ -136,7 +139,7 @@ void interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], ///////////////////////////////////////////////// // used in effect.c ///////////////////////////////////////////////// -struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, int *numcollobj); +struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj); typedef struct ColliderCache { struct ColliderCache *next, *prev; diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index e0ebedb320b..b3709853a8c 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -29,6 +29,10 @@ #ifndef BKE_COLORTOOLS_H #define BKE_COLORTOOLS_H +/** \file BKE_colortools.h + * \ingroup bke + */ + struct CurveMapping; struct CurveMap; struct Scopes; diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index d6e0075df1e..7c0e7050a9f 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -30,6 +30,11 @@ #ifndef BKE_CONSTRAINT_H #define BKE_CONSTRAINT_H +/** \file BKE_constraint.h + * \ingroup bke + * \author Joshua Leung (major recode 2007) + */ + struct ID; struct bConstraint; struct bConstraintTarget; diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 76a585fba04..36c442741ec 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -28,13 +28,17 @@ #ifndef BKE_CONTEXT_H #define BKE_CONTEXT_H -#ifdef __cplusplus -extern "C" { -#endif +/** \file BKE_context.h + * \ingroup bke + */ #include "DNA_listBase.h" #include "RNA_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct ARegion; struct bScreen; struct EditMesh; @@ -114,7 +118,7 @@ bContext *CTX_copy(const bContext *C); /* Stored Context */ -bContextStore *CTX_store_add(ListBase *contexts, char *name, PointerRNA *ptr); +bContextStore *CTX_store_add(ListBase *contexts, const char *name, PointerRNA *ptr); void CTX_store_set(bContext *C, bContextStore *store); bContextStore *CTX_store_copy(bContextStore *store); void CTX_store_free(bContextStore *store); @@ -124,7 +128,7 @@ void CTX_store_free_list(ListBase *contexts); int CTX_py_init_get(bContext *C); void CTX_py_init_set(bContext *C, int value); -void *CTX_py_dict_get(bContext *C); +void *CTX_py_dict_get(const bContext *C); void CTX_py_dict_set(bContext *C, void *value); /* Window Manager Context */ @@ -163,6 +167,8 @@ void CTX_wm_screen_set(bContext *C, struct bScreen *screen); /* to be removed */ void CTX_wm_area_set(bContext *C, struct ScrArea *sa); void CTX_wm_region_set(bContext *C, struct ARegion *region); void CTX_wm_menu_set(bContext *C, struct ARegion *menu); +const char *CTX_wm_operator_poll_msg_get(struct bContext *C); +void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg); /* Data Context @@ -223,7 +229,7 @@ struct Main *CTX_data_main(const bContext *C); struct Scene *CTX_data_scene(const bContext *C); struct ToolSettings *CTX_data_tool_settings(const bContext *C); -char *CTX_data_mode_string(const bContext *C); +const char *CTX_data_mode_string(const bContext *C); int CTX_data_mode_enum(const bContext *C); void CTX_data_main_set(bContext *C, struct Main *bmain); diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index db6d995aa74..f0c58e0a511 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_curve.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,11 @@ #ifndef BKE_CURVE_H #define BKE_CURVE_H +/** \file BKE_curve.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ struct Curve; struct ListBase; struct Object; @@ -54,7 +57,7 @@ struct BevList; void unlink_curve( struct Curve *cu); void free_curve( struct Curve *cu); void BKE_free_editfont(struct Curve *cu); -struct Curve *add_curve(char *name, int type); +struct Curve *add_curve(const char *name, int type); struct Curve *copy_curve( struct Curve *cu); void make_local_curve( struct Curve *cu); short curve_type( struct Curve *cu); @@ -69,9 +72,10 @@ void duplicateNurblist( struct ListBase *lb1, struct ListBase *lb2); void test2DNurb( struct Nurb *nu); void minmaxNurb( struct Nurb *nu, float *min, float *max); -void makeknots( struct Nurb *nu, short uv); +void nurbs_knot_calc_u(struct Nurb *nu); +void nurbs_knot_calc_v(struct Nurb *nu); -void makeNurbfaces(struct Nurb *nu, float *coord_array, int rowstride); +void makeNurbfaces(struct Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv); void makeNurbcurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride); void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); float *make_orco_curve(struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 7e59aa5ac8e..319519cf363 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -27,11 +27,19 @@ * ***** END GPL LICENSE BLOCK ***** */ -/* CustomData interface, see also DNA_customdata_types.h. */ +/** \file BKE_customdata.h + * \ingroup bke + * \author Ben Batt + * \brief CustomData interface, see also DNA_customdata_types.h. + */ #ifndef BKE_CUSTOMDATA_H #define BKE_CUSTOMDATA_H +#ifdef __cplusplus +extern "C" { +#endif + struct BMesh; struct ID; struct CustomData; @@ -146,7 +154,7 @@ int CustomData_number_of_layers(const struct CustomData *data, int type); * returns the layer data */ void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type); void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, - int type, char *name); + int type, const char *name); /* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is * zero for the layer type, so only layer types specified by the mask @@ -170,6 +178,7 @@ void CustomData_em_copy_data(const struct CustomData *source, void CustomData_bmesh_copy_data(const struct CustomData *source, struct CustomData *dest, void *src_block, void **dest_block); +void CustomData_em_validate_data(struct CustomData *data, void *block, int sub_elements); /* frees data in a CustomData object * return 1 on success, 0 on failure @@ -226,10 +235,10 @@ void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, i void *CustomData_get_layer(const struct CustomData *data, int type); void *CustomData_get_layer_n(const struct CustomData *data, int type, int n); void *CustomData_get_layer_named(const struct CustomData *data, int type, - char *name); + const char *name); int CustomData_get_layer_index(const struct CustomData *data, int type); int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n); -int CustomData_get_named_layer_index(const struct CustomData *data, int type, char *name); +int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name); int CustomData_get_active_layer_index(const struct CustomData *data, int type); int CustomData_get_render_layer_index(const struct CustomData *data, int type); int CustomData_get_clone_layer_index(const struct CustomData *data, int type); @@ -302,7 +311,7 @@ void CustomData_from_bmesh_block(const struct CustomData *source, /* query info over types */ -void CustomData_file_write_info(int type, char **structname, int *structnum); +void CustomData_file_write_info(int type, const char **structname, int *structnum); int CustomData_sizeof(int type); /* get the name of a layer type */ @@ -336,5 +345,9 @@ void CustomData_external_read(struct CustomData *data, void CustomData_external_reload(struct CustomData *data, struct ID *id, CustomDataMask mask, int totelem); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/blenkernel/BKE_customdata_file.h b/source/blender/blenkernel/BKE_customdata_file.h index 9bcef7636c6..f97565f23a1 100644 --- a/source/blender/blenkernel/BKE_customdata_file.h +++ b/source/blender/blenkernel/BKE_customdata_file.h @@ -23,6 +23,10 @@ #ifndef BKE_CUSTOMDATA_FILE_H #define BKE_CUSTOMDATA_FILE_H +/** \file BKE_customdata_file.h + * \ingroup bke + */ + #define CDF_TYPE_IMAGE 0 #define CDF_TYPE_MESH 1 diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 53f474aa972..a9ac201beda 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -1,9 +1,4 @@ -/* BKE_deform.h June 2001 - * - * support for deformation groups and hooks - * - * Reevan McKay et al - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -35,6 +30,13 @@ #ifndef BKE_DEFORM_H #define BKE_DEFORM_H +/** \file BKE_deform.h + * \ingroup bke + * \since June 2001 + * \author Reevan McKay et al + * \brief support for deformation groups and hooks. + */ + struct Object; struct ListBase; struct bDeformGroup; @@ -49,10 +51,10 @@ int defgroup_flip_index(struct Object *ob, int index, int use_default); int defgroup_name_index(struct Object *ob, const char *name); void defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob); -struct MDeformWeight *defvert_find_index(const struct MDeformVert *dv, int defgroup); -struct MDeformWeight *defvert_verify_index(struct MDeformVert *dv, int defgroup); +struct MDeformWeight *defvert_find_index(const struct MDeformVert *dv, const int defgroup); +struct MDeformWeight *defvert_verify_index(struct MDeformVert *dv, const int defgroup); -float defvert_find_weight(const struct MDeformVert *dvert, int group_num); +float defvert_find_weight(const struct MDeformVert *dvert, const int group_num); float defvert_array_find_weight_safe(const struct MDeformVert *dvert, int index, int group_num); void defvert_copy(struct MDeformVert *dvert_r, const struct MDeformVert *dvert); @@ -64,7 +66,7 @@ void defvert_normalize(struct MDeformVert *dvert); /* utility function, note that 32 chars is the maximum string length since its only * used with defgroups currently */ -void flip_side_name(char *name, const char *from_name, int strip_number); +void flip_side_name(char name[32], const char from_name[32], int strip_number); #endif diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index 0b78a1206fe..f78a957cbab 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -28,6 +28,14 @@ #ifndef DEPSGRAPH_API #define DEPSGRAPH_API +/** \file BKE_depsgraph.h + * \ingroup bke + */ + +#ifdef __cplusplus +extern "C" { +#endif + /* #define DEPS_DEBUG */ @@ -100,25 +108,28 @@ void draw_all_deps(void); void DAG_scene_sort(struct Main *bmain, struct Scene *sce); /* flag all objects that need recalc because they're animated */ -void DAG_scene_update_flags(struct Main *bmain, struct Scene *sce, unsigned int lay); +void DAG_scene_update_flags(struct Main *bmain, struct Scene *sce, unsigned int lay, const short do_time); /* flushes all recalc flags in objects down the dependency tree */ -void DAG_scene_flush_update(struct Main *bmain, struct Scene *sce, unsigned int lay, int time); +void DAG_scene_flush_update(struct Main *bmain, struct Scene *sce, unsigned int lay, const short do_time); /* tag objects for update on file load */ -void DAG_on_load_update(struct Main *bmain); - - /* flag all IDs that need recalc because they're animated, influencing - this ID only. only for objects currently */ -void DAG_id_update_flags(struct ID *id); - /* flushes all recalc flags for this object down the dependency tree, - but note the DAG only supports objects and object data currently */ -void DAG_id_flush_update(struct ID *id, short flag); +void DAG_on_load_update(struct Main *bmain, const short do_time); + /* when setting manual RECALC flags, call this afterwards */ void DAG_ids_flush_update(struct Main *bmain, int time); + /* tag datablock to get updated for the next redraw */ +void DAG_id_tag_update(struct ID *id, short flag); + /* flush all tagged updates */ +void DAG_ids_flush_tagged(struct Main *bmain); + /* (re)-create dependency graph for armature pose */ void DAG_pose_sort(struct Object *ob); /* callback for editors module to do updates */ void DAG_editors_update_cb(void (*func)(struct Main *bmain, struct ID *id)); + +#ifdef __cplusplus +} +#endif #endif diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 01d3de1b94f..68745975dae 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -1,4 +1,3 @@ -/* display list (or rather multi purpose list) stuff */ /* $Id$ * @@ -32,6 +31,10 @@ #ifndef BKE_DISPLIST_H #define BKE_DISPLIST_H +/** \file BKE_displist.h + * \ingroup bke + * \brief display list (or rather multi purpose list) stuff. + */ #include "DNA_customdata_types.h" #include "BKE_customdata.h" @@ -98,7 +101,6 @@ extern void shadeDispList(struct Scene *scene, struct Base *base); extern void shadeMeshMCol(struct Scene *scene, struct Object *ob, struct Mesh *me); int surfindex_displist(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4); -void imagestodisplist(void); void reshadeall_displist(struct Scene *scene); void filldisplist(struct ListBase *dispbase, struct ListBase *to, int flipnormal); diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 99f55200eac..97ac711651b 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_effect.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,11 @@ #ifndef BKE_EFFECT_H #define BKE_EFFECT_H +/** \file BKE_effect.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ #include "DNA_modifier_types.h" struct Object; diff --git a/source/blender/blenkernel/BKE_endian.h b/source/blender/blenkernel/BKE_endian.h index d61b81fb6ce..5647645e990 100644 --- a/source/blender/blenkernel/BKE_endian.h +++ b/source/blender/blenkernel/BKE_endian.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -26,11 +26,17 @@ * * ***** END GPL LICENSE BLOCK ***** * Are we little or big endian? From Harbison&Steele. - * BKE_ENDIANNESS(a) returns 1 if big endian and returns 0 if little endian */ #ifndef BKE_ENDIAN_H #define BKE_ENDIAN_H +/** \file BKE_endian.h + * \ingroup bke + */ + +/** + * BKE_ENDIANNESS(a) returns 1 if big endian and returns 0 if little endian + */ #define BKE_ENDIANNESS(a) { \ union { \ intptr_t l; \ diff --git a/source/blender/blenkernel/BKE_exotic.h b/source/blender/blenkernel/BKE_exotic.h index bd5af66c6a8..870dd7cb4d5 100644 --- a/source/blender/blenkernel/BKE_exotic.h +++ b/source/blender/blenkernel/BKE_exotic.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -25,28 +25,35 @@ * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** - * dxf/vrml/stl external file io function prototypes */ #ifndef BKE_EXOTIC_H #define BKE_EXOTIC_H +/** \file BKE_exotic.h + * \ingroup bke + * \brief dxf/vrml/stl external file io function prototypes. + * \attention is this used still? Candidate for removal? + */ struct Mesh; struct Scene; -void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a); -unsigned int *mcol_to_vcol(struct Mesh *me); // used in py_main.c - /** * Reads all 3D fileformats other than Blender fileformat * @retval 0 The file could not be read. * @retval 1 The file was read succesfully. * @attention Used in filesel.c */ -int BKE_read_exotic(struct Scene *scene, char *name); +int BKE_read_exotic(struct Scene *scene, const char *name); + +/* return codes */ +#define BKE_READ_EXOTIC_FAIL_PATH -3 /* file format is not supported */ +#define BKE_READ_EXOTIC_FAIL_FORMAT -2 /* file format is not supported */ +#define BKE_READ_EXOTIC_FAIL_OPEN -1 /* Can't open the file */ +#define BKE_READ_EXOTIC_OK_BLEND 0 /* .blend file */ +#define BKE_READ_EXOTIC_OK_OTHER 1 /* other supported formats */ void write_dxf(struct Scene *scene, char *str); -void write_vrml(struct Scene *scene, char *str); void write_stl(struct Scene *scene, char *str); #endif diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 95e0cfc3a91..f81acf4b11e 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -28,6 +28,16 @@ #ifndef BKE_FCURVE_H #define BKE_FCURVE_H +/** \file BKE_fcurve.h + * \ingroup bke + * \author Joshua Leung + * \since 2009 + */ + +#ifdef __cplusplus +extern "C" { +#endif + struct FCurve; struct FModifier; struct ChannelDriver; @@ -136,7 +146,7 @@ typedef enum eFMI_Action_Types { /* modifier only modifies the values of points (but times stay the same) */ FMI_TYPE_REPLACE_VALUES, /* modifier generates a curve regardless of what came before */ - FMI_TYPE_GENERATE_CURVE, + FMI_TYPE_GENERATE_CURVE } eFMI_Action_Types; /* Flags for the requirements of a FModifier Type */ @@ -148,7 +158,7 @@ typedef enum eFMI_Requirement_Flags { */ FMI_REQUIRES_NOTHING = (1<<1), /* refer to modifier instance */ - FMI_REQUIRES_RUNTIME_CHECK = (1<<2), + FMI_REQUIRES_RUNTIME_CHECK = (1<<2) } eFMI_Requirement_Flags; /* Function Prototypes for FModifierTypeInfo's */ @@ -189,7 +199,7 @@ struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int struct FCurve *iter_step_fcurve (struct FCurve *fcu_iter, const char rna_path[]); /* high level function to get an fcurve from C without having the rna */ -struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, char *prop_name, int index); +struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, const char *prop_name, int index); /* Get list of LinkData's containing pointers to the F-Curves which control the types of data indicated * e.g. numMatches = list_find_data_fcurves(matches, &act->curves, "pose.bones[", "MyFancyBone"); @@ -210,6 +220,14 @@ void calc_fcurve_range(struct FCurve *fcu, float *min, float *max); /* get the bounding-box extents for F-Curve */ void calc_fcurve_bounds(struct FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax); +/* .............. */ + +/* Are keyframes on F-Curve of any use (to final result, and to show in editors)? */ +short fcurve_are_keyframes_usable(struct FCurve *fcu); + +/* Can keyframes be added to F-Curve? */ +short fcurve_is_keyframable(struct FCurve *fcu); + /* -------- Curve Sanity -------- */ void calchandles_fcurve(struct FCurve *fcu); @@ -248,4 +266,8 @@ float fcurve_samplingcb_evalcurve(struct FCurve *fcu, void *data, float evaltime */ void fcurve_store_samples(struct FCurve *fcu, void *data, int start, int end, FcuSampleFunc sample_cb); +#ifdef __cplusplus +} +#endif + #endif /* BKE_FCURVE_H*/ diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h index e730f4ec34c..f6070cd81f0 100644 --- a/source/blender/blenkernel/BKE_fluidsim.h +++ b/source/blender/blenkernel/BKE_fluidsim.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -30,6 +30,9 @@ #ifndef BKE_FLUIDSIM_H #define BKE_FLUIDSIM_H +/** \file BKE_fluidsim.h + * \ingroup bke + */ struct Object; struct Scene; diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index 10811c0776d..7f4e7c208f6 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_vfont.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,10 @@ #ifndef BKE_VFONT_H #define BKE_VFONT_H +/** \file BKE_font.h + * \ingroup bke + */ + #ifdef __cplusplus extern "C" { #endif @@ -75,7 +77,7 @@ void BKE_font_register_builtin(void *mem, int size); void free_vfont(struct VFont *sc); void free_ttfont(void); struct VFont *get_builtin_font(void); -struct VFont *load_vfont(char *name); +struct VFont *load_vfont(const char *name); struct TmpFont *vfont_find_tmpfont(struct VFont *vfont); struct chartrans *BKE_text_to_curve(struct Scene *scene, struct Object *ob, int mode); diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 6a602339e11..d83e0e5bc4c 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -1,10 +1,4 @@ -/** - * blenlib/BKE_global.h (mar-2001 nzc) - * - * Global settings, handles, pointers. This is the root for finding - * any data in Blender. This block is not serialized, but built anew - * for every fresh Blender run. - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -35,6 +29,15 @@ #ifndef BKE_GLOBAL_H #define BKE_GLOBAL_H +/** \file BKE_global.h + * \ingroup bke + * \since March 2001 + * \author nzc + * \section aboutglobal Global settings + * Global settings, handles, pointers. This is the root for finding + * any data in Blender. This block is not serialized, but built anew + * for every fresh Blender run. + */ #include "DNA_listBase.h" #ifdef __cplusplus @@ -52,16 +55,17 @@ typedef struct Global { struct Main *main; /* strings: lastsaved */ - char ima[256], sce[256], lib[256]; + char ima[256], lib[256]; - /* flag: if != 0 G.sce contains valid relative base path */ + /* flag: if != 0 G.main->name contains valid relative base path */ int relbase_valid; /* strings of recent opend files */ struct ListBase recent_files; short afbreek, moving, file_loaded; - short background; + char background; + char factory_startup; short winpos, displaymode; /* used to be in Render */ short rendering; /* to indicate render is busy, prevent renderwindow events etc */ @@ -91,10 +95,6 @@ typedef struct Global { /* ndof device found ? */ int ndofdevice; - - /* confusing... G.f and G.flags */ - int flags; - } Global; /* **************** GLOBAL ********************* */ @@ -125,17 +125,17 @@ typedef struct Global { #define G_FILE_ENABLE_ALL_FRAMES (1 << 3) /* deprecated */ #define G_FILE_SHOW_DEBUG_PROPS (1 << 4) /* deprecated */ #define G_FILE_SHOW_FRAMERATE (1 << 5) /* deprecated */ -#define G_FILE_SHOW_PROFILE (1 << 6) /* deprecated */ +/* #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) +/* #define G_FILE_PUBLISH (1 << 9) */ /* deprecated */ #define G_FILE_NO_UI (1 << 10) -#define G_FILE_GAME_TO_IPO (1 << 11) /* deprecated */ +/* #define G_FILE_GAME_TO_IPO (1 << 11) */ /* deprecated */ #define G_FILE_GAME_MAT (1 << 12) /* deprecated */ -#define G_FILE_DISPLAY_LISTS (1 << 13) /* deprecated */ +/* #define G_FILE_DISPLAY_LISTS (1 << 13) */ /* deprecated */ #define G_FILE_SHOW_PHYSICS (1 << 14) /* deprecated */ #define G_FILE_GAME_MAT_GLSL (1 << 15) /* deprecated */ -#define G_FILE_GLSL_NO_LIGHTS (1 << 16) /* deprecated */ +/* #define G_FILE_GLSL_NO_LIGHTS (1 << 16) */ /* deprecated */ #define G_FILE_GLSL_NO_SHADERS (1 << 17) /* deprecated */ #define G_FILE_GLSL_NO_SHADOWS (1 << 18) /* deprecated */ #define G_FILE_GLSL_NO_RAMPS (1 << 19) /* deprecated */ diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 65bcb54408b..4898bb28c8d 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -28,6 +28,11 @@ #ifndef BKE_GPENCIL_H #define BKE_GPENCIL_H +/** \file BKE_gpencil.h + * \ingroup bke + * \author Joshua Leung + */ + struct ListBase; struct bGPdata; struct bGPDlayer; @@ -42,7 +47,7 @@ void free_gpencil_data(struct bGPdata *gpd); struct bGPDframe *gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe); struct bGPDlayer *gpencil_layer_addnew(struct bGPdata *gpd); -struct bGPdata *gpencil_data_addnew(char name[]); +struct bGPdata *gpencil_data_addnew(const char name[]); struct bGPDframe *gpencil_frame_duplicate(struct bGPDframe *src); struct bGPDlayer *gpencil_layer_duplicate(struct bGPDlayer *src); diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index e63e3c93f1e..e497f43e46d 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_group.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,12 @@ #ifndef BKE_GROUP_H #define BKE_GROUP_H +/** \file BKE_group.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ + struct Base; struct Group; struct GroupObject; @@ -40,7 +44,7 @@ struct Scene; void free_group_objects(struct Group *group); void unlink_group(struct Group *group); -struct Group *add_group(char *name); +struct Group *add_group(const char *name); struct Group *copy_group(struct Group *group); int add_to_group(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); int rem_from_group(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 252191803f2..5404402718d 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +31,10 @@ #ifndef BKE_ICONS_H #define BKE_ICONS_H +/** \file BKE_icons.h + * \ingroup bke + */ + /* Resizable Icons for Blender */ @@ -68,7 +72,7 @@ void BKE_icon_delete(struct ID* id); void BKE_icon_changed(int icon_id); /* free all icons */ -void BKE_icons_free(); +void BKE_icons_free(void); /* free the preview image */ void BKE_previewimg_free(struct PreviewImage **prv); @@ -77,7 +81,7 @@ void BKE_previewimg_free(struct PreviewImage **prv); void BKE_previewimg_free_id(ID *id); /* create a new preview image */ -struct PreviewImage* BKE_previewimg_create() ; +struct PreviewImage* BKE_previewimg_create(void) ; /* create a copy of the preview image */ struct PreviewImage* BKE_previewimg_copy(struct PreviewImage *prv); diff --git a/source/blender/blenkernel/BKE_idcode.h b/source/blender/blenkernel/BKE_idcode.h index 364345a3610..1b2b3d2ee95 100755 --- a/source/blender/blenkernel/BKE_idcode.h +++ b/source/blender/blenkernel/BKE_idcode.h @@ -1,5 +1,5 @@ -/** - * $Id: BKE_idcode.h 31221 2010-08-10 20:33:15Z gsrb3d $ +/* + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -30,6 +30,10 @@ #ifndef BKE_ID_INFO_H #define BKE_ID_INFO_H +/** \file BKE_idcode.h + * \ingroup bke + */ + /** * Convert an idcode into a name. * diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 0e0d76f4284..e71ad5c8a24 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -28,12 +28,17 @@ #ifndef _BKE_IDPROP_H #define _BKE_IDPROP_H +/** \file BKE_idprop.h + * \ingroup bke + * \author Joseph Eagar + */ + #include "DNA_ID.h" struct IDProperty; struct ID; -typedef union { +typedef union IDPropertyTemplate { int i; float f; double d; @@ -72,8 +77,8 @@ void IDP_UnlinkArray(struct IDProperty *prop); /* ---------- String Type ------------ */ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen);/* maxlen excludes '\0' */ -void IDP_AssignString(struct IDProperty *prop, char *st, int maxlen); /* maxlen excludes '\0' */ -void IDP_ConcatStringC(struct IDProperty *prop, char *st); +void IDP_AssignString(struct IDProperty *prop, const char *st, int maxlen); /* maxlen excludes '\0' */ +void IDP_ConcatStringC(struct IDProperty *prop, const char *st); void IDP_ConcatString(struct IDProperty *str1, struct IDProperty *append); void IDP_FreeString(struct IDProperty *prop); @@ -127,6 +132,8 @@ int IDP_InsertToGroup(struct IDProperty *group, struct IDProperty *previous, void IDP_RemFromGroup(struct IDProperty *group, struct IDProperty *prop); IDProperty *IDP_GetPropertyFromGroup(struct IDProperty *prop, const char *name); +/* same as above but ensure type match */ +IDProperty *IDP_GetPropertyTypeFromGroup(struct IDProperty *prop, const char *name, const char type); /*Get an iterator to iterate over the members of an id property group. Note that this will automatically free the iterator once iteration is complete; diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index c842efaa3b2..8f0ce8c1660 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_image.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,12 @@ #ifndef BKE_IMAGE_H #define BKE_IMAGE_H +/** \file BKE_image.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ + #ifdef __cplusplus extern "C" { #endif @@ -46,9 +50,10 @@ void free_image(struct Image *me); void BKE_stamp_info(struct Scene *scene, struct ImBuf *ibuf); void BKE_stamp_buf(struct Scene *scene, unsigned char *rect, float *rectf, int width, int height, int channels); -int BKE_write_ibuf(struct Scene *scene, struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality); -void BKE_makepicstring(char *string, char *base, int frame, int imtype, int use_ext); -void BKE_add_image_extension(char *string, int imtype); +int BKE_alphatest_ibuf(struct ImBuf *ibuf); +int BKE_write_ibuf(struct Scene *scene, struct ImBuf *ibuf, const char *name, int imtype, int subimtype, int quality); +void BKE_makepicstring(char *string, const char *base, int frame, int imtype, const short use_ext, const short use_frames); +int BKE_add_image_extension(char *string, int imtype); int BKE_ftype_to_imtype(int ftype); int BKE_imtype_to_ftype(int imtype); int BKE_imtype_is_movie(int imtype); @@ -93,10 +98,6 @@ struct RenderResult; /* reload only frees, doesn't read until image_get_ibuf() called */ #define IMA_SIGNAL_RELOAD 0 #define IMA_SIGNAL_FREE 1 - /* pack signals are executed */ -#define IMA_SIGNAL_PACK 2 -#define IMA_SIGNAL_REPACK 3 -#define IMA_SIGNAL_UNPACK 4 /* source changes, from image to sequence or movie, etc */ #define IMA_SIGNAL_SRC_CHANGE 5 /* image-user gets a new image, check settings */ @@ -112,10 +113,10 @@ struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void BKE_image_release_ibuf(struct Image *ima, void *lock); /* returns existing Image when filename/type is same (frame optional) */ -struct Image *BKE_add_image_file(const char *name, int frame); +struct Image *BKE_add_image_file(const char *name); /* adds image, adds ibuf, generates color or pattern */ -struct Image *BKE_add_image_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]); +struct Image *BKE_add_image_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short uvtestgrid, float color[4]); /* adds image from imbuf, owns imbuf */ struct Image *BKE_add_image_imbuf(struct ImBuf *ibuf); diff --git a/source/blender/blenkernel/BKE_ipo.h b/source/blender/blenkernel/BKE_ipo.h index 3bc707a674a..ea98c226e67 100644 --- a/source/blender/blenkernel/BKE_ipo.h +++ b/source/blender/blenkernel/BKE_ipo.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_ipo.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,13 @@ #ifndef BKE_IPO_H #define BKE_IPO_H +/** \file BKE_ipo.h + * \ingroup bke + * \since March 2001 + * \author nzc + * \author Joshua Leung + */ + #ifdef __cplusplus extern "C" { #endif @@ -44,10 +49,6 @@ void do_versions_ipos_to_animato(struct Main *main); void free_ipo(struct Ipo *ipo); -// xxx perhaps this should be in curve api not in anim api -void correct_bezpart(float *v1, float *v2, float *v3, float *v4); - - #ifdef __cplusplus }; #endif diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index daf6925845f..aeaf17bec27 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_key.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,11 @@ #ifndef BKE_KEY_H #define BKE_KEY_H +/** \file BKE_key.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ struct Key; struct KeyBlock; struct ID; @@ -61,14 +64,14 @@ void key_curve_normal_weights(float t, float *data, int type); float *do_ob_key(struct Scene *scene, struct Object *ob); struct Key *ob_get_key(struct Object *ob); -struct KeyBlock *add_keyblock(struct Key *key, char *name); +struct KeyBlock *add_keyblock(struct Key *key, const char *name); struct KeyBlock *ob_get_keyblock(struct Object *ob); struct KeyBlock *ob_get_reference_keyblock(struct Object *ob); struct KeyBlock *key_get_keyblock(struct Key *key, int index); struct KeyBlock *key_get_named_keyblock(struct Key *key, const char name[]); char *key_get_curValue_rnaPath(struct Key *key, struct KeyBlock *kb); // needed for the GE -void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, int mode); +void do_rel_key(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, const int mode); /* conversion functions */ void key_to_mesh(struct KeyBlock *kb, struct Mesh *me); @@ -81,9 +84,11 @@ float (*key_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3]; void vertcos_to_key(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]); void offset_to_key(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]); +/* key.c */ +extern int slurph_opt; + #ifdef __cplusplus }; #endif -#endif - +#endif // BKE_KEY_H diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index 880f3f7e724..2936338e760 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -25,12 +25,17 @@ * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** - * june-2001 ton */ #ifndef BKE_LATTICE_H #define BKE_LATTICE_H +/** \file BKE_lattice.h + * \ingroup bke + * \author Ton Roosendaal + * \since June 2001 + */ + struct Lattice; struct Object; struct Scene; @@ -39,7 +44,7 @@ struct BPoint; struct MDeformVert; void resizelattice(struct Lattice *lt, int u, int v, int w, struct Object *ltOb); -struct Lattice *add_lattice(char *name); +struct Lattice *add_lattice(const char *name); struct Lattice *copy_lattice(struct Lattice *lt); void free_lattice(struct Lattice *lt); void make_local_lattice(struct Lattice *lt); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index e25c379ded1..871a78bbab3 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -1,8 +1,4 @@ -/** - * blenlib/BKE_library.h (mar-2001 nzc) - * - * Library - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -33,6 +29,15 @@ #ifndef BKE_LIBRARY_TYPES_H #define BKE_LIBRARY_TYPES_H +/** \file BKE_library.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ +#ifdef __cplusplus +extern "C" { +#endif + struct ListBase; struct ID; struct Main; @@ -42,7 +47,7 @@ struct bContext; void *alloc_libblock(struct ListBase *lb, short type, const char *name); void *copy_libblock(void *rt); -void copy_libblock_data(struct ID *id, const struct ID *id_from); +void copy_libblock_data(struct ID *id, const struct ID *id_from, const short do_action); void id_lib_extern(struct ID *id); void id_us_plus(struct ID *id); @@ -61,20 +66,22 @@ int set_listbasepointers(struct Main *main, struct ListBase **lb); void free_libblock(struct ListBase *lb, void *idv); void free_libblock_us(struct ListBase *lb, void *idv); void free_main(struct Main *mainvar); -void tag_main(struct Main *mainvar, int tag); -int splitIDname(char *name, char *left, int *nr); -void rename_id(struct ID *id, char *name); +void tag_main_idcode(struct Main *mainvar, const short type, const short tag); +void tag_main_lb(struct ListBase *lb, const short tag); +void tag_main(struct Main *mainvar, const short tag); + +void rename_id(struct ID *id, const char *name); void name_uiprefix_id(char *name, struct ID *id); void test_idbutton(char *name); void text_idbutton(struct ID *id, char *text); void all_local(struct Library *lib, int untagged_only); -struct ID *find_id(char *type, char *name); +struct ID *find_id(const char *type, const char *name); void clear_id_newpoins(void); -void IDnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb,struct ID* link, short *nr); -void IMAnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb, struct ID *link, short *nr); -void IPOnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb, struct ID* link, short *nr, int blocktype); +void IDnames_to_pupstring(const char **str, const char *title, const char *extraops, struct ListBase *lb,struct ID* link, short *nr); +void IMAnames_to_pupstring(const char **str, const char *title, const char *extraops, struct ListBase *lb, struct ID *link, short *nr); +void IPOnames_to_pupstring(const char **str, const char *title, const char *extraops, struct ListBase *lb, struct ID* link, short *nr, int blocktype); void flag_listbase_ids(ListBase *lb, short flag, short value); void flag_all_listbases_ids(short flag, short value); @@ -85,4 +92,10 @@ void set_free_windowmanager_cb(void (*func)(struct bContext *, struct wmWindowMa /* use when "" is given to new_id() */ #define ID_FALLBACK_NAME "Untitled" +#define IS_TAGGED(_id) ((_id) && (((ID *)_id)->flag & LIB_DOIT)) + +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 60c2d51571f..df6a304f0b3 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -1,13 +1,4 @@ -/** - * blenlib/BKE_main.h (mar-2001 nzc) - * - * Main is the root of the 'database' of a Blender context. All data - * is stuffed into lists, and all these lists are knotted to here. A - * Blender file is not much more but a binary dump of these - * lists. This list of lists is not serialized itself. - * - * Oops... this should be a _types.h file. - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -38,8 +29,25 @@ #ifndef BKE_MAIN_H #define BKE_MAIN_H +/** \file BKE_main.h + * \ingroup bke + * \since March 2001 + * \author nzc + * \section aboutmain Main struct + * Main is the root of the 'database' of a Blender context. All data + * is stuffed into lists, and all these lists are knotted to here. A + * Blender file is not much more but a binary dump of these + * lists. This list of lists is not serialized itself. + * + * Oops... this should be a _types.h file. + * + */ #include "DNA_listBase.h" +#ifdef __cplusplus +extern "C" { +#endif + struct Library; typedef struct Main { @@ -47,6 +55,7 @@ typedef struct Main { char name[240]; short versionfile, subversionfile; short minversionfile, minsubversionfile; + int revision; /* svn revision of binary that saved file */ struct Library *curlib; ListBase scene; @@ -77,8 +86,14 @@ typedef struct Main { ListBase particle; ListBase wm; ListBase gpencil; + + char id_tag_update[256]; } Main; +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 40d98394a8e..523a67eff67 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -25,12 +25,15 @@ * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** - * General operations, lookup, etc. for materials. */ #ifndef BKE_MATERIAL_H #define BKE_MATERIAL_H +/** \file BKE_material.h + * \ingroup bke + * \brief General operations, lookup, etc. for materials. + */ #ifdef __cplusplus extern "C" { #endif @@ -45,9 +48,11 @@ struct Object; void init_def_material(void); void free_material(struct Material *sc); void test_object_materials(struct ID *id); +void resize_object_material(struct Object *ob, const short totcol); void init_material(struct Material *ma); -struct Material *add_material(char *name); +struct Material *add_material(const char *name); struct Material *copy_material(struct Material *ma); +struct Material *localize_material(struct Material *ma); struct Material *give_node_material(struct Material *ma); /* returns node material or self */ void make_local_material(struct Material *ma); diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 7fa4fc1a05e..c4119e99780 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_mball.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,11 @@ #ifndef BKE_MBALL_H #define BKE_MBALL_H +/** \file BKE_mball.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ struct MetaBall; struct Object; struct Scene; @@ -127,12 +130,7 @@ struct pgn_elements { char *data; }; -void calc_mballco(struct MetaElem *ml, float *vec); -float densfunc(struct MetaElem *ball, float x, float y, float z); octal_node* find_metaball_octal_node(octal_node *node, float x, float y, float z, short depth); -float metaball(float x, float y, float z); -void accum_mballfaces(int i1, int i2, int i3, int i4); -void *new_pgn_element(int size); void freepolygonize(PROCESS *p); void docube(CUBE *cube, PROCESS *p, struct MetaBall *mb); @@ -159,7 +157,7 @@ float init_meta(struct Scene *scene, struct Object *ob); void unlink_mball(struct MetaBall *mb); void free_mball(struct MetaBall *mb); -struct MetaBall *add_mball(char *name); +struct MetaBall *add_mball(const char *name); struct MetaBall *copy_mball(struct MetaBall *mb); void make_local_mball(struct MetaBall *mb); struct MetaElem *add_metaball_element(struct MetaBall *mb, const int type); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 7b31e87ab03..7dc1172d32e 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -1,4 +1,4 @@ -/** +/* * blenlib/BKE_mesh.h (mar-2001 nzc) * * $Id$ @@ -31,6 +31,10 @@ #ifndef BKE_MESH_H #define BKE_MESH_H +/** \file BKE_mesh.h + * \ingroup bke + */ + /***/ struct BoundBox; @@ -50,6 +54,8 @@ struct Object; struct MTFace; struct VecNor; struct CustomData; +struct DerivedMesh; +struct Scene; #ifdef __cplusplus extern "C" { @@ -82,7 +88,7 @@ void mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart, void unlink_mesh(struct Mesh *me); void free_mesh(struct Mesh *me, int unlink); -struct Mesh *add_mesh(char *name); +struct Mesh *add_mesh(const char *name); struct Mesh *copy_mesh(struct Mesh *me); void mesh_update_customdata_pointers(struct Mesh *me); @@ -123,7 +129,9 @@ void mesh_get_texspace(struct Mesh *me, float *loc_r, float *rot_r, float *size_ /* if old, it converts mface->edcode to edge drawflags */ void make_edges(struct Mesh *me, int old); + void mesh_strip_loose_faces(struct Mesh *me); +void mesh_strip_loose_edges(struct Mesh *me); /* Calculate vertex and face normals, face normals are returned in *faceNors_r if non-NULL * and vertex normals are stored in actual mverts. @@ -168,8 +176,8 @@ void create_vert_edge_map(ListBase **map, IndexNode **mem, const struct MEdge *m /* Partial Mesh Visibility */ struct PartialVisibility *mesh_pmv_copy(struct PartialVisibility *); void mesh_pmv_free(struct PartialVisibility *); -void mesh_pmv_revert(struct Object *ob, struct Mesh *me); -void mesh_pmv_off(struct Object *ob, struct Mesh *me); +void mesh_pmv_revert(struct Mesh *me); +void mesh_pmv_off(struct Mesh *me); /* functions for making menu's from customdata layers */ int mesh_layers_menu_charlen(struct CustomData *data, int type); /* use this to work out how many chars to allocate */ @@ -183,9 +191,15 @@ int mesh_center_median(struct Mesh *me, float cent[3]); int mesh_center_bounds(struct Mesh *me, float cent[3]); void mesh_translate(struct Mesh *me, float offset[3], int do_keys); +/* mesh_validate.c */ +int BKE_mesh_validate_arrays(struct Mesh *me, struct MVert *mverts, int totvert, struct MEdge *medges, int totedge, struct MFace *mfaces, int totface, const short do_verbose, const short do_fixes); +int BKE_mesh_validate(struct Mesh *me, int do_verbose); +int BKE_mesh_validate_dm(struct DerivedMesh *dm); + +void BKE_mesh_calc_edges(struct Mesh *mesh, int update); + #ifdef __cplusplus } #endif -#endif - +#endif /* BKE_MESH_H */ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 48ce0d4b57b..5f6120509f0 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -1,5 +1,4 @@ -/** - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -30,6 +29,10 @@ #ifndef BKE_MODIFIER_H #define BKE_MODIFIER_H +/** \file BKE_modifier.h + * \ingroup bke + */ + #include "DNA_modifier_types.h" /* needed for all enum typdefs */ #include "BKE_customdata.h" @@ -135,6 +138,12 @@ typedef struct ModifierTypeInfo { float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc); + /* Like deformMatricesEM but called from object mode (for supporting modifiers in sculpt mode) */ + void (*deformMatrices)( + struct ModifierData *md, struct Object *ob, + struct DerivedMesh *derivedData, + float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); + /* Like deformVerts but called during editmode (for supporting modifiers) */ void (*deformVertsEM)( @@ -246,6 +255,17 @@ typedef struct ModifierTypeInfo { */ int (*dependsOnTime)(struct ModifierData *md); + + /* True when a deform modifier uses normals, the requiredDataMask + * cant be used here because that refers to a normal layer where as + * in this case we need to know if the deform modifier uses normals. + * + * this is needed because applying 2 deform modifiers will give the + * second modifier bogus normals. + * */ + int (*dependsOnNormals)(struct ModifierData *md); + + /* Should call the given walk function on with a pointer to each Object * pointer that the modifier data stores. This is used for linking on file * load and for unlinking objects or forwarding object references. @@ -284,7 +304,11 @@ int modifier_couldBeCage(struct Scene *scene, struct ModifierData *md) int modifier_isCorrectableDeformed(struct ModifierData *md); int modifier_sameTopology(ModifierData *md); int modifier_isEnabled(struct Scene *scene, struct ModifierData *md, int required_mode); -void modifier_setError(struct ModifierData *md, char *format, ...); +void modifier_setError(struct ModifierData *md, const char *format, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 2, 3))); +#endif +; void modifiers_foreachObjectLink(struct Object *ob, ObjectWalkFunc walk, @@ -305,7 +329,7 @@ int modifiers_isParticleEnabled(struct Object *ob); struct Object *modifiers_isDeformedByArmature(struct Object *ob); struct Object *modifiers_isDeformedByLattice(struct Object *ob); int modifiers_usesArmature(struct Object *ob, struct bArmature *arm); -int modifiers_isCorrectableDeformed(struct Scene *scene, struct Object *ob); +int modifiers_isCorrectableDeformed(struct Object *ob); void modifier_freeTemporaryData(struct ModifierData *md); int modifiers_indexInObject(struct Object *ob, struct ModifierData *md); @@ -322,6 +346,9 @@ struct LinkNode *modifiers_calcDataMasks(struct Scene *scene, int required_mode); struct ModifierData *modifiers_getVirtualModifierList(struct Object *ob); +/* ensure modifier correctness when changing ob->data */ +void test_object_modifiers(struct Object *ob); + /* here for do_versions */ void modifier_mdef_compact_influences(struct ModifierData *md); diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 39fc795e6ff..ea34ff4aa07 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -30,6 +30,10 @@ #ifndef BKE_MULTIRES_H #define BKE_MULTIRES_H +/** \file BKE_multires.h + * \ingroup bke + */ + struct DerivedMesh; struct Mesh; struct MFace; @@ -37,6 +41,8 @@ struct Multires; struct MultiresModifierData; struct ModifierData; struct Object; +struct Scene; +struct MDisps; void multires_mark_as_modified(struct Object *ob); @@ -44,15 +50,18 @@ void multires_force_update(struct Object *ob); void multires_force_render_update(struct Object *ob); void multires_force_external_reload(struct Object *ob); +void multiresModifier_set_levels_from_disps(struct MultiresModifierData *mmd, struct Object *ob); + struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData*, int local_mmd, struct DerivedMesh*, struct Object *, int, int); struct MultiresModifierData *find_multires_modifier_before(struct Scene *scene, struct ModifierData *lastmd); +struct MultiresModifierData *get_multires_modifier(struct Scene *scene, struct Object *ob, int use_first); struct DerivedMesh *get_multires_dm(struct Scene *scene, struct MultiresModifierData *mmd, struct Object *ob); -void multiresModifier_join(struct Object *); void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction); +void multiresModifier_base_apply(struct MultiresModifierData *mmd, struct Object *ob); void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple); int multiresModifier_reshape(struct Scene *scene, struct MultiresModifierData *mmd, @@ -69,5 +78,22 @@ void multires_free(struct Multires *mr); void multires_load_old(struct Object *ob, struct Mesh *me); void multires_load_old_250(struct Mesh *); -#endif +void multiresModifier_scale_disp(struct Scene *scene, struct Object *ob); +void multiresModifier_prepare_join(struct Scene *scene, struct Object *ob, struct Object *to_ob); + +int multires_mdisp_corners(struct MDisps *s); +void multires_mdisp_smooth_bounds(struct MDisps *disps); + +/* update multires data after topology changing */ +void multires_topology_changed(struct Scene *scene, struct Object *ob); + +/**** interpolation stuff ****/ +void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v); +void mdisp_rot_crn_to_face(const int S, const int corners, const int face_side, const float x, const float y, float *u, float *v); +int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y); +void mdisp_apply_weight(const int S, const int corners, int x, int y, const int face_side, float crn_weight[4][2], float *u_r, float *v_r); +void mdisp_flip_disp(const int S, const int corners, const float axis_x[2], const float axis_y[2], float disp[3]); +void mdisp_join_tris(struct MDisps *dst, struct MDisps *tri1, struct MDisps *tri2); + +#endif // BKE_MULTIRES_H diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 30bce613dbe..0206756a1ad 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -30,6 +30,11 @@ #ifndef BKE_NLA_H #define BKE_NLA_H +/** \file BKE_nla.h + * \ingroup bke + * \author Joshua Leung (full recode) + */ + struct AnimData; struct NlaStrip; struct NlaTrack; diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 4bd4cc3792f..41e41eab78f 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -33,6 +33,10 @@ #ifndef BKE_NODE_H #define BKE_NODE_H +/** \file BKE_node.h + * \ingroup bke + */ + /* not very important, but the stack solver likes to know a maximum */ #define MAX_SOCKET 64 @@ -61,21 +65,18 @@ struct uiLayout; typedef struct bNodeSocketType { int type, limit; - char *name; + const char *name; float val1, val2, val3, val4; /* default alloc value for inputs */ float min, max; /* default range for inputs */ /* after this line is used internal only */ struct bNodeSocket *sock; /* used during verify_types */ - struct bNodeSocket *internsock; /* group nodes, the internal socket counterpart */ - int own_index; /* verify group nodes */ - } bNodeSocketType; typedef struct bNodeType { void *next,*prev; int type; - char *name; + const char *name; /* can be allocated too */ float width, minwidth, maxwidth; short nclass, flag; @@ -87,6 +88,7 @@ typedef struct bNodeType { /* this line is set on startup of blender */ void (*uifunc)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr); + const char *(*labelfunc)(struct bNode *); void (*initfunc)(struct bNode *); void (*freestoragefunc)(struct bNode *); @@ -125,17 +127,21 @@ typedef struct bNodeType { #define NODE_CLASS_PATTERN 12 #define NODE_CLASS_TEXTURE 13 +/* enum values for input/output */ +#define SOCK_IN 1 +#define SOCK_OUT 2 + /* ************** GENERIC API, TREES *************** */ void ntreeVerifyTypes(struct bNodeTree *ntree); -struct bNodeTree *ntreeAddTree(int type); +struct bNodeTree *ntreeAddTree(const char *name, int type, const short is_group); void ntreeInitTypes(struct bNodeTree *ntree); -void ntreeMakeOwnType(struct bNodeTree *ntree); +//void ntreeMakeGroupSockets(struct bNodeTree *ntree); void ntreeUpdateType(struct bNodeTree *ntree, struct bNodeType *ntype); void ntreeFreeTree(struct bNodeTree *ntree); -struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree, int internal_select); +struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree); void ntreeSwitchID(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to); void ntreeMakeLocal(struct bNodeTree *ntree); @@ -173,14 +179,14 @@ void nodeUpdateType(struct bNodeTree *ntree, struct bNode* node, struct bNodeT void nodeMakeDynamicType(struct bNode *node); int nodeDynamicUnlinkText(struct ID *txtid); void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node); -struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal); +struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node); struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock); void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link); void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name); -int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex); +int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex, int *in_out); struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to); int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); @@ -192,26 +198,44 @@ int nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id); void nodeClearActiveID(struct bNodeTree *ntree, short idtype); void NodeTagChanged(struct bNodeTree *ntree, struct bNode *node); -void NodeTagIDChanged(struct bNodeTree *ntree, struct ID *id); +int NodeTagIDChanged(struct bNodeTree *ntree, struct ID *id); +void ntreeClearTags(struct bNodeTree *ntree); /* ************** Groups ****************** */ struct bNode *nodeMakeGroupFromSelected(struct bNodeTree *ntree); int nodeGroupUnGroup(struct bNodeTree *ntree, struct bNode *gnode); -void nodeVerifyGroup(struct bNodeTree *ngroup); +void nodeGroupVerify(struct bNodeTree *ngroup); void nodeGroupSocketUseFlags(struct bNodeTree *ngroup); -void nodeCopyGroup(struct bNode *gnode); +void nodeGroupCopy(struct bNode *gnode); + +struct bNodeSocket *nodeGroupAddSocket(struct bNodeTree *ngroup, const char *name, int type, int in_out); +struct bNodeSocket *nodeGroupExposeSocket(struct bNodeTree *ngroup, struct bNodeSocket *sock, int in_out); +void nodeGroupExposeAllSockets(struct bNodeTree *ngroup); +void nodeGroupRemoveSocket(struct bNodeTree *ngroup, struct bNodeSocket *gsock, int in_out); /* ************** COMMON NODES *************** */ +/* Init a new node type struct with default values and callbacks */ +void node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag, + struct bNodeSocketType *inputs, struct bNodeSocketType *outputs); +void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth); +void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNode *)); +void node_type_storage(struct bNodeType *ntype, + const char *storagename, + void (*freestoragefunc)(struct bNode *), + void (*copystoragefunc)(struct bNode *, struct bNode *)); +void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **)); +void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out)); +void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *)); + #define NODE_GROUP 2 #define NODE_GROUP_MENU 1000 #define NODE_DYNAMIC_MENU 4000 -extern bNodeType node_group_typeinfo; - +void register_node_type_group(ListBase *lb); /* ************** SHADER NODES *************** */ @@ -399,7 +423,6 @@ int ntreeCompositTagAnimated(struct bNodeTree *ntree); void ntreeCompositTagGenerators(struct bNodeTree *ntree); void ntreeCompositForceHidden(struct bNodeTree *ntree, struct Scene *scene); -void free_compbuf(struct CompBuf *cbuf); /* internal...*/ /* ************** TEXTURE NODES *************** */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 2a7ba4f98c9..3d32ba5a30a 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -25,12 +25,15 @@ * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** - * General operations, lookup, etc. for blender objects. */ #ifndef BKE_OBJECT_H #define BKE_OBJECT_H +/** \file BKE_object.h + * \ingroup bke + * \brief General operations, lookup, etc. for blender objects. + */ #ifdef __cplusplus extern "C" { #endif @@ -71,25 +74,26 @@ void object_free_modifiers(struct Object *ob); void object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob); void object_copy_proxy_drivers(struct Object *ob, struct Object *target); -void unlink_object(struct Scene *scene, struct Object *ob); +void unlink_object(struct Object *ob); int exist_object(struct Object *obtest); -void *add_camera(char *name); +void *add_camera(const char *name); struct Camera *copy_camera(struct Camera *cam); void make_local_camera(struct Camera *cam); float dof_camera(struct Object *ob); -void *add_lamp(char *name); +void *add_lamp(const char *name); struct Lamp *copy_lamp(struct Lamp *la); void make_local_lamp(struct Lamp *la); void free_camera(struct Camera *ca); void free_lamp(struct Lamp *la); -struct Object *add_only_object(int type, char *name); +struct Object *add_only_object(int type, const char *name); struct Object *add_object(struct Scene *scene, int type); struct Object *copy_object(struct Object *ob); void expand_local_object(struct Object *ob); void make_local_object(struct Object *ob); +int object_is_libdata(struct Object *ob); int object_data_is_libdata(struct Object *ob); void set_mblur_offs(float blur); void set_field_offs(float field); @@ -98,10 +102,10 @@ void disable_speed_curve(int val); float bsystem_time(struct Scene *scene, struct Object *ob, float cfra, float ofs); void object_scale_to_mat3(struct Object *ob, float mat[][3]); void object_rot_to_mat3(struct Object *ob, float mat[][3]); -void object_mat3_to_rot(struct Object *ob, float mat[][3], int use_compat); +void object_mat3_to_rot(struct Object *ob, float mat[][3], short use_compat); void object_to_mat3(struct Object *ob, float mat[][3]); void object_to_mat4(struct Object *ob, float mat[][4]); -void object_apply_mat4(struct Object *ob, float mat[][4]); +void object_apply_mat4(struct Object *ob, float mat[][4], const short use_compat, const short use_parent); void set_no_parent_ipo(int val); @@ -130,7 +134,7 @@ int give_obdata_texspace(struct Object *ob, short **texflag, float **loc, float int object_insert_ptcache(struct Object *ob); // void object_delete_ptcache(struct Object *ob, int index); -struct KeyBlock *object_insert_shape_key(struct Scene *scene, struct Object *ob, char *name, int from_mix); +struct KeyBlock *object_insert_shape_key(struct Scene *scene, struct Object *ob, const char *name, int from_mix); void object_camera_matrix( struct RenderData *rd, struct Object *camera, int winx, int winy, short field_second, diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h index 58cf144483f..541c581e762 100644 --- a/source/blender/blenkernel/BKE_packedFile.h +++ b/source/blender/blenkernel/BKE_packedFile.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_packedFile.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,11 @@ #ifndef BKE_PACKEDFILE_H #define BKE_PACKEDFILE_H +/** \file BKE_packedFile.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ #define RET_OK 0 #define RET_ERROR 1 @@ -42,7 +45,7 @@ struct ReportList; struct VFont; /* pack */ -struct PackedFile *newPackedFile(struct ReportList *reports, char *filename); +struct PackedFile *newPackedFile(struct ReportList *reports, const char *filename); struct PackedFile *newPackedFileMemory(void *mem, int memlen); void packAll(struct Main *bmain, struct ReportList *reports); @@ -50,18 +53,18 @@ void packAll(struct Main *bmain, struct ReportList *reports); /* unpack */ char *unpackFile(struct ReportList *reports, char *abs_name, char *local_name, struct PackedFile *pf, int how); int unpackVFont(struct ReportList *reports, struct VFont *vfont, int how); -int unpackSound(struct ReportList *reports, struct bSound *sound, int how); +int unpackSound(struct Main *bmain, struct ReportList *reports, struct bSound *sound, int how); int unpackImage(struct ReportList *reports, struct Image *ima, int how); void unpackAll(struct Main *bmain, struct ReportList *reports, int how); -int writePackedFile(struct ReportList *reports, char *filename, struct PackedFile *pf, int guimode); +int writePackedFile(struct ReportList *reports, const char *filename, struct PackedFile *pf, int guimode); /* free */ void freePackedFile(struct PackedFile *pf); /* info */ int countPackedFiles(struct Main *bmain); -int checkPackedFile(char *filename, struct PackedFile *pf); +int checkPackedFile(const char *filename, struct PackedFile *pf); /* read */ int seekPackedFile(struct PackedFile *pf, int offset, int whence); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index e2d48baba37..e6caae7a954 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -28,6 +28,10 @@ #ifndef BKE_PAINT_H #define BKE_PAINT_H +/** \file BKE_paint.h + * \ingroup bke + */ + #include "DNA_vec_types.h" struct Brush; @@ -78,8 +82,11 @@ typedef struct SculptSession { /* PBVH acceleration structure */ struct PBVH *pbvh; - /* Used temporarily per-stroke */ - float *vertexcosnos; + /* Paiting on deformed mesh */ + int modifiers_active; /* object is deformed with some modifiers */ + float (*orig_cos)[3]; /* coords of undeformed mesh */ + float (*deform_cos)[3]; /* coords of deformed mesh but without stroke displacement */ + float (*deform_imats)[3][3]; /* crazyspace deformation matricies */ /* Partial redraw */ int partial_redraw; @@ -95,8 +102,6 @@ typedef struct SculptSession { struct GPUDrawObject *drawobject; - int modifiers_active; - rcti previous_r; } SculptSession; diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 1416e1280cf..507adcc5f2d 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -1,6 +1,4 @@ -/* BKE_particle.h - * - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -32,6 +30,10 @@ #ifndef BKE_PARTICLE_H #define BKE_PARTICLE_H +/** \file BKE_particle.h + * \ingroup bke + */ + #include "DNA_particle_types.h" #include "DNA_object_types.h" @@ -63,6 +65,7 @@ struct BVHTreeRayHit; #define LOOP_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) #define LOOP_EXISTING_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) if(!(pa->flag & PARS_UNEXIST)) #define LOOP_SHOWN_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) if(!(pa->flag & (PARS_UNEXIST|PARS_NO_DISP))) +#define LOOP_DYNAMIC_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) if(pa->state.time > 0.f) #define PSYS_FRAND_COUNT 1024 #define PSYS_FRAND(seed) psys->frand[(seed) % PSYS_FRAND_COUNT] @@ -79,20 +82,10 @@ typedef struct ParticleSimulationData { struct ListBase *colliders; } ParticleSimulationData; -//typedef struct ParticleReactEvent { -// struct ParticleReactEvent *next, *prev; -// int event, pa_num; -// Object *ob; -// struct ParticleSystem *psys; -// struct ParticleKey state; -// -// float time, size; -//}ParticleReactEvent; - typedef struct ParticleTexture{ float ivel; /* used in reset */ float time, life, exist, size; /* used in init */ - float pvel[3]; /* used in physics */ + float damp, gravity, field; /* used in physics */ float length, clump, kink, effector;/* used in path caching */ float rough1, rough2, roughe; /* used in path caching */ } ParticleTexture; @@ -158,6 +151,7 @@ typedef struct ParticleBillboardData int uv[3]; int lock, num; int totnum; + int lifetime; short align, uv_split, anim, split_offset; } ParticleBillboardData; @@ -171,7 +165,9 @@ typedef struct ParticleCollision float co1[3], co2[3]; // ray start and end points float ve1[3], ve2[3]; // particle velocities float ray_len; // original length of co2-co1, needed for collision time evaluation - float t; // time of previous collision, needed for substracting face velocity + float f; // time factor of previous collision, needed for substracting face velocity + float cfra; // start of the timestep (during frame change, since previous integer frame) + float dfra; // duration of timestep in frames } ParticleCollision; typedef struct ParticleDrawData { @@ -224,9 +220,9 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); -struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, char *name); +struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, const char *name); void object_remove_particle_system(struct Scene *scene, struct Object *ob); -struct ParticleSettings *psys_new_settings(char *name, struct Main *main); +struct ParticleSettings *psys_new_settings(const char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); void make_local_particlesettings(struct ParticleSettings *part); @@ -288,7 +284,7 @@ float psys_get_dietime_from_cache(struct PointCache *cache, int index); void psys_free_pdd(struct ParticleSystem *psys); float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup); -void psys_get_texture(struct ParticleSimulationData *sim, struct Material *ma, struct ParticleData *pa, struct ParticleTexture *ptex, int event); +void psys_get_texture(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleTexture *ptex, int event, float cfra); void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, float (*orcodata)[3], float *uv, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); float psys_particle_value_from_verts(struct DerivedMesh *dm, short from, struct ParticleData *pa, float *values); void psys_get_from_key(struct ParticleKey *key, float *loc, float *vel, float *rot, float *time); @@ -309,7 +305,7 @@ void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, /* psys_reset */ #define PSYS_RESET_ALL 1 #define PSYS_RESET_DEPSGRAPH 2 -#define PSYS_RESET_CHILDREN 3 +/* #define PSYS_RESET_CHILDREN 3 */ /*UNUSED*/ #define PSYS_RESET_CACHE_MISS 4 /* index_dmcache */ diff --git a/source/blender/blenkernel/BKE_plugin_types.h b/source/blender/blenkernel/BKE_plugin_types.h index 0bb1400858d..a7842b526ce 100644 --- a/source/blender/blenkernel/BKE_plugin_types.h +++ b/source/blender/blenkernel/BKE_plugin_types.h @@ -1,9 +1,4 @@ -/** - * blenlib/BKE_plugin_types.h (mar-2001 nzc) - * - * Renderrecipe and scene decription. The fact that there is a - * hierarchy here is a bit strange, and not desirable. - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -34,6 +29,11 @@ #ifndef BKE_PLUGIN_TYPES_H #define BKE_PLUGIN_TYPES_H +/** \file BKE_plugin_types.h + * \ingroup bke + * \author nzc + */ + struct ImBuf; typedef int (*TexDoitold)(int stype, void *cast, float *texvec, float *dxt, float *dyt); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 52536e10e56..346368a5958 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -29,9 +29,14 @@ #ifndef BKE_POINTCACHE_H #define BKE_POINTCACHE_H +/** \file BKE_pointcache.h + * \ingroup bke + */ + #include "DNA_ID.h" #include "DNA_object_force.h" #include "DNA_boid_types.h" +#include <stdio.h> /* for FILE */ /* Point cache clearing option, for BKE_ptcache_id_clear, before * and after are non inclusive (they wont remove the cfra) */ @@ -44,7 +49,7 @@ #define PTCACHE_RESET_DEPSGRAPH 0 #define PTCACHE_RESET_BAKED 1 #define PTCACHE_RESET_OUTDATED 2 -#define PTCACHE_RESET_FREE 3 +/* #define PTCACHE_RESET_FREE 3 */ /*UNUSED*/ /* Add the blendfile name after blendcache_ */ #define PTCACHE_EXT ".bphys" @@ -62,6 +67,13 @@ #define PTCACHE_TYPE_SMOKE_DOMAIN 3 #define PTCACHE_TYPE_SMOKE_HIGHRES 4 +/* high bits reserved for flags that need to be stored in file */ +#define PTCACHE_TYPEFLAG_COMPRESS (1<<16) +#define PTCACHE_TYPEFLAG_EXTRADATA (1<<17) + +#define PTCACHE_TYPEFLAG_TYPEMASK 0x0000FFFF +#define PTCACHE_TYPEFLAG_FLAGMASK 0xFFFF0000 + /* PTCache read return code */ #define PTCACHE_READ_EXACT 1 #define PTCACHE_READ_INTERPOLATED 2 @@ -81,7 +93,7 @@ struct SoftBody; /* temp structure for read/write */ typedef struct PTCacheData { - int index; + unsigned int index; float loc[3]; float vel[3]; float rot[4]; @@ -94,8 +106,9 @@ typedef struct PTCacheData { typedef struct PTCacheFile { FILE *fp; - int totpoint, type; - unsigned int data_types; + int frame, old_format; + unsigned int totpoint, type; + unsigned int data_types, flag; struct PTCacheData data; void *cur[BPHYS_TOT_DATA]; @@ -109,23 +122,31 @@ typedef struct PTCacheID { struct Scene *scene; struct Object *ob; void *calldata; - int type; - int stack_index; - int flag; + unsigned int type; + unsigned int stack_index; + unsigned int flag; /* flags defined in DNA_object_force.h */ unsigned int data_types, info_types; /* copies point data to cache data */ - int (*write_elem)(int index, void *calldata, void **data, int cfra); + int (*write_point)(int index, void *calldata, void **data, int cfra); + /* copies cache cata to point data */ + void (*read_point)(int index, void *calldata, void **data, float cfra, float *old_data); + /* interpolated between previously read point data and cache data */ + void (*interpolate_point)(int index, void *calldata, void **data, float cfra, float cfra1, float cfra2, float *old_data); + /* copies point data to cache data */ int (*write_stream)(PTCacheFile *pf, void *calldata); /* copies cache cata to point data */ - void (*read_elem)(int index, void *calldata, void **data, float frs_sec, float cfra, float *old_data); - /* copies cache cata to point data */ void (*read_stream)(PTCacheFile *pf, void *calldata); - /* interpolated between previously read point data and cache data */ - void (*interpolate_elem)(int index, void *calldata, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data); + + /* copies custom extradata to cache data */ + void (*write_extra_data)(void *calldata, struct PTCacheMem *pm, int cfra); + /* copies custom extradata to cache data */ + void (*read_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra); + /* copies custom extradata to cache data */ + void (*interpolate_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra, float cfra1, float cfra2); /* total number of simulated points (the cfra parameter is just for using same function pointer with totwrite) */ int (*totpoint)(void *calldata, int cfra); @@ -222,8 +243,8 @@ typedef struct PTCacheEdit { int totpoint, totframes, totcached, edited; - char sel_col[3]; - char nosel_col[3]; + unsigned char sel_col[3]; + unsigned char nosel_col[3]; } PTCacheEdit; /* Particle functions */ @@ -234,7 +255,6 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct Soft void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys); void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd); void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd); -void BKE_ptcache_id_from_smoke_turbulence(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd); void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis); @@ -242,7 +262,7 @@ void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct void BKE_ptcache_remove(void); /************ ID specific functions ************************/ -void BKE_ptcache_id_clear(PTCacheID *id, int mode, int cfra); +void BKE_ptcache_id_clear(PTCacheID *id, int mode, unsigned int cfra); int BKE_ptcache_id_exist(PTCacheID *id, int cfra); int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *id, int mode); void BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale); @@ -255,10 +275,13 @@ void BKE_ptcache_update_info(PTCacheID *pid); /* Size of cache data type. */ int BKE_ptcache_data_size(int data_type); +/* Is point with indes in memory cache */ +int BKE_ptcache_mem_index_find(struct PTCacheMem *pm, unsigned int index); + /* Memory cache read/write helpers. */ -void BKE_ptcache_mem_init_pointers(struct PTCacheMem *pm); -void BKE_ptcache_mem_incr_pointers(struct PTCacheMem *pm); -int BKE_ptcache_mem_seek_pointers(int point_index, struct PTCacheMem *pm); +void BKE_ptcache_mem_pointers_init(struct PTCacheMem *pm); +void BKE_ptcache_mem_pointers_incr(struct PTCacheMem *pm); +int BKE_ptcache_mem_pointers_seek(int point_index, struct PTCacheMem *pm); /* Copy a specific data type from cache data to point data. */ void BKE_ptcache_data_get(void **data, int type, int index, void *to); @@ -267,10 +290,10 @@ void BKE_ptcache_data_get(void **data, int type, int index, void *to); void BKE_ptcache_data_set(void **data, int type, void *from); /* Main cache reading call. */ -int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec); +int BKE_ptcache_read(PTCacheID *pid, float cfra); /* Main cache writing call. */ -int BKE_ptcache_write_cache(PTCacheID *pid, int cfra); +int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra); /****************** Continue physics ***************/ void BKE_ptcache_set_continue_physics(struct Main *bmain, struct Scene *scene, int enable); @@ -289,7 +312,7 @@ struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, struct L void BKE_ptcache_quick_cache_all(struct Main *bmain, struct Scene *scene); /* Bake cache or simulate to current frame with settings defined in the baker. */ -void BKE_ptcache_make_cache(struct PTCacheBaker* baker); +void BKE_ptcache_bake(struct PTCacheBaker* baker); /* Convert disk cache to memory cache. */ void BKE_ptcache_disk_to_mem(struct PTCacheID *pid); @@ -300,6 +323,9 @@ void BKE_ptcache_mem_to_disk(struct PTCacheID *pid); /* Convert disk cache to memory cache and vice versa. Clears the cache that was converted. */ void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid); +/* Rename all disk cache files with a new name. Doesn't touch the actual content of the files. */ +void BKE_ptcache_disk_cache_rename(struct PTCacheID *pid, char *from, char *to); + /* Loads simulation from external (disk) cache files. */ void BKE_ptcache_load_external(struct PTCacheID *pid); diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h index b9cca612846..10014a4611d 100644 --- a/source/blender/blenkernel/BKE_property.h +++ b/source/blender/blenkernel/BKE_property.h @@ -1,6 +1,4 @@ -/** - * blenkernel/BKE_property.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,10 @@ #ifndef BKE_PROPERTY_H #define BKE_PROPERTY_H +/** \file BKE_property.h + * \ingroup bke + */ + struct bProperty; struct ListBase; struct Object; @@ -42,7 +44,7 @@ void copy_properties(struct ListBase *lbn, struct ListBase *lbo); void init_property(struct bProperty *prop); struct bProperty *new_property(int type); void unique_property(struct bProperty *first, struct bProperty *prop, int force); -struct bProperty *get_ob_property(struct Object *ob, char *name); +struct bProperty *get_ob_property(struct Object *ob, const char *name); void set_ob_property(struct Object *ob, struct bProperty *propc); int compare_property(struct bProperty *prop, char *str); void set_property(struct bProperty *prop, char *str); diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h index d7b7801d697..397c96422a5 100644 --- a/source/blender/blenkernel/BKE_report.h +++ b/source/blender/blenkernel/BKE_report.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -28,6 +28,10 @@ #ifndef BKE_REPORT_H #define BKE_REPORT_H +/** \file BKE_report.h + * \ingroup bke + */ + #ifdef __cplusplus extern "C" { #endif @@ -45,7 +49,11 @@ void BKE_reports_init(ReportList *reports, int flag); void BKE_reports_clear(ReportList *reports); void BKE_report(ReportList *reports, ReportType type, const char *message); -void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...); +void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 3, 4))); +#endif +; void BKE_reports_prepend(ReportList *reports, const char *prepend); void BKE_reports_prependf(ReportList *reports, const char *prepend, ...); diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h index 6cafb7ef104..0db0b71c102 100644 --- a/source/blender/blenkernel/BKE_sca.h +++ b/source/blender/blenkernel/BKE_sca.h @@ -1,7 +1,5 @@ -/** - * blenlib/BKE_sca.h (mar-2001 nzc) - * - * $Id$ +/* + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -31,6 +29,10 @@ #ifndef BKE_SCA_H #define BKE_SCA_H +/** \file BKE_sca.h + * \ingroup bke + */ + struct Text; struct bSensor; struct Object; @@ -68,7 +70,7 @@ void clear_sca_new_poins_ob(struct Object *ob); void clear_sca_new_poins(void); void set_sca_new_poins_ob(struct Object *ob); void set_sca_new_poins(void); -void sca_remove_ob_poin(struct Object *obt, struct Object *ob); +void sca_remove_ob_poin(struct Object *obt, struct Object *ob); void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_up); void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 96ef8d44cf4..ac85f91bf46 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_scene.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,16 @@ #ifndef BKE_SCENE_H #define BKE_SCENE_H +/** \file BKE_scene.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ + +#ifdef __cplusplus +extern "C" { +#endif + struct AviCodecData; struct Base; struct bglMats; @@ -47,20 +55,20 @@ struct Text; #define SCE_COPY_LINK_DATA 2 #define SCE_COPY_FULL 3 -#define SETLOOPER(s, b) sce= s, b= _setlooper_base_step(&sce, NULL); b; b= _setlooper_base_step(&sce, b) -struct Base *_setlooper_base_step(struct Scene **sce, struct Base *base); +#define SETLOOPER(_sce_basis, _sce_iter, _base) _sce_iter= _sce_basis, _base= _setlooper_base_step(&_sce_iter, NULL); _base; _base= _setlooper_base_step(&_sce_iter, _base) +struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base); void free_avicodecdata(struct AviCodecData *acd); void free_qtcodecdata(struct QuicktimeCodecData *acd); void free_scene(struct Scene *sce); -struct Scene *add_scene(char *name); +struct Scene *add_scene(const char *name); struct Base *object_in_scene(struct Object *ob, struct Scene *sce); void set_scene_bg(struct Main *bmain, struct Scene *sce); -struct Scene *set_scene_name(struct Main *bmain, char *name); +struct Scene *set_scene_name(struct Main *bmain, const char *name); -struct Scene *copy_scene(struct Main *bmain, struct Scene *sce, int type); +struct Scene *copy_scene(struct Scene *sce, int type); void unlink_scene(struct Main *bmain, struct Scene *sce, struct Scene *newsce); int next_object(struct Scene **scene, int val, struct Base **base, struct Object **ob); @@ -72,6 +80,7 @@ char *scene_find_marker_name(struct Scene *scene, int frame); char *scene_find_last_marker_name(struct Scene *scene, int frame); int scene_marker_tfm_translate(struct Scene *scene, int delta, int flag); int scene_marker_tfm_extend(struct Scene *scene, int delta, int flag, int frame, char side); +int scene_marker_tfm_scale(struct Scene *scene, float value, int flag); struct Base *scene_add_base(struct Scene *sce, struct Object *ob); void scene_deselect_all(struct Scene *sce); @@ -93,5 +102,9 @@ int get_render_child_particle_number(struct RenderData *r, int num); int get_render_shadow_samples(struct RenderData *r, int samples); float get_render_aosss_error(struct RenderData *r, float error); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 125486625bb..0a7d9780a6b 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_screen.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,12 @@ #ifndef BKE_SCREEN_H #define BKE_SCREEN_H +/** \file BKE_screen.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ + struct ARegion; struct bContext; struct bContextDataResult; diff --git a/source/blender/blenkernel/BKE_script.h b/source/blender/blenkernel/BKE_script.h index 4ea1ee6db85..304e46fe2c5 100644 --- a/source/blender/blenkernel/BKE_script.h +++ b/source/blender/blenkernel/BKE_script.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_script.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,13 @@ #ifndef BKE_SCRIPT_H #define BKE_SCRIPT_H +/** \file BKE_script.h + * \ingroup bke + * \since March 2001 + * \author nzc + * \author Willian P. Germano + */ + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 0766012b4a5..cc1d8537cbd 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +31,10 @@ #ifndef BKE_SEQUENCER_H #define BKE_SEQUENCER_H +/** \file BKE_sequencer.h + * \ingroup bke + */ + struct bContext; struct Editing; struct ImBuf; @@ -46,6 +50,11 @@ struct StripElem; #define BUILD_SEQAR_COUNT_CURRENT 1 #define BUILD_SEQAR_COUNT_CHILDREN 2 +#define EARLY_NO_INPUT -1 +#define EARLY_DO_EFFECT 0 +#define EARLY_USE_INPUT_1 1 +#define EARLY_USE_INPUT_2 2 + /* sequence iterator */ typedef struct SeqIterator { @@ -78,6 +87,22 @@ void seq_array(struct Editing *ed, struct Sequence ***seqarray, int *tot, int us seq_end(&iter); \ } +typedef struct SeqRenderData { + struct Main *bmain; + struct Scene *scene; + int rectx; + int recty; + int preview_render_size; + int motion_blur_samples; + float motion_blur_shutter; +} SeqRenderData; + +SeqRenderData seq_new_render_data( + struct Main * bmain, struct Scene * scene, + int rectx, int recty, int preview_render_size); + +int seq_cmp_render_data(const SeqRenderData * a, const SeqRenderData * b); +unsigned int seq_hash_render_data(const SeqRenderData * a); /* Wipe effect */ enum {DO_SINGLE_WIPE, DO_DOUBLE_WIPE, DO_BOX_WIPE, DO_CROSS_WIPE, @@ -92,7 +117,7 @@ struct SeqEffectHandle { /* number of input strips needed (called directly after construction) */ - int (*num_inputs)(); + int (*num_inputs)(void); /* load is called first time after readblenfile in get_sequence_effect automatically */ @@ -124,53 +149,61 @@ struct SeqEffectHandle { (mixed cases are handled one layer up...) */ struct ImBuf* (*execute)( - struct Main *bmain, - struct Scene *scene, struct Sequence *seq, float cfra, + SeqRenderData context, + struct Sequence *seq, float cfra, float facf0, float facf1, - int x, int y, int preview_render_size, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3); }; /* ********************* prototypes *************** */ -/* sequence.c */ -void printf_strip(struct Sequence *seq); +/* ********************************************************************** + * sequence.c + + * sequencer render functions + ********************************************************************** */ + +struct ImBuf *give_ibuf_seq(SeqRenderData context, float cfra, int chanshown); +struct ImBuf *give_ibuf_seq_threaded(SeqRenderData context, float cfra, int chanshown); +struct ImBuf *give_ibuf_seq_direct(SeqRenderData context, float cfra, struct Sequence *seq); +struct ImBuf *give_ibuf_seqbase(SeqRenderData context, float cfra, int chan_shown, struct ListBase *seqbasep); +void give_ibuf_prefetch_request(SeqRenderData context, float cfra, int chan_shown); /* apply functions recursively */ int seqbase_recursive_apply(struct ListBase *seqbase, int (*apply_func)(struct Sequence *seq, void *), void *arg); int seq_recursive_apply(struct Sequence *seq, int (*apply_func)(struct Sequence *, void *), void *arg); -// extern +/* maintainance functions, mostly for RNA */ +// extern void seq_free_sequence(struct Scene *scene, struct Sequence *seq); void seq_free_strip(struct Strip *strip); void seq_free_editing(struct Scene *scene); void seq_free_clipboard(void); struct Editing *seq_give_editing(struct Scene *scene, int alloc); -char *give_seqname(struct Sequence *seq); -struct ImBuf *give_ibuf_seq(struct Main *bmain, struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size); -struct ImBuf *give_ibuf_seq_threaded(struct Main *bmain, struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size); -struct ImBuf *give_ibuf_seq_direct(struct Main *bmain, struct Scene *scene, int rectx, int recty, int cfra, int render_size, struct Sequence *seq); -struct ImBuf *give_ibuf_seqbase(struct Main *bmain, struct Scene *scene, int rectx, int recty, int cfra, int chan_shown, int render_size, struct ListBase *seqbasep); -void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, int render_size); +const char *give_seqname(struct Sequence *seq); void calc_sequence(struct Scene *scene, struct Sequence *seq); void calc_sequence_disp(struct Scene *scene, struct Sequence *seq); void new_tstripdata(struct Sequence *seq); -void reload_sequence_new_file(struct Main *bmain, struct Scene *scene, struct Sequence * seq, int lock_range); +void reload_sequence_new_file(struct Scene *scene, struct Sequence * seq, int lock_range); void sort_seq(struct Scene *scene); void build_seqar_cb(struct ListBase *seqbase, struct Sequence ***seqar, int *totseq, int (*test_func)(struct Sequence * seq)); int evaluate_seq_frame(struct Scene *scene, int cfra); struct StripElem *give_stripelem(struct Sequence *seq, int cfra); -// intern? +// intern +void printf_strip(struct Sequence *seq); // debugging function (unused) void update_changed_seq_and_deps(struct Scene *scene, struct Sequence *changed_seq, int len_change, int ibuf_change); int input_have_to_preprocess( - struct Scene *scene, struct Sequence * seq, - float cfra, int seqrectx, int seqrecty); + SeqRenderData context, struct Sequence * seq, float cfra); + +/* ********************************************************************** + seqcache.c -/* seqcache.c */ + Sequencer memory cache management functions + ********************************************************************** */ typedef enum { SEQ_STRIPELEM_IBUF, @@ -179,28 +212,39 @@ typedef enum { SEQ_STRIPELEM_IBUF_ENDSTILL } seq_stripelem_ibuf_t; -void seq_stripelem_cache_init(); -void seq_stripelem_cache_destruct(); +void seq_stripelem_cache_init(void); +void seq_stripelem_cache_destruct(void); -void seq_stripelem_cache_cleanup(); +void seq_stripelem_cache_cleanup(void); struct ImBuf * seq_stripelem_cache_get( - struct Sequence * seq, int rectx, int recty, + SeqRenderData context, struct Sequence * seq, float cfra, seq_stripelem_ibuf_t type); void seq_stripelem_cache_put( - struct Sequence * seq, int rectx, int recty, + SeqRenderData context, struct Sequence * seq, float cfra, seq_stripelem_ibuf_t type, struct ImBuf * nval); +/* ********************************************************************** + seqeffects.c -/* seqeffects.c */ -// intern? + Sequencer effect strip managment functions + ********************************************************************** +*/ + +/* intern */ struct SeqEffectHandle get_sequence_blend(struct Sequence *seq); void sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, int force); -// extern +/* extern */ struct SeqEffectHandle get_sequence_effect(struct Sequence *seq); int get_sequence_effect_num_inputs(int seq_type); + +/* ********************************************************************** + Sequencer editing functions + ********************************************************************** +*/ + /* for transform but also could use elsewhere */ int seq_tx_get_start(struct Sequence *seq); int seq_tx_get_end(struct Sequence *seq); @@ -213,6 +257,8 @@ int seq_tx_test(struct Sequence * seq); int seq_single_check(struct Sequence *seq); void seq_single_fix(struct Sequence *seq); int seq_test_overlap(struct ListBase * seqbasep, struct Sequence *test); +void seq_translate(struct Scene *scene, struct Sequence *seq, int delta); +struct Sequence *seq_foreground_frame_get(struct Scene *scene, int frame); struct ListBase *seq_seqbase(struct ListBase *seqbase, struct Sequence *seq); void seq_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); void seq_dupe_animdata(struct Scene *scene, char *name_from, char *name_to); @@ -220,14 +266,14 @@ int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test, struct Scene int shuffle_seq_time(ListBase * seqbasep, struct Scene *evil_scene); int seqbase_isolated_sel_check(struct ListBase *seqbase); void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_mem_usage, int keep_file_handles); -struct Sequence *seq_dupli_recursive(struct Scene *scene, struct Sequence * seq, int dupe_flag); +struct Sequence *seq_dupli_recursive(struct Scene *scene, struct Scene *scene_to, struct Sequence * seq, int dupe_flag); int seq_swap(struct Sequence *seq_a, struct Sequence *seq_b); void seq_update_sound(struct Scene* scene, struct Sequence *seq); void seq_update_muting(struct Scene* scene, struct Editing *ed); void seqbase_sound_reload(struct Scene *scene, ListBase *seqbase); void seqbase_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); -void seqbase_dupli_recursive(struct Scene *scene, ListBase *nseqbase, ListBase *seqbase, int dupe_flag); +void seqbase_dupli_recursive(struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag); void clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce); @@ -252,17 +298,17 @@ typedef struct SeqLoadInfo { } SeqLoadInfo; /* SeqLoadInfo.flag */ -#define SEQ_LOAD_REPLACE_SEL 1<<0 -#define SEQ_LOAD_FRAME_ADVANCE 1<<1 -#define SEQ_LOAD_MOVIE_SOUND 1<<2 -#define SEQ_LOAD_SOUND_CACHE 1<<3 +#define SEQ_LOAD_REPLACE_SEL (1<<0) +#define SEQ_LOAD_FRAME_ADVANCE (1<<1) +#define SEQ_LOAD_MOVIE_SOUND (1<<2) +#define SEQ_LOAD_SOUND_CACHE (1<<3) /* seq_dupli' flags */ -#define SEQ_DUPE_UNIQUE_NAME 1<<0 -#define SEQ_DUPE_CONTEXT 1<<1 -#define SEQ_DUPE_ANIM 1<<2 -#define SEQ_DUPE_ALL 1<<3 /* otherwise only selected are copied */ +#define SEQ_DUPE_UNIQUE_NAME (1<<0) +#define SEQ_DUPE_CONTEXT (1<<1) +#define SEQ_DUPE_ANIM (1<<2) +#define SEQ_DUPE_ALL (1<<3) /* otherwise only selected are copied */ /* use as an api function */ typedef struct Sequence *(*SeqLoadFunc)(struct bContext *, ListBase *, struct SeqLoadInfo *); diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index 47fb5049278..937a46d68dd 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -1,6 +1,4 @@ -/** - * BKE_shrinkwrap.h - * +/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -29,13 +27,17 @@ #ifndef BKE_SHRINKWRAP_H #define BKE_SHRINKWRAP_H +/** \file BKE_shrinkwrap.h + * \ingroup bke + */ + /* mesh util */ //TODO: move this somewhere else #include "BKE_customdata.h" struct DerivedMesh; struct Object; -struct DerivedMesh *object_get_derived_final(struct Scene *scene, struct Object *ob, CustomDataMask dataMask); +struct DerivedMesh *object_get_derived_final(struct Object *ob); /* SpaceTransform stuff */ @@ -121,7 +123,7 @@ typedef struct ShrinkwrapCalcData } ShrinkwrapCalcData; -void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts); +void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts); /* * This function casts a ray in the given BVHTree.. but it takes into consideration the space_transform, that is: diff --git a/source/blender/blenkernel/BKE_sketch.h b/source/blender/blenkernel/BKE_sketch.h index c46604f09f0..f42d733d583 100644 --- a/source/blender/blenkernel/BKE_sketch.h +++ b/source/blender/blenkernel/BKE_sketch.h @@ -1,5 +1,4 @@ -/** - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -25,6 +24,10 @@ #ifndef BKE_SKETCH_H #define BKE_SKETCH_H +/** \file BKE_sketch.h + * \ingroup bke + */ + typedef enum SK_PType { PT_CONTINUOUS, @@ -113,12 +116,12 @@ typedef struct SK_Gesture { /************************************************/ void freeSketch(SK_Sketch *sketch); -SK_Sketch* createSketch(); +SK_Sketch* createSketch(void); void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk); void sk_freeStroke(SK_Stroke *stk); -SK_Stroke* sk_createStroke(); +SK_Stroke* sk_createStroke(void); SK_Point *sk_lastStrokePoint(SK_Stroke *stk); diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h index 088d61061b2..16e5336bcc1 100644 --- a/source/blender/blenkernel/BKE_smoke.h +++ b/source/blender/blenkernel/BKE_smoke.h @@ -1,6 +1,4 @@ -/** - * BKE_smoke.h - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -32,9 +30,14 @@ #ifndef BKE_SMOKE_H_ #define BKE_SMOKE_H_ +/** \file BKE_smoke.h + * \ingroup bke + * \author Daniel Genrich + */ + typedef float (*bresenham_callback) (float *result, float *input, int res[3], int *pixel, float *tRay, float correct); -void smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, int useRenderParams, int isFinalCalc); +void smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm); void smokeModifier_free (struct SmokeModifierData *smd); void smokeModifier_reset(struct SmokeModifierData *smd); diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h index 738fe7dde82..6aea9344070 100644 --- a/source/blender/blenkernel/BKE_softbody.h +++ b/source/blender/blenkernel/BKE_softbody.h @@ -1,6 +1,4 @@ -/** - * BKE_softbody.h - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,10 @@ #ifndef BKE_SOFTBODY_H #define BKE_SOFTBODY_H +/** \file BKE_softbody.h + * \ingroup bke + */ + struct Object; struct Scene; struct SoftBody; diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 190b0400aff..acd4718a65a 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -1,6 +1,4 @@ -/** - * sound.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,12 @@ #ifndef BKE_SOUND_H #define BKE_SOUND_H +/** \file BKE_sound.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ + struct PackedFile; struct bSound; struct bContext; @@ -38,16 +42,16 @@ struct ListBase; struct Main; struct Sequence; -void sound_init_once(); +void sound_init_once(void); void sound_init(struct Main *main); -void sound_exit(); +void sound_exit(void); void sound_force_device(int device); -int sound_define_from_str(char *str); +int sound_define_from_str(const char *str); -struct bSound* sound_new_file(struct Main *main, char* filename); +struct bSound* sound_new_file(struct Main *main, const char *filename); // XXX unused currently #if 0 @@ -96,4 +100,6 @@ int sound_scene_playing(struct Scene *scene); int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length, float start, float end); +int sound_get_channels(struct bSound* sound); + #endif diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index 2e2b4f2bf2a..3394d5b7bf6 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -28,6 +28,10 @@ #ifndef BKE_SUBSURF_H #define BKE_SUBSURF_H +/** \file BKE_subsurf.h + * \ingroup bke + */ + struct DMGridAdjacency; struct DMGridData; struct DerivedMesh; @@ -78,7 +82,6 @@ typedef struct CCGDerivedMesh { int *reverseFaceMap; struct PBVH *pbvh; - int pbvh_draw; struct ListBase *fmap; struct IndexNode *fmap_mem; diff --git a/source/blender/blenkernel/BKE_suggestions.h b/source/blender/blenkernel/BKE_suggestions.h index 59369d6ac14..e215cabd70f 100644 --- a/source/blender/blenkernel/BKE_suggestions.h +++ b/source/blender/blenkernel/BKE_suggestions.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -29,6 +29,10 @@ #ifndef BKE_SUGGESTIONS_H #define BKE_SUGGESTIONS_H +/** \file BKE_suggestions.h + * \ingroup bke + */ + #ifdef __cplusplus extern "C" { #endif @@ -64,27 +68,27 @@ typedef struct SuggList { } SuggList; /* Free all text tool memory */ -void free_texttools(); +void free_texttools(void); /* Used to identify which Text object the current tools should appear against */ void texttool_text_set_active(Text *text); -void texttool_text_clear(); +void texttool_text_clear(void); short texttool_text_is_active(Text *text); /* Suggestions */ void texttool_suggest_add(const char *name, char type); void texttool_suggest_prefix(const char *prefix); -void texttool_suggest_clear(); -SuggItem *texttool_suggest_first(); -SuggItem *texttool_suggest_last(); +void texttool_suggest_clear(void); +SuggItem *texttool_suggest_first(void); +SuggItem *texttool_suggest_last(void); void texttool_suggest_select(SuggItem *sel); -SuggItem *texttool_suggest_selected(); -int *texttool_suggest_top(); +SuggItem *texttool_suggest_selected(void); +int *texttool_suggest_top(void); /* Documentation */ void texttool_docs_show(const char *docs); -char *texttool_docs_get(); -void texttool_docs_clear(); +char *texttool_docs_get(void); +void texttool_docs_clear(void); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index bcda86fdae4..a6b98b8ea88 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_text.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,12 @@ #ifndef BKE_TEXT_H #define BKE_TEXT_H +/** \file BKE_text.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ + #ifdef __cplusplus extern "C" { #endif @@ -43,13 +47,13 @@ struct SpaceText; void free_text (struct Text *text); void txt_set_undostate (int u); int txt_get_undostate (void); -struct Text* add_empty_text (char *name); +struct Text* add_empty_text (const char *name); int reopen_text (struct Text *text); -struct Text* add_text (char *file, const char *relpath); +struct Text* add_text (const char *file, const char *relpath); struct Text* copy_text (struct Text *ta); void unlink_text (struct Main *bmain, struct Text *text); void clear_text(struct Text *text); -void write_text(struct Text *text, char *str); +void write_text(struct Text *text, const char *str); char* txt_to_buf (struct Text *text); void txt_clean_text (struct Text *text); @@ -94,7 +98,7 @@ void indent (struct Text *text); void uncomment (struct Text *text); int setcurr_tab_spaces (struct Text *text, int space); -void txt_add_marker (struct Text *text, struct TextLine *line, int start, int end, char color[4], int group, int flags); +void txt_add_marker (struct Text *text, struct TextLine *line, int start, int end, const unsigned char color[4], int group, int flags); short txt_clear_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); short txt_clear_markers (struct Text *text, int group, int flags); struct TextMarker *txt_find_marker (struct Text *text, struct TextLine *line, int curs, int group, int flags); diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 99bb8db44ed..e6a21ec3966 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_texture.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +29,16 @@ #ifndef BKE_TEXTURE_H #define BKE_TEXTURE_H +/** \file BKE_texture.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ + +#ifdef __cplusplus +extern "C" { +#endif + struct bNode; struct Brush; struct ColorBand; @@ -40,6 +48,7 @@ struct Lamp; struct LampRen; struct Material; struct MTex; +struct ParticleSettings; struct PluginTex; struct PointDensity; struct Tex; @@ -80,6 +89,7 @@ struct Tex *give_current_material_texture(struct Material *ma); struct Tex *give_current_lamp_texture(struct Lamp *la); struct Tex *give_current_world_texture(struct World *world); struct Tex *give_current_brush_texture(struct Brush *br); +struct Tex *give_current_particle_texture(struct ParticleSettings *part); struct bNode *give_current_material_texture_node(struct Material *ma); @@ -90,6 +100,7 @@ void set_current_brush_texture(struct Brush *br, struct Tex *tex); void set_current_world_texture(struct World *wo, struct Tex *tex); void set_current_material_texture(struct Material *ma, struct Tex *tex); void set_current_lamp_texture(struct Lamp *la, struct Tex *tex); +void set_current_particle_texture(struct ParticleSettings *part, struct Tex *tex); struct TexMapping *add_mapping(void); void init_mapping(struct TexMapping *texmap); @@ -112,5 +123,9 @@ struct VoxelData *BKE_copy_voxeldata(struct VoxelData *vd); int BKE_texture_dependsOnTime(const struct Tex *texture); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h index 36ccc1f1497..0a3e56c8cba 100644 --- a/source/blender/blenkernel/BKE_unit.h +++ b/source/blender/blenkernel/BKE_unit.h @@ -1,4 +1,4 @@ -/** +/* * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -24,6 +24,10 @@ #ifndef BKE_UNIT_H #define BKE_UNIT_H +/** \file BKE_unit.h + * \ingroup bke + */ + #ifdef __cplusplus extern "C" { #endif @@ -36,19 +40,26 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system, /* replace units with values, used before python button evaluation */ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pref, int system, int type); +/* make string keyboard-friendly: 10µm --> 10um */ +void bUnit_ToUnitAltName(char *str, int len_max, char *orig_str, int system, int type); + /* the size of the unit used for this value (used for calculating the ckickstep) */ double bUnit_ClosestScalar(double value, int system, int type); /* base scale for these units */ double bUnit_BaseScalar(int system, int type); +/* return true is the unit system exists */ +int bUnit_IsValid(int system, int type); + /* loop over scales, coudl add names later */ //double bUnit_Iter(void **unit, char **name, int system, int type); -void bUnit_GetSystem(void **usys_pt, int *len, int system, int type); -char* bUnit_GetName(void *usys_pt, int index); -char* bUnit_GetNameDisplay(void *usys_pt, int index); -double bUnit_GetScaler(void *usys_pt, int index); +void bUnit_GetSystem(void **usys_pt, int *len, int system, int type); +int bUnit_GetBaseUnit(void *usys_pt); +const char* bUnit_GetName(void *usys_pt, int index); +const char* bUnit_GetNameDisplay(void *usys_pt, int index); +double bUnit_GetScaler(void *usys_pt, int index); /* aligned with PropertyUnit */ #define B_UNIT_NONE 0 @@ -60,6 +71,7 @@ double bUnit_GetScaler(void *usys_pt, int index); #define B_UNIT_TIME 6 #define B_UNIT_VELOCITY 7 #define B_UNIT_ACCELERATION 8 +#define B_UNIT_TYPE_TOT 9 #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index e4f81625031..0e2817365f8 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -27,6 +27,13 @@ * ***** END GPL LICENSE BLOCK ***** */ +/** \file BKE_utildefines.h + * \ingroup bke + * \brief blender format spesific macros + * \note generic defines should go in BLI_utildefines.h + */ + + #ifndef BKE_UTILDEFINES_H #define BKE_UTILDEFINES_H @@ -34,17 +41,6 @@ extern "C" { #endif -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -/* Macro to convert a value to string in the preprocessor */ -#define QUOTE(x) #x - /* these values need to be hardcoded in structs, dna does not recognize defines */ /* also defined in DNA_space_types.h */ #ifndef FILE_MAXDIR @@ -53,96 +49,6 @@ extern "C" { #define FILE_MAX 240 #endif -#define ELEM(a, b, c) ( (a)==(b) || (a)==(c) ) -#define ELEM3(a, b, c, d) ( ELEM(a, b, c) || (a)==(d) ) -#define ELEM4(a, b, c, d, e) ( ELEM(a, b, c) || ELEM(a, d, e) ) -#define ELEM5(a, b, c, d, e, f) ( ELEM(a, b, c) || ELEM3(a, d, e, f) ) -#define ELEM6(a, b, c, d, e, f, g) ( ELEM(a, b, c) || ELEM4(a, d, e, f, g) ) -#define ELEM7(a, b, c, d, e, f, g, h) ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) ) -#define ELEM8(a, b, c, d, e, f, g, h, i) ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) ) -#define ELEM9(a, b, c, d, e, f, g, h, i, j) ( ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) ) -#define ELEM10(a, b, c, d, e, f, g, h, i, j, k) ( ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) ) -#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l) ( ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) ) - -/* shift around elements */ -#define SHIFT3(type, a, b, c) { type tmp; tmp = a; a = c; c = b; b = tmp; } -#define SHIFT4(type, a, b, c, d) { type tmp; tmp = a; a = d; d = c; c = b; b = tmp; } - -/* min/max */ -#define MIN2(x,y) ( (x)<(y) ? (x) : (y) ) -#define MIN3(x,y,z) MIN2( MIN2((x),(y)) , (z) ) -#define MIN4(x,y,z,a) MIN2( MIN2((x),(y)) , MIN2((z),(a)) ) - -#define MAX2(x,y) ( (x)>(y) ? (x) : (y) ) -#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) ) -#define MAX4(x,y,z,a) MAX2( MAX2((x),(y)) , MAX2((z),(a)) ) - -#define INIT_MINMAX(min, max) { (min)[0]= (min)[1]= (min)[2]= 1.0e30f; (max)[0]= (max)[1]= (max)[2]= -1.0e30f; } - -#define INIT_MINMAX2(min, max) { (min)[0]= (min)[1]= 1.0e30f; (max)[0]= (max)[1]= -1.0e30f; } - -#define DO_MIN(vec, min) { if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \ - if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \ - if( (min)[2]>(vec)[2] ) (min)[2]= (vec)[2]; } \ - -#define DO_MAX(vec, max) { if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \ - if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1]; \ - if( (max)[2]<(vec)[2] ) (max)[2]= (vec)[2]; } \ - -#define DO_MINMAX(vec, min, max) { if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \ - if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \ - if( (min)[2]>(vec)[2] ) (min)[2]= (vec)[2]; \ - if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \ - if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1]; \ - if( (max)[2]<(vec)[2] ) (max)[2]= (vec)[2]; } \ - -#define DO_MINMAX2(vec, min, max) { if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \ - if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \ - if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \ - if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1]; } - -/* some math and copy defines */ - -#ifndef SWAP -#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; } -#endif - -#define ABS(a) ( (a)<0 ? (-(a)) : (a) ) - -#define AVG2(x, y) ( 0.5 * ((x) + (y)) ) - -#define FTOCHAR(val) ((val)<=0.0f)? 0 : (((val)>(1.0f-0.5f/255.0f))? 255 : (char)((255.0f*(val))+0.5f)) -#define FTOUSHORT(val) ((val >= 1.0f-0.5f/65535)? 65535: (val <= 0.0f)? 0: (unsigned short)(val*65535.0f + 0.5f)) - -#define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);} -#define VECCOPY2D(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1);} -#define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);} -#define LONGCOPY(a, b, c) {int lcpc=c, *lcpa=(int *)a, *lcpb=(int *)b; while(lcpc-->0) *(lcpa++)= *(lcpb++);} - - -#define VECADD(v1,v2,v3) {*(v1)= *(v2) + *(v3); *(v1+1)= *(v2+1) + *(v3+1); *(v1+2)= *(v2+2) + *(v3+2);} -#define VECSUB(v1,v2,v3) {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1); *(v1+2)= *(v2+2) - *(v3+2);} -#define VECSUB2D(v1,v2,v3) {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1);} -#define VECMUL(v1, fac) {v1[0] *= fac; v1[1] *= fac; v1[2] *= fac;} - -#define VECADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac);} -#define VECSUBFAC(v1,v2,v3,fac) {*(v1)= *(v2) - *(v3)*(fac); *(v1+1)= *(v2+1) - *(v3+1)*(fac); *(v1+2)= *(v2+2) - *(v3+2)*(fac);} -#define QUATADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac); *(v1+3)= *(v2+3) + *(v3+3)*(fac);} - -#define INPR(v1, v2) ( (v1)[0]*(v2)[0] + (v1)[1]*(v2)[1] + (v1)[2]*(v2)[2] ) - - -/* some misc stuff.... */ -#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c) -#define CLAMPIS(a, b, c) ((a)<(b) ? (b) : (a)>(c) ? (c) : (a)) -#define CLAMPTEST(a, b, c) if((b)<(c)) {CLAMP(a, b, c);} else {CLAMP(a, c, b);} - -#define IS_EQ(a,b) ((fabs((double)(a)-(b)) >= (double) FLT_EPSILON) ? 0 : 1) - -#define IS_EQT(a, b, c) ((a > b)? (((a-b) <= c)? 1:0) : ((((b-a) <= c)? 1:0))) -#define IN_RANGE(a, b, c) ((b < c)? ((b<a && a<c)? 1:0) : ((c<a && a<b)? 1:0)) -#define IN_RANGE_INCL(a, b, c) ((b < c)? ((b<=a && a<=c)? 1:0) : ((c<=a && a<=b)? 1:0)) - /* this weirdo pops up in two places ... */ #if !defined(WIN32) #ifndef O_BINARY @@ -161,15 +67,8 @@ extern "C" { #define ID_NEW(a) if( (a) && (a)->id.newid ) (a)= (void *)(a)->id.newid -#define FORM MAKE_ID('F','O','R','M') - -#define BLEN MAKE_ID('B','L','E','N') -#define DER_ MAKE_ID('D','E','R','_') -#define V100 MAKE_ID('V','1','0','0') - #define DATA MAKE_ID('D','A','T','A') #define GLOB MAKE_ID('G','L','O','B') -#define IMAG MAKE_ID('I','M','A','G') #define DNA1 MAKE_ID('D','N','A','1') #define TEST MAKE_ID('T','E','S','T') /* used as preview between 'REND' and 'GLOB' */ @@ -178,28 +77,6 @@ extern "C" { #define ENDB MAKE_ID('E','N','D','B') - -/* This one rotates the bytes in an int64, int (32) and short (16) */ -#define SWITCH_INT64(a) { \ - char s_i, *p_i; \ - p_i= (char *)&(a); \ - s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \ - s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \ - s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \ - s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; } - -#define SWITCH_INT(a) { \ - char s_i, *p_i; \ - p_i= (char *)&(a); \ - s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \ - s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; } - -#define SWITCH_SHORT(a) { \ - char s_i, *p_i; \ - p_i= (char *)&(a); \ - s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; } - - /* Bit operations */ #define BTST(a,b) ( ( (a) & 1<<(b) )!=0 ) #define BNTST(a,b) ( ( (a) & 1<<(b) )==0 ) @@ -209,17 +86,7 @@ extern "C" { /* bit-row */ #define BROW(min, max) (((max)>=31? 0xFFFFFFFF: (1<<(max+1))-1) - ((min)? ((1<<(min))-1):0) ) - -#ifdef GS -#undef GS -#endif -#define GS(a) (*((short *)(a))) - -/* Warning-free macros for storing ints in pointers. Use these _only_ - * for storing an int in a pointer, not a pointer in an int (64bit)! */ -#define SET_INT_IN_POINTER(i) ((void*)(intptr_t)(i)) -#define GET_INT_FROM_POINTER(i) ((int)(intptr_t)(i)) - +#define BMEMSET(mem, val, size) {unsigned int _i; char *_c = (char*) mem; for (_i=0; _i<size; _i++) *_c++ = val;} /*little macro so inline keyword works*/ #if defined(_MSC_VER) #define BM_INLINE static __forceinline @@ -227,9 +94,9 @@ extern "C" { #define BM_INLINE static inline __attribute((always_inline)) #endif -#define BMEMSET(mem, val, size) {unsigned int _i; char *_c = (char*) mem; for (_i=0; _i<size; _i++) *_c++ = val;} - #ifdef __cplusplus } #endif -#endif + +#endif // BKE_UTILDEFINES_H + diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h index 9d763e8f003..30780b87085 100644 --- a/source/blender/blenkernel/BKE_world.h +++ b/source/blender/blenkernel/BKE_world.h @@ -1,6 +1,4 @@ -/** - * blenlib/BKE_world.h (mar-2001 nzc) - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,10 +29,16 @@ #ifndef BKE_WORLD_H #define BKE_WORLD_H +/** \file BKE_world.h + * \ingroup bke + * \since March 2001 + * \author nzc + */ + struct World; void free_world(struct World *sc); -struct World *add_world(char *name); +struct World *add_world(const char *name); struct World *copy_world(struct World *wrld); void make_local_world(struct World *wrld); diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h index c7f26d9b76c..19cc1ae2dbf 100644 --- a/source/blender/blenkernel/BKE_writeavi.h +++ b/source/blender/blenkernel/BKE_writeavi.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -30,6 +30,10 @@ #ifndef BKE_WRITEAVI_H #define BKE_WRITEAVI_H +/** \file BKE_writeavi.h + * \ingroup bke + */ + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 311676b37b5..2b10f1b246c 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -1,4 +1,4 @@ -/** +/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -28,6 +28,10 @@ #ifndef BKE_WRITEFFMPEG_H #define BKE_WRITEFFMPEG_H +/** \file BKE_writeffmpeg.h + * \ingroup bke + */ + #ifdef WITH_FFMPEG #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_writeframeserver.h b/source/blender/blenkernel/BKE_writeframeserver.h index 036e0dbd774..2117a23b938 100644 --- a/source/blender/blenkernel/BKE_writeframeserver.h +++ b/source/blender/blenkernel/BKE_writeframeserver.h @@ -1,4 +1,4 @@ -/** +/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -28,6 +28,10 @@ #ifndef BKE_WRITEFRAMESERVER_H #define BKE_WRITEFRAMESERVER_H +/** \file BKE_writeframeserver.h + * \ingroup bke + */ + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b196ddc8509..dc485f5dc5f 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -24,94 +24,288 @@ # # ***** END GPL LICENSE BLOCK ***** -FILE(GLOB SRC intern/*.c) - -SET(INC - . ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna ../modifiers - ../render/extern/include ../../../intern/decimation/extern - ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern - ../../../intern/iksolver/extern ../blenloader ../ikplugin ../bmesh - ../nodes ../../../extern/glew/include ../gpu ../makesrna ../../../intern/smoke/extern - ../../../intern/bsp/extern ../blenfont +set(INC + . + ../avi + ../blenlib + ../blenloader + ../gpu + ../ikplugin + ../imbuf + ../makesdna + ../makesrna + ../bmesh + ../modifiers + ../nodes + ../editors/include + ../render/extern/include + ../../../extern/glew/include ../../../intern/audaspace/intern + ../../../intern/bsp/extern ../blenfont + ../../../intern/decimation/extern + ../../../intern/elbeem/extern + ../../../intern/guardedalloc + ../../../intern/iksolver/extern + ../../../intern/memutil + ../../../intern/opennl/extern + ../../../intern/smoke/extern + ../../../intern/mikktspace ../../../source/blender/windowmanager # XXX - BAD LEVEL CALL WM_api.h - ${ZLIB_INC} + ${ZLIB_INCLUDE_DIRS} ) +set(SRC + intern/BME_Customdata.c + intern/BME_conversions.c + intern/BME_eulers.c + intern/BME_mesh.c + intern/BME_structure.c + intern/BME_tools.c + intern/CCGSubSurf.c + intern/DerivedMesh.c + intern/action.c + intern/anim.c + intern/anim_sys.c + intern/armature.c + intern/blender.c + intern/bmfont.c + intern/boids.c + intern/booleanops_mesh.c + intern/brush.c + intern/bullet.c + intern/bvhutils.c + intern/cdderivedmesh.c + intern/cloth.c + intern/collision.c + intern/colortools.c + intern/constraint.c + intern/context.c + intern/curve.c + intern/customdata.c + intern/customdata_file.c + intern/deform.c + intern/depsgraph.c + intern/displist.c + intern/effect.c + intern/editderivedbmesh.c + intern/exotic.c + intern/fcurve.c + intern/fluidsim.c + intern/fmodifier.c + intern/font.c + intern/gpencil.c + intern/group.c + intern/icons.c + intern/idcode.c + intern/idprop.c + intern/image.c + intern/image_gen.c + intern/implicit.c + intern/ipo.c + intern/key.c + intern/lattice.c + intern/library.c + intern/material.c + intern/mball.c + intern/mesh.c + intern/mesh_validate.c + intern/modifier.c + intern/modifiers_bmesh.c + intern/multires.c + intern/nla.c + intern/node.c + intern/object.c + intern/packedFile.c + intern/paint.c + intern/particle.c + intern/particle_system.c + intern/pointcache.c + intern/property.c + intern/report.c + intern/sca.c + intern/scene.c + intern/screen.c + intern/script.c + intern/seqcache.c + intern/seqeffects.c + intern/sequencer.c + intern/shrinkwrap.c + intern/sketch.c + intern/smoke.c + intern/softbody.c + intern/sound.c + intern/subsurf_ccg.c + intern/suggestions.c + intern/text.c + intern/texture.c + intern/unit.c + intern/world.c + intern/writeavi.c + intern/writeffmpeg.c + intern/writeframeserver.c + + BKE_DerivedMesh.h + BKE_action.h + BKE_anim.h + BKE_animsys.h + BKE_armature.h + BKE_array_mallocn.h + BKE_blender.h + BKE_bmesh.h + BKE_bmeshCustomData.h + BKE_bmfont.h + BKE_bmfont_types.h + BKE_boids.h + BKE_booleanops_mesh.h + BKE_brush.h + BKE_bullet.h + BKE_bvhutils.h + BKE_cdderivedmesh.h + BKE_cloth.h + BKE_collision.h + BKE_colortools.h + BKE_constraint.h + BKE_context.h + BKE_curve.h + BKE_customdata.h + BKE_customdata_file.h + BKE_deform.h + BKE_depsgraph.h + BKE_displist.h + BKE_effect.h + BKE_endian.h + BKE_exotic.h + BKE_fcurve.h + BKE_fluidsim.h + BKE_font.h + BKE_global.h + BKE_gpencil.h + BKE_group.h + BKE_icons.h + BKE_idcode.h + BKE_idprop.h + BKE_image.h + BKE_ipo.h + BKE_key.h + BKE_lattice.h + BKE_library.h + BKE_main.h + BKE_material.h + BKE_mball.h + BKE_mesh.h + BKE_modifier.h + BKE_multires.h + BKE_nla.h + BKE_node.h + BKE_object.h + BKE_packedFile.h + BKE_paint.h + BKE_particle.h + BKE_plugin_types.h + BKE_pointcache.h + BKE_property.h + BKE_report.h + BKE_sca.h + BKE_scene.h + BKE_screen.h + BKE_script.h + BKE_sequencer.h + BKE_shrinkwrap.h + BKE_sketch.h + BKE_smoke.h + BKE_softbody.h + BKE_sound.h + BKE_subsurf.h + BKE_suggestions.h + BKE_text.h + BKE_texture.h + BKE_unit.h + BKE_utildefines.h + BKE_world.h + BKE_writeavi.h + BKE_writeffmpeg.h + BKE_writeframeserver.h + depsgraph_private.h + intern/CCGSubSurf.h + intern/bmesh_private.h + nla_private.h +) -ADD_DEFINITIONS(-DGLEW_STATIC) +add_definitions(-DGLEW_STATIC) -IF(WITH_BULLET) - SET(INC ${INC} ../../../extern/bullet2/src) - ADD_DEFINITIONS(-DUSE_BULLET) -ENDIF(WITH_BULLET) +if(WITH_BULLET) + list(APPEND INC ../../../extern/bullet2/src) + add_definitions(-DUSE_BULLET) +endif() -IF(WITH_IMAGE_OPENEXR) - ADD_DEFINITIONS(-DWITH_OPENEXR) -ENDIF(WITH_IMAGE_OPENEXR) +if(WITH_IMAGE_OPENEXR) + add_definitions(-DWITH_OPENEXR) +endif() -IF(WITH_IMAGE_TIFF) - ADD_DEFINITIONS(-DWITH_TIFF) -ENDIF(WITH_IMAGE_TIFF) +if(WITH_IMAGE_TIFF) + add_definitions(-DWITH_TIFF) +endif() -IF(WITH_IMAGE_OPENJPEG) - ADD_DEFINITIONS(-DWITH_OPENJPEG) -ENDIF(WITH_IMAGE_OPENJPEG) +if(WITH_IMAGE_OPENJPEG) + add_definitions(-DWITH_OPENJPEG) +endif() -IF(WITH_IMAGE_DDS) - ADD_DEFINITIONS(-DWITH_DDS) -ENDIF(WITH_IMAGE_DDS) +if(WITH_IMAGE_DDS) + add_definitions(-DWITH_DDS) +endif() -IF(WITH_IMAGE_CINEON) - ADD_DEFINITIONS(-DWITH_CINEON) -ENDIF(WITH_IMAGE_CINEON) +if(WITH_IMAGE_CINEON) + add_definitions(-DWITH_CINEON) +endif() -IF(WITH_IMAGE_HDR) - ADD_DEFINITIONS(-DWITH_HDR) -ENDIF(WITH_IMAGE_HDR) +if(WITH_IMAGE_HDR) + add_definitions(-DWITH_HDR) +endif() -IF(WITH_QUICKTIME) - SET(INC ${INC} ../quicktime ${QUICKTIME_INC}) - ADD_DEFINITIONS(-DWITH_QUICKTIME) -ENDIF(WITH_QUICKTIME) +if(WITH_CODEC_QUICKTIME) + list(APPEND INC ../quicktime ${QUICKTIME_INC}) + add_definitions(-DWITH_QUICKTIME) +endif() -IF(WITH_FFMPEG) - SET(INC ${INC} ${FFMPEG_INC}) - ADD_DEFINITIONS(-DWITH_FFMPEG) -ENDIF(WITH_FFMPEG) +if(WITH_CODEC_FFMPEG) + list(APPEND INC ${FFMPEG_INC}) + add_definitions(-DWITH_FFMPEG) +endif() -IF(WITH_LCMS) - SET(INC ${INC} ${LCMS_INCLUDE_DIR}) - ADD_DEFINITIONS(-DWITH_LCMS) -ENDIF(WITH_LCMS) +if(WITH_LCMS) + list(APPEND INC ${LCMS_INCLUDE_DIR}) + add_definitions(-DWITH_LCMS) +endif() -IF(WITH_PYTHON) - SET(INC ${INC} ../python ${PYTHON_INC}) -ELSE(WITH_PYTHON) - ADD_DEFINITIONS(-DDISABLE_PYTHON) -ENDIF(WITH_PYTHON) +if(WITH_PYTHON) + list(APPEND INC ../python ${PYTHON_INCLUDE_DIRS}) + add_definitions(-DWITH_PYTHON) +endif() -IF(WITH_OPENMP) - ADD_DEFINITIONS(-DPARALLEL=1) -ENDIF(WITH_OPENMP) +if(WITH_OPENMP) + add_definitions(-DPARALLEL=1) +endif() -IF(NOT WITH_FLUID) - ADD_DEFINITIONS(-DDISABLE_ELBEEM) -ENDIF(NOT WITH_FLUID) +if(NOT WITH_MOD_FLUID) + add_definitions(-DDISABLE_ELBEEM) +endif() -IF(WITH_LZO) - SET(INC ${INC} ../../../extern/lzo/minilzo) - ADD_DEFINITIONS(-DWITH_LZO) -ENDIF(WITH_LZO) +if(WITH_JACK) + add_definitions(-DWITH_JACK) +endif() -IF(WITH_LZMA) - SET(INC ${INC} ../../../extern/lzma) - ADD_DEFINITIONS(-DWITH_LZMA) -ENDIF(WITH_LZMA) +if(WITH_LZO) + list(APPEND INC ../../../extern/lzo/minilzo) + add_definitions(-DWITH_LZO) +endif() -IF(WIN32) - SET(INC ${INC} ${PTHREADS_INC}) -ENDIF(WIN32) +if(WITH_LZMA) + list(APPEND INC ../../../extern/lzma) + add_definitions(-DWITH_LZMA) +endif() -BLENDERLIB(bf_blenkernel "${SRC}" "${INC}") +if(MSVC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") +endif() +blender_add_lib(bf_blenkernel "${SRC}" "${INC}") diff --git a/source/blender/blenkernel/Makefile b/source/blender/blenkernel/Makefile deleted file mode 100644 index dc5f0a91da6..00000000000 --- a/source/blender/blenkernel/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# -# $Id$ -# -# ***** 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): none yet. -# -# ***** END GPL LICENSE BLOCK ***** -# -# Bounces make to subdirectories. - -SOURCEDIR = source/blender/blenkernel -DIRS = intern - -include nan_subdirs.mk diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 51c42bf4c7d..33c6a170178 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -13,6 +13,7 @@ incs += ' #/intern/opennl/extern #/intern/bsp/extern' incs += ' ../gpu #/extern/glew/include' incs += ' ../bmesh' incs += ' #/intern/smoke/extern' +incs += ' #/intern/mikktspace' incs += ' #/intern/audaspace/intern' incs += ' ' + env['BF_OPENGL_INC'] @@ -20,71 +21,76 @@ incs += ' ' + env['BF_ZLIB_INC'] defs = [ 'GLEW_STATIC' ] -if not env['WITH_BF_PYTHON']: - defs.append('DISABLE_PYTHON') -else: - incs += ' ../python' - incs += ' ' + env['BF_PYTHON_INC'] - if env['BF_DEBUG']: - defs.append('_DEBUG') +if env['WITH_BF_PYTHON']: + incs += ' ../python' + incs += ' ' + env['BF_PYTHON_INC'] + defs.append('WITH_PYTHON') + if env['BF_DEBUG']: + defs.append('DEBUG') if env['WITH_BF_QUICKTIME']: - incs += ' ../quicktime' + incs += ' ../quicktime' if env['WITH_BF_SDL']: - incs += ' ' + env['BF_SDL_INC'] + incs += ' ' + env['BF_SDL_INC'] else: - defs.append('DISABLE_SDL') + defs.append('DISABLE_SDL') if env['WITH_BF_OPENEXR']: - defs.append('WITH_OPENEXR') + defs.append('WITH_OPENEXR') if env['WITH_BF_TIFF']: - defs.append('WITH_TIFF') + defs.append('WITH_TIFF') if env['WITH_BF_OPENJPEG']: - defs.append('WITH_OPENJPEG') + defs.append('WITH_OPENJPEG') if env['WITH_BF_DDS']: - defs.append('WITH_DDS') + defs.append('WITH_DDS') if env['WITH_BF_CINEON']: - defs.append('WITH_CINEON') + defs.append('WITH_CINEON') if env['WITH_BF_HDR']: - defs.append('WITH_HDR') + defs.append('WITH_HDR') + +if env['WITH_BF_JACK']: + defs.append('WITH_JACK') if env['WITH_BF_FFMPEG']: - defs.append('WITH_FFMPEG') - incs += ' ' + env['BF_FFMPEG_INC'] + defs.append('WITH_FFMPEG') + incs += ' ' + env['BF_FFMPEG_INC'] if env['WITH_BF_QUICKTIME']: - defs.append('WITH_QUICKTIME') - incs += ' ' + env['BF_QUICKTIME_INC'] + defs.append('WITH_QUICKTIME') + incs += ' ' + env['BF_QUICKTIME_INC'] if env['WITH_BF_BULLET']: - defs.append('USE_BULLET') + defs.append('USE_BULLET') if env['OURPLATFORM'] == 'darwin': if env['WITH_BF_OPENMP']: defs.append('PARALLEL=1') if env['BF_NO_ELBEEM']: - defs.append('DISABLE_ELBEEM') + defs.append('DISABLE_ELBEEM') if env['WITH_BF_LCMS']: - defs.append('WITH_LCMS') - incs += ' ' + env['BF_LCMS_INC'] + defs.append('WITH_LCMS') + incs += ' ' + env['BF_LCMS_INC'] if env['WITH_BF_LZO']: - incs += ' #/extern/lzo/minilzo' - defs.append('WITH_LZO') + incs += ' #/extern/lzo/minilzo' + defs.append('WITH_LZO') if env['WITH_BF_LZMA']: - incs += ' #/extern/lzma' - defs.append('WITH_LZMA') + incs += ' #/extern/lzma' + defs.append('WITH_LZMA') if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): incs += ' ' + env['BF_PTHREADS_INC'] -env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [166,25] ) +if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [166,25]) #, cc_compileflags = env['CCFLAGS'].append('/WX') ) +else: + env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player', 'player2'], priority = [166,25,0] ) diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h index 503ee973be0..4f99dacbc08 100644 --- a/source/blender/blenkernel/depsgraph_private.h +++ b/source/blender/blenkernel/depsgraph_private.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -51,7 +51,7 @@ typedef struct DagAdjList short type; int count; // number of identical arcs unsigned int lay; // for flushing redraw/rebuild events - char *name; + const char *name; struct DagAdjList *next; } DagAdjList; @@ -64,8 +64,8 @@ typedef struct DagNode void * ob; void * first_ancestor; int ancestor_count; - int lay; // accumulated layers of its relations + itself - int scelay; // layers due to being in scene + unsigned int lay; // accumulated layers of its relations + itself + unsigned int scelay; // layers due to being in scene int lasttime; // if lasttime != DagForest->time, this node was not evaluated yet for flushing int BFS_dist; // BFS distance int DFS_dist; // DFS distance @@ -117,7 +117,7 @@ DagNode * dag_find_node (DagForest *forest,void * fob); DagNode * dag_add_node (DagForest *forest,void * fob); DagNode * dag_get_node (DagForest *forest,void * fob); DagNode * dag_get_sub_node (DagForest *forest,void * fob); -void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name); +void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name); void graph_bfs(void); diff --git a/source/blender/blenkernel/intern/BME_Customdata.c b/source/blender/blenkernel/intern/BME_Customdata.c index 139f07c3902..f8b432ed384 100644 --- a/source/blender/blenkernel/intern/BME_Customdata.c +++ b/source/blender/blenkernel/intern/BME_Customdata.c @@ -1,5 +1,6 @@ #if 0 /** +/* * BME_customdata.c jan 2007 * * Custom Data functions for Bmesh @@ -44,7 +45,7 @@ /********************* Layer type information **********************/ typedef struct BME_LayerTypeInfo { int size; - char *defaultname; + const char *defaultname; void (*copy)(const void *source, void *dest, int count); void (*free)(void *data, int count, int size); void (*interp)(void **sources, float *weights, float *sub_weights, int count, void *dest); diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c index 439b77db9a6..8c399e88d67 100644 --- a/source/blender/blenkernel/intern/BME_conversions.c +++ b/source/blender/blenkernel/intern/BME_conversions.c @@ -1,5 +1,6 @@ #if 0 /** +/* * BME_mesh.c jan 2007 * * BMesh mesh level functions. @@ -39,10 +40,12 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BLI_edgehash.h" +#include "BLI_utildefines.h" + #include "BKE_mesh.h" #include "BKE_cdderivedmesh.h" -#include "BLI_edgehash.h" //XXX #include "BIF_editmesh.h" //XXX #include "editmesh.h" #include "bmesh_private.h" diff --git a/source/blender/blenkernel/intern/BME_eulers.c b/source/blender/blenkernel/intern/BME_eulers.c index baa490bbeb5..6897b0c8990 100644 --- a/source/blender/blenkernel/intern/BME_eulers.c +++ b/source/blender/blenkernel/intern/BME_eulers.c @@ -1,5 +1,6 @@ #if 0 /** +/* * BME_eulers.c jan 2007 * * BMesh Euler construction API. @@ -34,7 +35,7 @@ */ #include "MEM_guardedalloc.h" - +#include "BLI_utildefines.h" #include "bmesh_private.h" diff --git a/source/blender/blenkernel/intern/BME_mesh.c b/source/blender/blenkernel/intern/BME_mesh.c index 938b193a433..1097b9da2bc 100644 --- a/source/blender/blenkernel/intern/BME_mesh.c +++ b/source/blender/blenkernel/intern/BME_mesh.c @@ -1,5 +1,6 @@ #if 0 /** +/* * BME_mesh.c jan 2007 * * BMesh mesh level functions. diff --git a/source/blender/blenkernel/intern/BME_structure.c b/source/blender/blenkernel/intern/BME_structure.c index 53cf93c43af..f79b8edc866 100644 --- a/source/blender/blenkernel/intern/BME_structure.c +++ b/source/blender/blenkernel/intern/BME_structure.c @@ -1,5 +1,6 @@ #if 0 /** +/* * BME_structure.c jan 2007 * * Low level routines for manipulating the BMesh structure. @@ -34,8 +35,9 @@ */ #if 0 #include <limits.h> -#include "MEM_guardedalloc.h" +#include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BKE_bmesh.h" /** * MISC utility functions. diff --git a/source/blender/blenkernel/intern/BME_tools.c b/source/blender/blenkernel/intern/BME_tools.c index 66df8f2ad6a..9dd4669ba1f 100644 --- a/source/blender/blenkernel/intern/BME_tools.c +++ b/source/blender/blenkernel/intern/BME_tools.c @@ -1,5 +1,6 @@ #if 0 /** +/* * BME_tools.c jan 2007 * * Functions for changing the topology of a mesh. @@ -39,9 +40,14 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" -#include "BKE_bmesh.h" #include "BLI_math.h" +<<<<<<< .working #include "BLI_cellalloc.h" +======= +#include "BLI_utildefines.h" +>>>>>>> .merge-right.r35190 + +#include "BKE_bmesh.h" /*split this all into a seperate bevel.c file in src*/ @@ -109,7 +115,7 @@ float *BME_new_transdata_float(BME_TransData_Head *td) { return BLI_memarena_alloc(td->ma, sizeof(float)); } -static int BME_is_nonmanifold_vert(BME_Mesh *bm, BME_Vert *v) { +static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) { BME_Edge *e, *oe; BME_Loop *l; int len, count, flag; @@ -219,7 +225,7 @@ static void BME_data_interp_from_verts(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, #endif -static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Vert *v, BME_Edge *e1, float fac){ +static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *UNUSED(v2), BME_Vert *v, BME_Edge *e1, float fac){ void *src[2]; float w[2]; BME_Loop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL; @@ -358,7 +364,7 @@ static int BME_bevel_get_vec(float *vec, BME_Vert *v1, BME_Vert *v2, BME_TransDa * vec2 is the direction of projection (pointing away from vec1) * up_vec is used for orientation (expected to be normalized) * returns the length of the projected vector that lies along vec1 */ -static float BME_bevel_project_vec(float *vec1, float *vec2, float *up_vec, int is_forward, BME_TransData_Head *td) { +static float BME_bevel_project_vec(float *vec1, float *vec2, float *up_vec, int is_forward, BME_TransData_Head *UNUSED(td)) { float factor, vec3[3], tmp[3],c1,c2; cross_v3_v3v3(tmp,vec1,vec2); @@ -584,7 +590,7 @@ static float BME_bevel_set_max(BME_Vert *v1, BME_Vert *v2, float value, BME_Tran return max; } -static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, int options, BME_TransData_Head *td) { +static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, int UNUSED(options), BME_TransData_Head *td) { BME_Vert *ov1, *ov2, *v1, *v2; ov1 = BME_edge_getothervert(v->e, v); @@ -609,7 +615,7 @@ static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, return v1; } -static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int options, float *up_vec, BME_TransData_Head *td) { +static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUSED(options), float *up_vec, BME_TransData_Head *td) { BME_Vert *v1, *v2, *kv; BME_Loop *kl=NULL, *nl; BME_Edge *e; @@ -710,7 +716,7 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int opti return l; } -static BME_Loop *BME_bevel_vert(BME_Mesh *bm, BME_Loop *l, float value, int options, float *up_vec, BME_TransData_Head *td) { +static BME_Loop *BME_bevel_vert(BME_Mesh *bm, BME_Loop *l, float value, int UNUSED(options), float *up_vec, BME_TransData_Head *td) { BME_Vert *v1, *v2; BME_Poly *f; @@ -861,7 +867,7 @@ static void BME_bevel_add_vweight(BME_TransData_Head *td, BME_Mesh *bm, BME_Vert } } -static float BME_bevel_get_angle(BME_Mesh *bm, BME_Edge *e, BME_Vert *v) { +static float BME_bevel_get_angle(BME_Mesh *UNUSED(bm), BME_Edge *e, BME_Vert *v) { BME_Vert *v1, *v2; BME_Loop *l1, *l2; float vec1[3], vec2[3], vec3[3], vec4[3]; @@ -920,7 +926,7 @@ static int BME_face_sharededges(BME_Poly *f1, BME_Poly *f2){ * Returns - * A BME_Mesh pointer to the BMesh passed as a parameter. */ -static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int defgrp_index, float angle, BME_TransData_Head *td) { +static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defgrp_index), float angle, BME_TransData_Head *td) { BME_Vert *v; BME_Edge *e; BME_Poly *f; @@ -1164,7 +1170,7 @@ static void bmesh_dissolve_disk(BME_Mesh *bm, BME_Vert *v){ //BME_JEKV(bm,v->e,v); } } -static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int defgrp_index, BME_TransData_Head *td) { +static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int UNUSED(defgrp_index), BME_TransData_Head *td) { BME_Vert *v, *nv; BME_Edge *e, *oe; BME_Loop *l, *l2; diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index bbd68fb797b..3564c93681a 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -15,6 +15,13 @@ #define CCG_INLINE inline #endif +/* copied from BKE_utildefines.h ugh */ +#ifdef __GNUC__ +# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) +#else +# define UNUSED(x) x +#endif + /* used for normalize_v3 in BLI_math_vector * float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */ #define EPSILON (1.0e-35f) @@ -185,13 +192,13 @@ static int _ehashIterator_isStopped(EHashIterator *ehi) { /***/ -static void *_stdAllocator_alloc(CCGAllocatorHDL a, int numBytes) { +static void *_stdAllocator_alloc(CCGAllocatorHDL UNUSED(a), int numBytes) { return malloc(numBytes); } -static void *_stdAllocator_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) { +static void *_stdAllocator_realloc(CCGAllocatorHDL UNUSED(a), void *ptr, int newSize, int UNUSED(oldSize)) { return realloc(ptr, newSize); } -static void _stdAllocator_free(CCGAllocatorHDL a, void *ptr) { +static void _stdAllocator_free(CCGAllocatorHDL UNUSED(a), void *ptr) { free(ptr); } @@ -236,13 +243,13 @@ enum { Vert_eEffected= (1<<0), Vert_eChanged= (1<<1), Vert_eSeam= (1<<2), -} VertFlags; +} /*VertFlags*/; enum { Edge_eEffected= (1<<0), -} CCGEdgeFlags; +} /*CCGEdgeFlags*/; enum { Face_eEffected= (1<<0), -} FaceFlags; +} /*FaceFlags*/; struct _CCGVert { CCGVert *next; /* EHData.next */ @@ -390,7 +397,7 @@ static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) { (e->v1==v && e->v0==vQ)) return e; } - return 0; + return NULL; } static int _vert_isBoundary(CCGVert *v) { int i; @@ -592,7 +599,7 @@ static CCG_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int e static float *_face_getIFNoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset) { return (float*) ((byte*) _face_getIFCoEdge(f, e, lvl, eX, eY, levels, dataSize) + normalDataOffset); } -void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float *no, int levels, int dataSize) { +static void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float *no, int levels, int dataSize) { float *a = _face_getIFCo(f, lvl, S, x+0, y+0, levels, dataSize); float *b = _face_getIFCo(f, lvl, S, x+1, y+0, levels, dataSize); float *c = _face_getIFCo(f, lvl, S, x+1, y+1, levels, dataSize); @@ -1514,7 +1521,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, } } - if (seam && seamEdges < 2) + if (seamEdges < 2 || seamEdges != v->numEdges) seam = 0; if (!v->numEdges) { @@ -1942,7 +1949,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) { } } - if (seam && seamEdges < 2) + if (seamEdges < 2 || seamEdges != v->numEdges) seam = 0; if (!v->numEdges) { @@ -2601,7 +2608,7 @@ float ccgSubSurf_getEdgeCrease(CCGEdge *e) { /* Face accessors */ -CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *ss, CCGFace *f) { +CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *UNUSED(ss), CCGFace *f) { return f->fHDL; } int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f) { @@ -2619,14 +2626,14 @@ void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f) { int ccgSubSurf_getFaceNumVerts(CCGFace *f) { return f->numVerts; } -CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *ss, CCGFace *f, int index) { +CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *UNUSED(ss), CCGFace *f, int index) { if (index<0 || index>=f->numVerts) { return NULL; } else { return FACE_getVerts(f)[index]; } } -CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *ss, CCGFace *f, int index) { +CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *UNUSED(ss), CCGFace *f, int index) { if (index<0 || index>=f->numVerts) { return NULL; } else { diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index c9a1cfc4618..05c06e86cd0 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -44,6 +44,7 @@ #include "BLI_memarena.h" #include "BLI_array.h" #include "BLI_pbvh.h" +#include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" #include "BKE_displist.h" @@ -53,11 +54,12 @@ #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_texture.h" -#include "BKE_utildefines.h" +#include "BKE_multires.h" #include "BKE_particle.h" #include "BKE_tessmesh.h" #include "BKE_bvhutils.h" + #include "BLO_sys_types.h" // for intptr_t support #include "BIF_gl.h" @@ -68,6 +70,8 @@ #include "GPU_extensions.h" #include "GPU_material.h" +#include "ED_sculpt.h" /* for ED_sculpt_modifiers_changed */ + /////////////////////////////////// /////////////////////////////////// @@ -398,6 +402,15 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me) if(!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) dm_add_polys_from_iter(&tmp.ldata, &tmp.pdata, dm, totloop); + /* object had got displacement layer, should copy this layer to save sculpted data */ + /* NOTE: maybe some other layers should be copied? nazgul */ + if(CustomData_has_layer(&me->fdata, CD_MDISPS)) { + if (totface == me->totface) { + MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + CustomData_add_layer(&tmp.fdata, CD_MDISPS, CD_DUPLICATE, mdisps, totface); + } + } + mesh_update_customdata_pointers(&tmp); CustomData_free(&me->vdata, me->totvert); @@ -637,7 +650,7 @@ void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest, } /// -static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3]) +DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3]) { DerivedMesh *dm = CDDM_from_mesh(me, ob); @@ -670,11 +683,11 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts); mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, 0, 0); - dm = getMeshDerivedMesh(me, ob, deformedVerts); + dm = mesh_create_derived(me, ob, deformedVerts); MEM_freeN(deformedVerts); } else { - DerivedMesh *tdm = getMeshDerivedMesh(me, ob, NULL); + DerivedMesh *tdm = mesh_create_derived(me, ob, NULL); dm = mti->applyModifier(md, ob, tdm, 0, 0); if(tdm != dm) tdm->release(tdm); @@ -920,17 +933,32 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos DerivedMesh *dm, *orcodm, *clothorcodm, *finaldm; int numVerts = me->totvert; int required_mode; + int isPrevDeform= FALSE; + int skipVirtualArmature = (useDeform < 0); + MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0); + int has_multires = mmd != NULL, multires_applied = 0; + int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt; + + if(mmd && !mmd->sculptlvl) + has_multires = 0; + + if(!skipVirtualArmature) { + firstmd = modifiers_getVirtualModifierList(ob); + } + else { + /* game engine exception */ + firstmd = ob->modifiers.first; + if(firstmd && firstmd->type == eModifierType_Armature) + firstmd = firstmd->next; + } - md = firstmd = (useDeform<0) ? ob->modifiers.first : modifiers_getVirtualModifierList(ob); + md = firstmd; modifiers_clearErrors(ob); if(useRenderParams) required_mode = eModifierMode_Render; else required_mode = eModifierMode_Realtime; - /* we always want to keep original indices */ - dataMask |= CD_MASK_ORIGINDEX; - datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode); curr = datamasks; @@ -996,13 +1024,18 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene= scene; - + if(!modifier_isEnabled(scene, md, required_mode)) continue; if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue; if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { modifier_setError(md, "Modifier requires original data, bad stack position."); continue; } + if(sculpt_mode && (!has_multires || multires_applied)) + if(mti->type != eModifierTypeType_OnlyDeform || multires_applied) { + modifier_setError(md, "Not supported in sculpt mode."); + continue; + } if(needMapping && !modifier_supportsMapping(md)) continue; if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; @@ -1037,10 +1070,26 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } } + /* if this is not the last modifier in the stack then recalculate the normals + * to avoid giving bogus normals to the next modifier see: [#23673] */ + if(isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { + /* XXX, this covers bug #23673, but we may need normal calc for other types */ + if(dm->type == DM_TYPE_CDDM) { + CDDM_apply_vert_coords(dm, deformedVerts); + CDDM_calc_normals(dm); + } + } + mti->deformVerts(md, ob, dm, deformedVerts, numVerts, useRenderParams, useDeform); } else { DerivedMesh *ndm; + /* determine which data layers are needed by following modifiers */ + if(curr->next) + nextmask= (CustomDataMask)GET_INT_FROM_POINTER(curr->next->link); + else + nextmask= dataMask; + /* apply vertex coordinates or build a DerivedMesh as necessary */ if(dm) { if(deformedVerts) { @@ -1062,28 +1111,30 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) add_weight_mcol_dm(ob, dm); - /* constructive modifiers need to have an origindex - * otherwise they wont have anywhere to copy the data from */ - if(needMapping) { - int *index, i; + /* Constructive modifiers need to have an origindex + * otherwise they wont have anywhere to copy the data from. + * + * Also create ORIGINDEX data if any of the following modifiers + * requests it, this way Mirror, Solidify etc will keep ORIGINDEX + * data by using generic DM_copy_vert_data() functions. + */ + if(needMapping || (nextmask & CD_MASK_ORIGINDEX)) { + int i, *orig; + + /* calc */ DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); - index = DM_get_vert_data_layer(dm, CD_ORIGINDEX); - for(i=0; i<dm->numVertData; i++) *index++= i; - index = DM_get_edge_data_layer(dm, CD_ORIGINDEX); - for(i=0; i<dm->numEdgeData; i++) *index++= i; - index = DM_get_face_data_layer(dm, CD_ORIGINDEX); - for(i=0; i<dm->numPolyData; i++) *index++= i; + orig = DM_get_vert_data_layer(dm, CD_ORIGINDEX); + for(i=0; i<dm->numVertData; i++) *orig++= i; + orig = DM_get_edge_data_layer(dm, CD_ORIGINDEX); + for(i=0; i<dm->numEdgeData; i++) *orig++= i; + orig = DM_get_face_data_layer(dm, CD_ORIGINDEX); + for(i=0; i<dm->numPolyData; i++) *orig++= i; } } - /* determine which data layers are needed by following modifiers */ - if(curr->next) - nextmask= (CustomDataMask)GET_INT_FROM_POINTER(curr->next->link); - else - nextmask= dataMask; /* set the DerivedMesh to only copy needed data */ mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link); @@ -1120,7 +1171,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos orcodm= create_orco_dm(ob, me, NULL, CD_ORCO); nextmask &= ~CD_MASK_ORCO; - DM_set_only_copy(orcodm, nextmask); + DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX); ndm = mti->applyModifier(md, ob, orcodm, useRenderParams, 0); if(ndm) { @@ -1136,7 +1187,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos clothorcodm= create_orco_dm(ob, me, NULL, CD_CLOTH_ORCO); nextmask &= ~CD_MASK_CLOTH_ORCO; - DM_set_only_copy(clothorcodm, nextmask); + DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX); ndm = mti->applyModifier(md, ob, clothorcodm, useRenderParams, 0); if(ndm) { @@ -1147,9 +1198,14 @@ 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)) break; + + if(sculpt_mode && md->type == eModifierType_Multires) + multires_applied = 1; } for(md=firstmd; md; md=md->next) @@ -1204,7 +1260,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos BLI_linklist_free(datamasks, NULL); } -static float (*editbmesh_getVertexCos(BMEditMesh *em, int *numVerts_r))[3] +float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *numVerts_r))[3] { int i, numVerts = *numVerts_r = em->bm->totvert; float (*cos)[3]; @@ -1221,7 +1277,7 @@ static float (*editbmesh_getVertexCos(BMEditMesh *em, int *numVerts_r))[3] return cos; } -static int editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm) +int editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; @@ -1255,9 +1311,6 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D dm = NULL; md = modifiers_getVirtualModifierList(ob); - - /* we always want to keep original indices */ - dataMask |= CD_MASK_ORIGINDEX; datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode); @@ -1295,7 +1348,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv"); dm->getVertCos(dm, deformedVerts); } else { - deformedVerts = editbmesh_getVertexCos(em, &numVerts); + deformedVerts = editbmesh_get_vertex_cos(em, &numVerts); } } @@ -1336,7 +1389,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D orcodm= create_orco_dm(ob, ob->data, em, CD_ORCO); mask &= ~CD_MASK_ORCO; - DM_set_only_copy(orcodm, mask); + DM_set_only_copy(orcodm, mask | CD_MASK_ORIGINDEX); if (mti->applyModifierEM) ndm = mti->applyModifierEM(md, ob, em, orcodm); @@ -1351,9 +1404,11 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D } /* set the DerivedMesh to only copy needed data */ - DM_set_only_copy(dm, (CustomDataMask)GET_INT_FROM_POINTER(curr->link)); + mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link); /* CD_MASK_ORCO may have been cleared above */ - if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE) + DM_set_only_copy(dm, mask | CD_MASK_ORIGINDEX); + + if(mask & CD_MASK_ORIGSPACE) if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE)) DM_add_tessface_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL); @@ -1448,14 +1503,9 @@ static void clear_mesh_caches(Object *ob) ob->derivedDeform->release(ob->derivedDeform); ob->derivedDeform= NULL; } - /* we free pbvh on changes, except during sculpt since it can't deal with - changing PVBH node organization, we hope topology does not change in - the meantime .. weak */ - if(ob->sculpt && ob->sculpt->pbvh) { - if(!ob->sculpt->cache) { - BLI_pbvh_free(ob->sculpt->pbvh); - ob->sculpt->pbvh= NULL; - } + + if(ob->sculpt) { + ED_sculpt_modifiers_changed(ob); } } @@ -1463,8 +1513,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) { Object *obact = scene->basact?scene->basact->object:NULL; int editing = paint_facesel_test(ob); - /* weight paint and face select need original indicies because of selection buffer drawing */ - int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT)) || editing); + /* weight paint and face select need original indices because of selection buffer drawing */ + int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT))); clear_mesh_caches(ob); @@ -1584,6 +1634,16 @@ DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*ve return final; } +DerivedMesh *mesh_create_derived_physics(Scene *scene, Object *ob, float (*vertCos)[3], + CustomDataMask dataMask) +{ + DerivedMesh *final; + + mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 1, dataMask, -1, 0); + + return final; +} + DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob, float (*vertCos)[3], CustomDataMask dataMask) @@ -1685,61 +1745,112 @@ float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob) return vertexcosnos; } -/* ********* crazyspace *************** */ +/* ******************* GLSL ******************** */ -int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3]) +typedef struct { - ModifierData *md; - DerivedMesh *dm; - int i, a, numleft = 0, numVerts = 0; - int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); - float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; + float * precomputedFaceNormals; + MTFace * mtface; // texture coordinates + MFace * mface; // indices + MVert * mvert; // vertices & normals + float (*orco)[3]; + float (*tangent)[4]; // destination + int numFaces; - modifiers_clearErrors(ob); +} SGLSLMeshToTangent; - dm = NULL; - md = modifiers_getVirtualModifierList(ob); +// interface +#include "mikktspace.h" - /* compute the deformation matrices and coordinates for the first - modifiers with on cage editing that are enabled and support computing - deform matrices */ - for(i = 0; md && i <= cageIndex; i++, md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); +static int GetNumFaces(const SMikkTSpaceContext * pContext) +{ + SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; + return pMesh->numFaces; +} - if(!editbmesh_modifier_is_enabled(scene, md, dm)) - continue; +static int GetNumVertsOfFace(const SMikkTSpaceContext * pContext, const int face_num) +{ + SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; + return pMesh->mface[face_num].v4!=0 ? 4 : 3; +} - if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) { - if(!defmats) { - dm= getEditDerivedBMesh(em, ob, NULL); - deformedVerts= editbmesh_getVertexCos(em, &numVerts); - defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats"); +static void GetPosition(const SMikkTSpaceContext * pContext, float fPos[], const int face_num, const int vert_index) +{ + //assert(vert_index>=0 && vert_index<4); + SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; + unsigned int indices[] = { pMesh->mface[face_num].v1, pMesh->mface[face_num].v2, + pMesh->mface[face_num].v3, pMesh->mface[face_num].v4 }; + VECCOPY(fPos, pMesh->mvert[indices[vert_index]].co); +} - for(a=0; a<numVerts; a++) - unit_m3(defmats[a]); - } +static void GetTextureCoordinate(const SMikkTSpaceContext * pContext, float fUV[], const int face_num, const int vert_index) +{ + //assert(vert_index>=0 && vert_index<4); + SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; - mti->deformMatricesEM(md, ob, em, dm, deformedVerts, defmats, - numVerts); - } - else - break; + if(pMesh->mtface!=NULL) + { + float * uv = pMesh->mtface[face_num].uv[vert_index]; + fUV[0]=uv[0]; fUV[1]=uv[1]; } + else + { + unsigned int indices[] = { pMesh->mface[face_num].v1, pMesh->mface[face_num].v2, + pMesh->mface[face_num].v3, pMesh->mface[face_num].v4 }; - for(; md && i <= cageIndex; md = md->next, i++) - if(editbmesh_modifier_is_enabled(scene, md, dm) && modifier_isCorrectableDeformed(md)) - numleft++; + map_to_sphere( &fUV[0], &fUV[1],pMesh->orco[indices[vert_index]][0], pMesh->orco[indices[vert_index]][1], pMesh->orco[indices[vert_index]][2]); + } +} - if(dm) - dm->release(dm); - - *deformmats= defmats; - *deformcos= deformedVerts; +static void GetNormal(const SMikkTSpaceContext * pContext, float fNorm[], const int face_num, const int vert_index) +{ + //assert(vert_index>=0 && vert_index<4); + SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; + unsigned int indices[] = { pMesh->mface[face_num].v1, pMesh->mface[face_num].v2, + pMesh->mface[face_num].v3, pMesh->mface[face_num].v4 }; - return numleft; + const int smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH); + if(!smoothnormal) // flat + { + if(pMesh->precomputedFaceNormals) + { + VECCOPY(fNorm, &pMesh->precomputedFaceNormals[3*face_num]); + } + else + { + float nor[3]; + float * p0, * p1, * p2; + const int iGetNrVerts = pMesh->mface[face_num].v4!=0 ? 4 : 3; + p0 = pMesh->mvert[indices[0]].co; p1 = pMesh->mvert[indices[1]].co; p2 = pMesh->mvert[indices[2]].co; + if(iGetNrVerts==4) + { + float * p3 = pMesh->mvert[indices[3]].co; + normal_quad_v3( nor, p0, p1, p2, p3); + } + else { + normal_tri_v3(nor, p0, p1, p2); + } + VECCOPY(fNorm, nor); + } + } + else + { + int i=0; + short * no = pMesh->mvert[indices[vert_index]].no; + for(i=0; i<3; i++) + fNorm[i]=no[i]/32767.0f; + normalize_v3(fNorm); + } +} +static void SetTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int face_num, const int iVert) +{ + //assert(vert_index>=0 && vert_index<4); + SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; + float * pRes = pMesh->tangent[4*face_num+iVert]; + VECCOPY(pRes, fvTangent); + pRes[3]=fSign; } -/* ******************* GLSL ******************** */ void DM_add_tangent_layer(DerivedMesh *dm) { @@ -1749,14 +1860,17 @@ void DM_add_tangent_layer(DerivedMesh *dm) MVert *mvert, *v1, *v2, *v3, *v4; MemArena *arena= NULL; VertexTangent **vtangents= NULL; - float (*orco)[3]= NULL, (*tangent)[3]; + float (*orco)[3]= NULL, (*tangent)[4]; float *uv1, *uv2, *uv3, *uv4, *vtang; float fno[3], tang[3], uv[4][2]; - int i, j, len, mf_vi[4], totvert, totface; + int i, j, len, mf_vi[4], totvert, totface, iCalcNewMethod; + float *nors; if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1) return; + nors = dm->getTessFaceDataArray(dm, CD_NORMAL); + /* check we have all the needed layers */ totvert= dm->getNumVerts(dm); totface= dm->getNumTessFaces(dm); @@ -1779,79 +1893,108 @@ void DM_add_tangent_layer(DerivedMesh *dm) arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "tangent layer arena"); BLI_memarena_use_calloc(arena); vtangents= MEM_callocN(sizeof(VertexTangent*)*totvert, "VertexTangent"); - - /* sum tangents at connected vertices */ - for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++) { - v1= &mvert[mf->v1]; - v2= &mvert[mf->v2]; - v3= &mvert[mf->v3]; - - if (mf->v4) { - v4= &mvert[mf->v4]; - normal_quad_v3( fno,v4->co, v3->co, v2->co, v1->co); - } - else { - v4= NULL; - normal_tri_v3( fno,v3->co, v2->co, v1->co); - } - - if(mtface) { - uv1= tf->uv[0]; - uv2= tf->uv[1]; - uv3= tf->uv[2]; - uv4= tf->uv[3]; - } - else { - uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3]; - map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]); - map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]); - map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]); - if(v4) - map_to_sphere( &uv[3][0], &uv[3][1],orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]); - } + + // new computation method + iCalcNewMethod = 1; + if(iCalcNewMethod!=0) + { + SGLSLMeshToTangent mesh2tangent; + SMikkTSpaceContext sContext; + SMikkTSpaceInterface sInterface; + memset(&mesh2tangent, 0, sizeof(SGLSLMeshToTangent)); + memset(&sContext, 0, sizeof(SMikkTSpaceContext)); + memset(&sInterface, 0, sizeof(SMikkTSpaceInterface)); + + mesh2tangent.precomputedFaceNormals = nors; + mesh2tangent.mtface = mtface; + mesh2tangent.mface = mface; + mesh2tangent.mvert = mvert; + mesh2tangent.orco = orco; + mesh2tangent.tangent = tangent; + mesh2tangent.numFaces = totface; + + sContext.m_pUserData = &mesh2tangent; + sContext.m_pInterface = &sInterface; + sInterface.m_getNumFaces = GetNumFaces; + sInterface.m_getNumVerticesOfFace = GetNumVertsOfFace; + sInterface.m_getPosition = GetPosition; + sInterface.m_getTexCoord = GetTextureCoordinate; + sInterface.m_getNormal = GetNormal; + sInterface.m_setTSpaceBasic = SetTSpace; + + // 0 if failed + iCalcNewMethod = genTangSpaceDefault(&sContext); + } + + if(!iCalcNewMethod) + { + /* sum tangents at connected vertices */ + for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++) { + v1= &mvert[mf->v1]; + v2= &mvert[mf->v2]; + v3= &mvert[mf->v3]; + + if (mf->v4) { + v4= &mvert[mf->v4]; + normal_quad_v3( fno,v4->co, v3->co, v2->co, v1->co); + } + else { + v4= NULL; + normal_tri_v3( fno,v3->co, v2->co, v1->co); + } - tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang); - sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1); - sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2); - sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3); + if(mtface) { + uv1= tf->uv[0]; + uv2= tf->uv[1]; + uv3= tf->uv[2]; + uv4= tf->uv[3]; + } + else { + uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3]; + map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]); + map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]); + map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]); + if(v4) + map_to_sphere( &uv[3][0], &uv[3][1],orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]); + } - if(mf->v4) { - v4= &mvert[mf->v4]; - - tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang); + tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang); sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2); sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3); - sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4); - } - } - - /* write tangent to layer */ - for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) { - len= (mf->v4)? 4 : 3; - if(mtface) { - uv1= tf->uv[0]; - uv2= tf->uv[1]; - uv3= tf->uv[2]; - uv4= tf->uv[3]; - } - else { - uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3]; - map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]); - map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]); - map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]); - if(len==4) - map_to_sphere( &uv[3][0], &uv[3][1],orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]); + if(mf->v4) { + v4= &mvert[mf->v4]; + + tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4); + } } + + /* write tangent to layer */ + for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) { + len= (mf->v4)? 4 : 3; + + if(mtface == NULL) { + map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]); + map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]); + map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]); + if(len==4) + map_to_sphere( &uv[3][0], &uv[3][1],orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]); + } - mf_vi[0]= mf->v1; - mf_vi[1]= mf->v2; - mf_vi[2]= mf->v3; - mf_vi[3]= mf->v4; + mf_vi[0]= mf->v1; + mf_vi[1]= mf->v2; + mf_vi[2]= mf->v3; + mf_vi[3]= mf->v4; - for(j=0; j<len; j++) { - vtang= find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]); - normalize_v3_v3(tangent[j], vtang); + for(j=0; j<len; j++) { + vtang= find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]); + normalize_v3_v3(tangent[j], vtang); + ((float *) tangent[j])[3]=1.0f; + } } } diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile deleted file mode 100644 index 53a9999758c..00000000000 --- a/source/blender/blenkernel/intern/Makefile +++ /dev/null @@ -1,156 +0,0 @@ -# -# $Id$ -# -# ***** 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): none yet. -# -# ***** END GPL LICENSE BLOCK ***** -# -# - -LIBNAME = blenkernel -DIR = $(OCGDIR)/blender/$(LIBNAME) - -include nan_compile.mk - -CFLAGS += $(LEVEL_1_C_WARNINGS) - -# OpenGL and Python -CPPFLAGS += -I$(NAN_GLEW)/include -CPPFLAGS += -I$(OPENGL_HEADERS) -CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) - -CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include -CPPFLAGS += -I../../../../intern/memutil -CPPFLAGS += -I$(NAN_AUDASPACE)/include -# Reference to the types in makesdna and imbuf -CPPFLAGS += -I../../makesdna -CPPFLAGS += -I../../makesrna -CPPFLAGS += -I../../imbuf -CPPFLAGS += -I../../ikplugin -# This mod uses the BLI and BLO module -CPPFLAGS += -I../../blenlib -CPPFLAGS += -I../../blenloader -CPPFLAGS += -I../../python -CPPFLAGS += -I../../blenfont -# This is bad level, remove eventually -CPPFLAGS += -I../../windowmanager -# also avi is used -CPPFLAGS += -I../../avi -CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include - -# we still refer to /include a bit... -CPPFLAGS += -I../../editors/include - -# to include the render stuff: -CPPFLAGS += -I../../render/extern/include - -# for sound -#CPPFLAGS += -I../../../kernel/gen_system -CPPFLAGS += $(NAN_SDLCFLAGS) - -CPPFLAGS += -I$(NAN_IKSOLVER)/include -CPPFLAGS += -I$(NAN_DECIMATION)/include -CPPFLAGS += -I$(NAN_ELBEEM)/include -CPPFLAGS += -I$(NAN_OPENNL)/include -CPPFLAGS += -I$(NAN_BSP)/include -CPPFLAGS += -I$(NAN_SMOKE)/include - -# path to zlib -CPPFLAGS += -I$(NAN_ZLIB)/include - -#path to nodes -CPPFLAGS += -I../../nodes - -#path to gpu -CPPFLAGS += -I../../gpu - -#modifiers got moved -CPPFLAGS += -I../../modifiers - -# path to our own external headerfiles -CPPFLAGS += -I.. - -CPPFLAGS += -I$(NAN_FREETYPE)/include -CPPFLAGS += -I$(NAN_FREETYPE)/include/freetype2 - -# path to bullet2, for cloth -ifeq ($(NAN_USE_BULLET), true) - CPPFLAGS += -I$(NAN_BULLET2)/include -endif - -# lzo and lzma, for pointcache -ifeq ($(WITH_LZO),true) - CPPFLAGS += -I$(NAN_LZO)/minilzo - CPPFLAGS += -DWITH_LZO -endif - -ifeq ($(WITH_LZO),true) - CPPFLAGS += -I$(NAN_LZMA) - CPPFLAGS += -DWITH_LZMA -endif - -ifeq ($(WITH_FFMPEG),true) - CPPFLAGS += -DWITH_FFMPEG - CPPFLAGS += $(NAN_FFMPEGCFLAGS) -endif - -ifeq ($(WITH_OPENEXR), true) - CPPFLAGS += -DWITH_OPENEXR -endif - -ifeq ($(WITH_DDS), true) - CPPFLAGS += -DWITH_DDS -endif - -ifeq ($(WITH_OPENJPEG), true) - CPPFLAGS += -DWITH_OPENJPEG -endif - -ifeq ($(WITH_QUICKTIME), true) - CPPFLAGS += -I../../quicktime - CPPFLAGS += -DWITH_QUICKTIME -endif - -ifeq ($(WITH_TIFF), true) - CPPFLAGS += -DWITH_TIFF -endif - -ifeq ($(WITH_CINEON), true) - CPPFLAGS += -DWITH_CINEON -endif - -ifeq ($(WITH_HDR), true) - CPPFLAGS += -DWITH_HDR -endif - -ifeq ($(OS), darwin) - ifeq ($(WITH_BF_OPENMP), true) - CPPFLAGS += -DPARALLEL=1 - endif -endif - -ifeq ($(WITH_LCMS), true) - CPPFLAGS += -DWITH_LCMS - CPPFLAGS += -I$(BF_LCMS_INC) -endif diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 90a3a6ce664..14a0f71f824 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -39,6 +39,11 @@ #include "DNA_scene_types.h" #include "DNA_object_types.h" +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" +#include "BLI_ghash.h" + #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_anim.h" @@ -48,15 +53,11 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_object.h" -#include "BKE_utildefines.h" + #include "BKE_idprop.h" #include "BIK_api.h" -#include "BLI_blenlib.h" -#include "BLI_ghash.h" -#include "BLI_math.h" - #include "RNA_access.h" /* *********************** NOTE ON POSE AND ACTION ********************** @@ -92,12 +93,11 @@ void make_local_action(bAction *act) bAction *actn; int local=0, lib=0; - if (act->id.lib==0) return; + if (act->id.lib==NULL) return; if (act->id.us==1) { - act->id.lib= 0; + act->id.lib= NULL; act->id.flag= LIB_LOCAL; - //make_local_action_channels(act); - new_id(0, (ID *)act, 0); + new_id(NULL, (ID *)act, NULL); return; } @@ -113,10 +113,10 @@ void make_local_action(bAction *act) #endif if(local && lib==0) { - act->id.lib= 0; + act->id.lib= NULL; act->id.flag= LIB_LOCAL; //make_local_action_channels(act); - new_id(0, (ID *)act, 0); + new_id(NULL, (ID *)act, NULL); } else if(local && lib) { actn= copy_action(act); @@ -376,6 +376,20 @@ bActionGroup *action_groups_find_named (bAction *act, const char name[]) return BLI_findstring(&act->groups, name, offsetof(bActionGroup, name)); } +/* Clear all 'temp' flags on all groups */ +void action_groups_clear_tempflags (bAction *act) +{ + bActionGroup *agrp; + + /* sanity checks */ + if (ELEM(NULL, act, act->groups.first)) + return; + + /* flag clearing loop */ + for (agrp = act->groups.first; agrp; agrp = agrp->next) + agrp->flag &= ~AGRP_TEMP; +} + /* *************** Pose channels *************** */ /* usually used within a loop, so we got a N^2 slowdown */ @@ -408,9 +422,10 @@ bPoseChannel *verify_pose_channel(bPose *pose, const char *name) /* If not, create it and add it */ chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel"); - strncpy(chan->name, name, 31); + BLI_strncpy(chan->name, name, sizeof(chan->name)); /* init vars to prevent math errors */ - chan->quat[0] = chan->rotAxis[1]= 1.0f; + unit_qt(chan->quat); + unit_axis_angle(chan->rotAxis, &chan->rotAngle); chan->size[0] = chan->size[1] = chan->size[2] = 1.0f; chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f; @@ -774,7 +789,7 @@ void pose_add_group (Object *ob) return; grp= MEM_callocN(sizeof(bActionGroup), "PoseGroup"); - strcpy(grp->name, "Group"); + BLI_strncpy(grp->name, "Group", sizeof(grp->name)); BLI_addtail(&pose->agroups, grp); BLI_uniquename(&pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), sizeof(grp->name)); @@ -1027,7 +1042,6 @@ void extract_pose_from_pose(bPose *pose, const bPose *src) void rest_pose(bPose *pose) { bPoseChannel *pchan; - int i; if (!pose) return; @@ -1036,16 +1050,12 @@ void rest_pose(bPose *pose) memset(pose->cyclic_offset, 0, sizeof(pose->cyclic_offset)); for (pchan=pose->chanbase.first; pchan; pchan= pchan->next) { - for (i=0; i<3; i++) { - pchan->loc[i]= 0.0f; - pchan->quat[i+1]= 0.0f; - pchan->eul[i]= 0.0f; - pchan->size[i]= 1.0f; - pchan->rotAxis[i]= 0.0f; - } - pchan->quat[0]= pchan->rotAxis[1]= 1.0f; - pchan->rotAngle= 0.0f; - + zero_v3(pchan->loc); + zero_v3(pchan->eul); + unit_qt(pchan->quat); + unit_axis_angle(pchan->rotAxis, &pchan->rotAngle); + pchan->size[0]= pchan->size[1]= pchan->size[2]= 1.0f; + pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); } } @@ -1091,7 +1101,7 @@ void copy_pose_result(bPose *to, bPose *from) /* For the calculation of the effects of an Action at the given frame on an object * This is currently only used for the Action Constraint */ -void what_does_obaction (Scene *scene, Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe) +void what_does_obaction (Scene *UNUSED(scene), Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe) { bActionGroup *agrp= action_groups_find_named(act, groupname); @@ -1119,8 +1129,8 @@ void what_does_obaction (Scene *scene, Object *ob, Object *workob, bPose *pose, workob->pose= pose; /* need to set pose too, since this is used for both types of Action Constraint */ - strcpy(workob->parsubstr, ob->parsubstr); - strcpy(workob->id.name, "OB<ConstrWorkOb>"); /* we don't use real object name, otherwise RNA screws with the real thing */ + BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr)); + BLI_strncpy(workob->id.name, "OB<ConstrWorkOb>", sizeof(workob->id.name)); /* we don't use real object name, otherwise RNA screws with the real thing */ /* if we're given a group to use, it's likely to be more efficient (though a bit more dangerous) */ if (agrp) { @@ -1134,10 +1144,9 @@ void what_does_obaction (Scene *scene, Object *ob, Object *workob, bPose *pose, animsys_evaluate_action_group(&id_ptr, act, agrp, NULL, cframe); } else { - AnimData adt; + AnimData adt= {NULL}; /* init animdata, and attach to workob */ - memset(&adt, 0, sizeof(AnimData)); workob->adt= &adt; adt.recalc= ADT_RECALC_ANIM; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 167ceab23eb..5842197da48 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -1,4 +1,4 @@ -/** anim.c +/* anim.c * * * $Id$ @@ -39,6 +39,7 @@ #include "BLI_editVert.h" #include "BLI_math.h" #include "BLI_rand.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -50,6 +51,7 @@ #include "DNA_view3d_types.h" #include "DNA_vfont_types.h" +#include "BKE_animsys.h" #include "BKE_curve.h" #include "BKE_DerivedMesh.h" #include "BKE_depsgraph.h" @@ -66,6 +68,7 @@ #include "BKE_utildefines.h" #include "BKE_tessmesh.h" #include "BKE_depsgraph.h" +#include "BKE_anim.h" // XXX bad level call... @@ -299,7 +302,7 @@ static void motionpaths_calc_update_scene(Scene *scene) Base *base, *last=NULL; /* only stuff that moves or needs display still */ - DAG_scene_update_flags(G.main, scene, scene->lay); + DAG_scene_update_flags(G.main, scene, scene->lay, TRUE); /* find the last object with the tag * - all those afterwards are assumed to not be relevant for our calculations @@ -439,6 +442,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) /* free curve path data * NOTE: frees the path itself! + * NOTE: this is increasingly innacurate with non-uniform BevPoint subdivisions [#24633] */ void free_path(Path *path) { @@ -447,7 +451,7 @@ void free_path(Path *path) } /* calculate a curve-deform path for a curve - * - only called from displist.c -> makeDispListCurveTypes + * - only called from displist.c -> do_makeDispListCurveTypes */ void calc_curvepath(Object *ob) { @@ -510,7 +514,7 @@ void calc_curvepath(Object *ob) /* the path verts in path->data */ /* now also with TILT value */ - pp= path->data = (PathPoint *)MEM_callocN(sizeof(PathPoint)*4*path->len, "pathdata"); // XXX - why *4? - in 2.4x each element was 4 and the size was 16, so better leave for now - Campbell + pp= path->data = (PathPoint *)MEM_callocN(sizeof(PathPoint)*path->len, "pathdata"); bevp= bevpfirst; bevpn= bevp+1; @@ -640,32 +644,21 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat, vec[1]= data[0]*p0->vec[1] + data[1]*p1->vec[1] + data[2]*p2->vec[1] + data[3]*p3->vec[1] ; /* Y */ vec[2]= data[0]*p0->vec[2] + data[1]*p1->vec[2] + data[2]*p2->vec[2] + data[3]*p3->vec[2] ; /* Z */ vec[3]= data[0]*p0->vec[3] + data[1]*p1->vec[3] + data[2]*p2->vec[3] + data[3]*p3->vec[3] ; /* Tilt, should not be needed since we have quat still used */ - /* Need to verify the quat interpolation is correct - XXX */ if (quat) { - //float totfac, q1[4], q2[4]; + float totfac, q1[4], q2[4]; - /* checks for totfac are needed when 'fac' is 1.0 key_curve_position_weights can assign zero - * to more then one index in data which can give divide by zero error */ -/* - totfac= data[0]+data[1]; - if(totfac>0.000001) interp_qt_qtqt(q1, p0->quat, p1->quat, data[0] / totfac); - else QUATCOPY(q1, p1->quat); + totfac= data[0]+data[3]; + if(totfac>FLT_EPSILON) interp_qt_qtqt(q1, p0->quat, p3->quat, data[3] / totfac); + else QUATCOPY(q1, p1->quat); - normalize_qt(q1); - - totfac= data[2]+data[3]; - if(totfac>0.000001) interp_qt_qtqt(q2, p2->quat, p3->quat, data[2] / totfac); - else QUATCOPY(q1, p3->quat); - normalize_qt(q2); + totfac= data[1]+data[2]; + if(totfac>FLT_EPSILON) interp_qt_qtqt(q2, p1->quat, p2->quat, data[2] / totfac); + else QUATCOPY(q2, p3->quat); totfac = data[0]+data[1]+data[2]+data[3]; - if(totfac>0.000001) interp_qt_qtqt(quat, q1, q2, (data[0]+data[1]) / totfac); - else QUATCOPY(quat, q2); - normalize_qt(quat); - */ - // XXX - find some way to make quat interpolation work correctly, above code fails in rare but nasty cases. - QUATCOPY(quat, p1->quat); + if(totfac>FLT_EPSILON) interp_qt_qtqt(quat, q1, q2, (data[1]+data[2]) / totfac); + else QUATCOPY(quat, q2); } if(radius) @@ -753,41 +746,69 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, i static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated) { extern int enable_cu_speed; /* object.c */ - Object copyob; - DupliObject *dob; - int cfrao, ok; + Object copyob = {{NULL}}; + int cfrao = scene->r.cfra; - /* simple preventing of too deep nested groups */ - if(level>MAX_DUPLI_RECUR) return; + /* simple prevention of too deep nested groups */ + if (level > MAX_DUPLI_RECUR) return; - cfrao= scene->r.cfra; - if(ob->parent==NULL && ob->constraints.first==NULL) return; - - if(ob->transflag & OB_DUPLINOSPEED) enable_cu_speed= 0; - copyob= *ob; /* store transform info */ - - for(scene->r.cfra= ob->dupsta; scene->r.cfra<=ob->dupend; scene->r.cfra++) { - - ok= 1; - if(ob->dupoff) { + /* if we don't have any data/settings which will lead to object movement, + * don't waste time trying, as it will all look the same... + */ + if (ob->parent==NULL && ob->constraints.first==NULL && ob->adt==NULL) + return; + + /* make a copy of the object's original data (before any dupli-data overwrites it) + * as we'll need this to keep track of unkeyed data + * - this doesn't take into account other data that can be reached from the object, + * for example it's shapekeys or bones, hence the need for an update flush at the end + */ + copyob = *ob; + + /* duplicate over the required range */ + if (ob->transflag & OB_DUPLINOSPEED) enable_cu_speed= 0; + + for (scene->r.cfra= ob->dupsta; scene->r.cfra<=ob->dupend; scene->r.cfra++) { + short ok= 1; + + /* - dupoff = how often a frames within the range shouldn't be made into duplis + * - dupon = the length of each "skipping" block in frames + */ + if (ob->dupoff) { ok= scene->r.cfra - ob->dupsta; ok= ok % (ob->dupon+ob->dupoff); - if(ok < ob->dupon) ok= 1; - else ok= 0; + ok= (ok < ob->dupon); } - if(ok) { -#if 0 // XXX old animation system - do_ob_ipo(scene, ob); -#endif // XXX old animation system + + if (ok) { + DupliObject *dob; + + /* WARNING: doing animation updates in this way is not terribly accurate, as the dependencies + * and/or other objects which may affect this object's transforms are not updated either. + * However, this has always been the way that this worked (i.e. pre 2.5), so I guess that it'll be fine! + */ + BKE_animsys_evaluate_animdata(&ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ where_is_object_time(scene, ob, (float)scene->r.cfra); + dob= new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, OB_DUPLIFRAMES, animated); copy_m4_m4(dob->omat, copyob.obmat); } } - *ob= copyob; /* restore transform info */ - scene->r.cfra= cfrao; enable_cu_speed= 1; + + /* reset frame to original frame, then re-evaluate animation as above + * as 2.5 animation data may have far-reaching consequences + */ + scene->r.cfra= cfrao; + + BKE_animsys_evaluate_animdata(&ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ + where_is_object_time(scene, ob, (float)scene->r.cfra); + + /* but, to make sure unkeyed object transforms are still sane, + * let's copy object's original data back over + */ + *ob = copyob; } typedef struct vertexDupliData { @@ -809,6 +830,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n DupliObject *dob; vertexDupliData *vdd= userData; float vec[3], q2[4], mat[3][3], tmat[4][4], obmat[4][4]; + int origlay; mul_v3_m4v3(vec, vdd->pmat, co); sub_v3_v3(vec, vdd->pmat[3]); @@ -831,7 +853,14 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n copy_m4_m4(tmat, obmat); mul_m4_m4m3(obmat, tmat, mat); } + + origlay = vdd->ob->lay; + dob= new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS, vdd->animated); + + /* restore the original layer so that each dupli will have proper dob->origlay */ + vdd->ob->lay = origlay; + if(vdd->orco) VECCOPY(dob->orco, vdd->orco[index]); @@ -856,7 +885,8 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl GroupObject * go = NULL; BMEditMesh *em; float vec[3], no[3], pmat[4][4]; - int lay, totvert, a, oblay; + int totvert, a, oblay; + unsigned int lay; copy_m4_m4(pmat, par->obmat); @@ -939,6 +969,14 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl vertex_dupli__mapFunc(&vdd, a, vec, no, NULL); } } + if(sce) { + /* Set proper layer in case of scene looping, + * in case of groups the object layer will be + * changed when it's duplicated due to the + * group duplication. + */ + ob->lay = vdd.par->lay; + } break; } @@ -1150,33 +1188,37 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated) { GroupObject *go; - Object *ob=0, **oblist=0, obcopy, *obcopylist=0; + Object *ob=NULL, **oblist=NULL, obcopy, *obcopylist=NULL; DupliObject *dob; ParticleDupliWeight *dw; - ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)}; ParticleSettings *part; ParticleData *pa; - ChildParticle *cpa=0; + ChildParticle *cpa=NULL; ParticleKey state; ParticleCacheKey *cache; float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0; float (*obmat)[4], (*oldobmat)[4]; - int lay, a, b, counter, hair = 0; + int a, b, counter, hair = 0; int totpart, totchild, totgroup=0, pa_num; - if(psys==0) return; + int no_draw_flag = PARS_UNEXIST; + + if(psys==NULL) return; /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; part=psys->part; - if(part==0) + if(part==NULL) return; if(!psys_check_enabled(par, psys)) return; + + if(G.rendering == 0) + no_draw_flag |= PARS_NO_DISP; ctime = bsystem_time(scene, par, (float)scene->r.cfra, 0.0); @@ -1184,9 +1226,13 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p totchild = psys->totchild; BLI_srandom(31415926 + psys->seed); - - lay= scene->lay; + if((psys->renderdata || part->draw_as==PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { + ParticleSimulationData sim= {NULL}; + sim.scene= scene; + sim.ob= par; + sim.psys= psys; + sim.psmd= psys_get_modifier(par, psys); /* first check for loops (particle system object used as dupli object) */ if(part->ren_as == PART_DRAW_OB) { @@ -1268,7 +1314,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p for(pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) { if(a<totpart) { /* handle parent particle */ - if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) + if(pa->flag & no_draw_flag) continue; pa_num = pa->num; @@ -1281,7 +1327,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p pa_num = a; pa_time = psys->particles[cpa->parent].time; - size = psys_get_child_size(psys, cpa, ctime, 0); + size = psys_get_child_size(psys, cpa, ctime, NULL); } /* some hair paths might be non-existent so they can't be used for duplication */ @@ -1312,11 +1358,11 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p /* hair we handle separate and compute transform based on hair keys */ if(a < totpart) { cache = psys->pathcache[a]; - psys_get_dupli_path_transform(&sim, pa, 0, cache, pamat, &scale); + psys_get_dupli_path_transform(&sim, pa, NULL, cache, pamat, &scale); } else { cache = psys->childcache[a-totpart]; - psys_get_dupli_path_transform(&sim, 0, cpa, cache, pamat, &scale); + psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale); } VECCOPY(pamat[3], cache->co); @@ -1326,12 +1372,16 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else { /* first key */ state.time = ctime; - if(psys_get_particle_state(&sim, a, &state, 0) == 0) + if(psys_get_particle_state(&sim, a, &state, 0) == 0) { continue; - - quat_to_mat4( pamat,state.rot); - VECCOPY(pamat[3], state.co); - pamat[3][3]= 1.0f; + } + else { + float tquat[4]; + normalize_qt_qt(tquat, state.rot); + quat_to_mat4(pamat, tquat); + copy_v3_v3(pamat[3], state.co); + pamat[3][3]= 1.0f; + } } if(part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { @@ -1356,20 +1406,26 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p VECCOPY(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; - copy_m4_m4(mat, pamat); + /* Normal particles and cached hair live in global space so we need to + * remove the real emitter's transformation before 2nd order duplication. + */ + if(par_space_mat && GS(id->name) != ID_GR) + mul_m4_m4m4(mat, pamat, psys->imat); + else + copy_m4_m4(mat, pamat); mul_m4_m4m4(tmat, obmat, mat); mul_mat3_m4_fl(tmat, size*scale); - if(part->draw & PART_DRAW_GLOBAL_OB) - VECADD(tmat[3], tmat[3], vec); - if(par_space_mat) mul_m4_m4m4(mat, tmat, par_space_mat); else copy_m4_m4(mat, tmat); - dob= new_dupli_object(lb, ob, mat, ob->lay, counter, OB_DUPLIPARTS, animated); + if(part->draw & PART_DRAW_GLOBAL_OB) + VECADD(mat[3], mat[3], vec); + + dob= new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated); copy_m4_m4(dob->omat, oldobmat); if(G.rendering) psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco); @@ -1422,7 +1478,7 @@ static Object *find_family_object(Object **obar, char *family, char ch) static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int level, int animated) { - Object *ob, *obar[256]; + Object *ob, *obar[256]= {NULL}; Curve *cu; struct chartrans *ct, *chartransdata; float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof; @@ -1436,10 +1492,8 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int level, i /* in par the family name is stored, use this to find the other objects */ chartransdata= BKE_text_to_curve(scene, par, FO_DUPLI); - if(chartransdata==0) return; - - memset(obar, 0, 256*sizeof(void *)); - + if(chartransdata==NULL) return; + cu= par->data; slen= strlen(cu->str); fsize= cu->fsize; diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 10c2c1801cb..77d0f008c2b 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -37,9 +37,12 @@ #include "BLI_blenlib.h" #include "BLI_dynstr.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" +#include "DNA_material_types.h" #include "DNA_scene_types.h" +#include "DNA_texture_types.h" #include "BKE_animsys.h" #include "BKE_action.h" @@ -47,6 +50,7 @@ #include "BKE_nla.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_library.h" #include "BKE_utildefines.h" #include "RNA_access.h" @@ -70,7 +74,7 @@ short id_type_can_have_animdata (ID *id) switch (GS(id->name)) { /* has AnimData */ case ID_OB: - case ID_ME: case ID_MB: case ID_CU: case ID_AR: + case ID_ME: case ID_MB: case ID_CU: case ID_AR: case ID_LT: case ID_KE: case ID_PA: case ID_MA: case ID_TE: case ID_NT: @@ -175,7 +179,7 @@ void BKE_free_animdata (ID *id) /* Freeing -------------------------------------------- */ /* Make a copy of the given AnimData - to be used when copying datablocks */ -AnimData *BKE_copy_animdata (AnimData *adt) +AnimData *BKE_copy_animdata (AnimData *adt, const short do_action) { AnimData *dadt; @@ -185,9 +189,15 @@ AnimData *BKE_copy_animdata (AnimData *adt) dadt= MEM_dupallocN(adt); /* make a copy of action - at worst, user has to delete copies... */ - dadt->action= copy_action(adt->action); - dadt->tmpact= copy_action(adt->tmpact); - + if(do_action) { + dadt->action= copy_action(adt->action); + dadt->tmpact= copy_action(adt->tmpact); + } + else { + id_us_plus((ID *)dadt->action); + id_us_plus((ID *)dadt->tmpact); + } + /* duplicate NLA data */ copy_nladata(&dadt->nla_tracks, &adt->nla_tracks); @@ -201,7 +211,7 @@ AnimData *BKE_copy_animdata (AnimData *adt) return dadt; } -int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from) +int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from, const short do_action) { AnimData *adt; @@ -213,13 +223,26 @@ int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from) adt = BKE_animdata_from_id(id_from); if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id_to; - iat->adt= BKE_copy_animdata(adt); + iat->adt= BKE_copy_animdata(adt, do_action); } return 1; } - +void BKE_copy_animdata_id_action(struct ID *id) +{ + AnimData *adt= BKE_animdata_from_id(id); + if(adt) { + if(adt->action) { + ((ID *)adt->action)->us--; + adt->action= copy_action(adt->action); + } + if(adt->tmpact) { + ((ID *)adt->tmpact)->us--; + adt->tmpact= copy_action(adt->tmpact); + } + } +} /* Make Local -------------------------------------------- */ @@ -254,6 +277,176 @@ void BKE_animdata_make_local(AnimData *adt) make_local_strips(&nlt->strips); } +/* Sub-ID Regrouping ------------------------------------------- */ + +/* helper heuristic for determining if a path is compatible with the basepath + * < path: (str) full RNA-path from some data (usually an F-Curve) to compare + * < basepath: (str) shorter path fragment to look for + * > returns (bool) whether there is a match + */ +static short animpath_matches_basepath (const char path[], const char basepath[]) +{ + /* we need start of path to be basepath */ + return (path && basepath) && (strstr(path, basepath) == path); +} + +/* Move F-Curves in src action to dst action, setting up all the necessary groups + * for this to happen, but only if the F-Curves being moved have the appropriate + * "base path". + * - This is used when data moves from one datablock to another, causing the + * F-Curves to need to be moved over too + */ +void action_move_fcurves_by_basepath (bAction *srcAct, bAction *dstAct, const char basepath[]) +{ + FCurve *fcu, *fcn=NULL; + + /* sanity checks */ + if ELEM3(NULL, srcAct, dstAct, basepath) { + if (G.f & G_DEBUG) { + printf("ERROR: action_partition_fcurves_by_basepath(%p, %p, %p) has insufficient info to work with\n", + srcAct, dstAct, basepath); + } + return; + } + + /* clear 'temp' flags on all groups in src, as we'll be needing them later + * to identify groups that we've managed to empty out here + */ + action_groups_clear_tempflags(srcAct); + + /* iterate over all src F-Curves, moving over the ones that need to be moved */ + for (fcu = srcAct->curves.first; fcu; fcu = fcn) { + /* store next pointer in case we move stuff */ + fcn = fcu->next; + + /* should F-Curve be moved over? + * - we only need the start of the path to match basepath + */ + if (animpath_matches_basepath(fcu->rna_path, basepath)) { + bActionGroup *agrp = NULL; + + /* if grouped... */ + if (fcu->grp) { + /* make sure there will be a matching group on the other side for the migrants */ + agrp = action_groups_find_named(dstAct, fcu->grp->name); + + if (agrp == NULL) { + /* add a new one with a similar name (usually will be the same though) */ + agrp = action_groups_add_new(dstAct, fcu->grp->name); + } + + /* old groups should be tagged with 'temp' flags so they can be removed later + * if we remove everything from them + */ + fcu->grp->flag |= AGRP_TEMP; + } + + /* perform the migration now */ + action_groups_remove_channel(srcAct, fcu); + + if (agrp) + action_groups_add_channel(dstAct, agrp, fcu); + else + BLI_addtail(&dstAct->curves, fcu); + } + } + + /* cleanup groups (if present) */ + if (srcAct->groups.first) { + bActionGroup *agrp, *grp=NULL; + + for (agrp = srcAct->groups.first; agrp; agrp = grp) { + grp = agrp->next; + + /* only tagged groups need to be considered - clearing these tags or removing them */ + if (agrp->flag & AGRP_TEMP) { + /* if group is empty and tagged, then we can remove as this operation + * moved out all the channels that were formerly here + */ + if (agrp->channels.first == NULL) + BLI_freelinkN(&srcAct->groups, agrp); + else + agrp->flag &= ~AGRP_TEMP; + } + } + } +} + +/* Transfer the animation data from srcID to dstID where the srcID + * animation data is based off "basepath", creating new AnimData and + * associated data as necessary + */ +void BKE_animdata_separate_by_basepath (ID *srcID, ID *dstID, ListBase *basepaths) +{ + AnimData *srcAdt=NULL, *dstAdt=NULL; + LinkData *ld; + + /* sanity checks */ + if ELEM(NULL, srcID, dstID) { + if (G.f & G_DEBUG) + printf("ERROR: no source or destination ID to separate AnimData with\n"); + return; + } + + /* get animdata from src, and create for destination (if needed) */ + srcAdt = BKE_animdata_from_id(srcID); + dstAdt = BKE_id_add_animdata(dstID); + + if ELEM(NULL, srcAdt, dstAdt) { + if (G.f & G_DEBUG) + printf("ERROR: no AnimData for this pair of ID's\n"); + return; + } + + /* active action */ + if (srcAdt->action) { + /* set up an action if necessary, and name it in a similar way so that it can be easily found again */ + if (dstAdt->action == NULL) { + dstAdt->action = add_empty_action(srcAdt->action->id.name+2); + } + else if (dstAdt->action == srcAdt->action) { + printf("Argh! Source and Destination share animation! ('%s' and '%s' both use '%s') Making new empty action\n", + srcID->name, dstID->name, srcAdt->action->id.name); + + // TODO: review this... + id_us_min(&dstAdt->action->id); + dstAdt->action = add_empty_action(dstAdt->action->id.name+2); + } + + /* loop over base paths, trying to fix for each one... */ + for (ld = basepaths->first; ld; ld = ld->next) { + const char *basepath = (const char *)ld->data; + action_move_fcurves_by_basepath(srcAdt->action, dstAdt->action, basepath); + } + } + + /* drivers */ + if (srcAdt->drivers.first) { + FCurve *fcu, *fcn=NULL; + + /* check each driver against all the base paths to see if any should go */ + for (fcu = srcAdt->drivers.first; fcu; fcu = fcn) { + fcn = fcu->next; + + /* try each basepath in turn, but stop on the first one which works */ + for (ld = basepaths->first; ld; ld = ld->next) { + const char *basepath = (const char *)ld->data; + + if (animpath_matches_basepath(fcu->rna_path, basepath)) { + /* just need to change lists */ + BLI_remlink(&srcAdt->drivers, fcu); + BLI_addtail(&dstAdt->drivers, fcu); + + // TODO: add depsgraph flushing calls? + + /* can stop now, as moved already */ + break; + } + } + } + } +} + /* Path Validation -------------------------------------------- */ /* Check if a given RNA Path is valid, by tracing it from the given ID, and seeing if we can resolve it */ @@ -272,7 +465,7 @@ static short check_rna_path_is_valid (ID *owner_id, char *path) /* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate * NOTE: we assume that oldName and newName have [" "] padding around them */ -static char *rna_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, char *oldpath, int verify_paths) +static char *rna_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, char *oldpath, int verify_paths) { char *prefixPtr= strstr(oldpath, prefix); char *oldNamePtr= strstr(oldpath, oldName); @@ -330,7 +523,7 @@ static char *rna_path_rename_fix (ID *owner_id, char *prefix, char *oldName, cha } /* Check RNA-Paths for a list of F-Curves */ -static void fcurves_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *curves, int verify_paths) +static void fcurves_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *curves, int verify_paths) { FCurve *fcu; @@ -343,7 +536,7 @@ static void fcurves_path_rename_fix (ID *owner_id, char *prefix, char *oldName, } /* Check RNA-Paths for a list of Drivers */ -static void drivers_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, char *oldKey, char *newKey, ListBase *curves, int verify_paths) +static void drivers_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, char *oldKey, char *newKey, ListBase *curves, int verify_paths) { FCurve *fcu; @@ -383,7 +576,7 @@ static void drivers_path_rename_fix (ID *owner_id, char *prefix, char *oldName, } /* Fix all RNA-Paths for Actions linked to NLA Strips */ -static void nlastrips_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *strips, int verify_paths) +static void nlastrips_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *strips, int verify_paths) { NlaStrip *strip; @@ -403,7 +596,7 @@ static void nlastrips_path_rename_fix (ID *owner_id, char *prefix, char *oldName * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]> * i.e. pose.bones["Bone"] */ -void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, char *prefix, char *oldName, char *newName, int oldSubscript, int newSubscript, int verify_paths) +void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, const char *prefix, char *oldName, char *newName, int oldSubscript, int newSubscript, int verify_paths) { NlaTrack *nlt; char *oldN, *newN; @@ -443,44 +636,73 @@ void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, char *prefix, c /* Whole Database Ops -------------------------------------------- */ /* apply the given callback function on all data in main database */ -void BKE_animdata_main_cb (Main *main, ID_AnimData_Edit_Callback func, void *user_data) +void BKE_animdata_main_cb (Main *mainptr, ID_AnimData_Edit_Callback func, void *user_data) { ID *id; + /* standard data version */ #define ANIMDATA_IDS_CB(first) \ for (id= first; id; id= id->next) { \ AnimData *adt= BKE_animdata_from_id(id); \ if (adt) func(id, adt, user_data); \ } - - ANIMDATA_IDS_CB(main->nodetree.first); /* nodes */ - ANIMDATA_IDS_CB(main->tex.first); /* textures */ - ANIMDATA_IDS_CB(main->lamp.first); /* lamps */ - ANIMDATA_IDS_CB(main->mat.first); /* materials */ - ANIMDATA_IDS_CB(main->camera.first); /* cameras */ - ANIMDATA_IDS_CB(main->key.first); /* shapekeys */ - ANIMDATA_IDS_CB(main->mball.first); /* metaballs */ - ANIMDATA_IDS_CB(main->curve.first); /* curves */ - ANIMDATA_IDS_CB(main->armature.first); /* armatures */ - ANIMDATA_IDS_CB(main->mesh.first); /* meshes */ - ANIMDATA_IDS_CB(main->particle.first); /* particles */ - ANIMDATA_IDS_CB(main->object.first); /* objects */ - ANIMDATA_IDS_CB(main->world.first); /* worlds */ - - /* scenes */ - for (id= main->scene.first; id; id= id->next) { - AnimData *adt= BKE_animdata_from_id(id); - Scene *scene= (Scene *)id; - - /* do compositing nodes first (since these aren't included in main tree) */ - if (scene->nodetree) { - AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree); - if (adt2) func(id, adt2, user_data); - } - - /* now fix scene animation data as per normal */ - if (adt) func((ID *)id, adt, user_data); + + /* "embedded" nodetree cases (i.e. scene/material/texture->nodetree) */ +#define ANIMDATA_NODETREE_IDS_CB(first, NtId_Type) \ + for (id= first; id; id= id->next) { \ + AnimData *adt= BKE_animdata_from_id(id); \ + NtId_Type *ntp= (NtId_Type *)id; \ + if (ntp->nodetree) { \ + AnimData *adt2= BKE_animdata_from_id((ID *)ntp); \ + if (adt2) func(id, adt2, user_data); \ + } \ + if (adt) func(id, adt, user_data); \ } + + /* nodes */ + ANIMDATA_IDS_CB(mainptr->nodetree.first); + + /* textures */ + ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex); + + /* lamps */ + ANIMDATA_IDS_CB(mainptr->lamp.first); + + /* materials */ + ANIMDATA_NODETREE_IDS_CB(mainptr->mat.first, Material); + + /* cameras */ + ANIMDATA_IDS_CB(mainptr->camera.first); + + /* shapekeys */ + ANIMDATA_IDS_CB(mainptr->key.first); + + /* metaballs */ + ANIMDATA_IDS_CB(mainptr->mball.first); + + /* curves */ + ANIMDATA_IDS_CB(mainptr->curve.first); + + /* armatures */ + ANIMDATA_IDS_CB(mainptr->armature.first); + + /* lattices */ + ANIMDATA_IDS_CB(mainptr->latt.first); + + /* meshes */ + ANIMDATA_IDS_CB(mainptr->mesh.first); + + /* particles */ + ANIMDATA_IDS_CB(mainptr->particle.first); + + /* objects */ + ANIMDATA_IDS_CB(mainptr->object.first); + + /* worlds */ + ANIMDATA_IDS_CB(mainptr->world.first); + + /* scenes */ + ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene); } /* Fix all RNA-Paths throughout the database (directly access the Global.main version) @@ -503,17 +725,29 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName, 0, 0, 1);\ } + /* another version of this macro for nodetrees */ +#define RENAMEFIX_ANIM_NODETREE_IDS(first, NtId_Type) \ + for (id= first; id; id= id->next) { \ + AnimData *adt= BKE_animdata_from_id(id); \ + NtId_Type *ntp= (NtId_Type *)id; \ + if (ntp->nodetree) { \ + AnimData *adt2= BKE_animdata_from_id((ID *)ntp); \ + BKE_animdata_fix_paths_rename((ID *)ntp, adt2, prefix, oldName, newName, 0, 0, 1);\ + } \ + BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName, 0, 0, 1);\ + } + /* nodes */ RENAMEFIX_ANIM_IDS(mainptr->nodetree.first); /* textures */ - RENAMEFIX_ANIM_IDS(mainptr->tex.first); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->tex.first, Tex); /* lamps */ RENAMEFIX_ANIM_IDS(mainptr->lamp.first); /* materials */ - RENAMEFIX_ANIM_IDS(mainptr->mat.first); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->mat.first, Material); /* cameras */ RENAMEFIX_ANIM_IDS(mainptr->camera.first); @@ -530,8 +764,11 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa /* armatures */ RENAMEFIX_ANIM_IDS(mainptr->armature.first); + /* lattices */ + RENAMEFIX_ANIM_IDS(mainptr->latt.first); + /* meshes */ - // TODO... + RENAMEFIX_ANIM_IDS(mainptr->mesh.first); /* particles */ RENAMEFIX_ANIM_IDS(mainptr->particle.first); @@ -543,19 +780,7 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa RENAMEFIX_ANIM_IDS(mainptr->world.first); /* scenes */ - for (id= mainptr->scene.first; id; id= id->next) { - AnimData *adt= BKE_animdata_from_id(id); - Scene *scene= (Scene *)id; - - /* do compositing nodes first (since these aren't included in main tree) */ - if (scene->nodetree) { - AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree); - BKE_animdata_fix_paths_rename((ID *)scene->nodetree, adt2, prefix, oldName, newName, 0, 0, 1); - } - - /* now fix scene animation data as per normal */ - BKE_animdata_fix_paths_rename((ID *)id, adt, prefix, oldName, newName, 0, 0, 1); - } + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene); } /* *********************************** */ @@ -565,7 +790,7 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa /* Find the first path that matches the given criteria */ // TODO: do we want some method to perform partial matches too? -KS_Path *BKE_keyingset_find_path (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode) +KS_Path *BKE_keyingset_find_path (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int UNUSED(group_mode)) { KS_Path *ksp; @@ -584,7 +809,7 @@ KS_Path *BKE_keyingset_find_path (KeyingSet *ks, ID *id, const char group_name[] eq_id= 0; /* path */ - if ((ksp->rna_path==0) || strcmp(rna_path, ksp->rna_path)) + if ((ksp->rna_path==NULL) || strcmp(rna_path, ksp->rna_path)) eq_path= 0; /* index - need to compare whole-array setting too... */ @@ -614,12 +839,9 @@ KeyingSet *BKE_keyingset_add (ListBase *list, const char name[], short flag, sho /* allocate new KeyingSet */ ks= MEM_callocN(sizeof(KeyingSet), "KeyingSet"); - - if (name) - strncpy(ks->name, name, sizeof(ks->name)); - else - strcpy(ks->name, "KeyingSet"); - + + BLI_strncpy(ks->name, name ? name : "KeyingSet", sizeof(ks->name)); + ks->flag= flag; ks->keyingflag= keyingflag; @@ -665,9 +887,9 @@ KS_Path *BKE_keyingset_add_path (KeyingSet *ks, ID *id, const char group_name[], /* just store absolute info */ ksp->id= id; if (group_name) - BLI_snprintf(ksp->group, 64, group_name); + BLI_strncpy(ksp->group, group_name, sizeof(ksp->group)); else - strcpy(ksp->group, ""); + ksp->group[0]= '\0'; /* store additional info for relative paths (just in case user makes the set relative) */ if (id) @@ -695,10 +917,11 @@ void BKE_keyingset_free_path (KeyingSet *ks, KS_Path *ksp) /* sanity check */ if ELEM(NULL, ks, ksp) return; - + /* free RNA-path info */ - MEM_freeN(ksp->rna_path); - + if(ksp->rna_path) + MEM_freeN(ksp->rna_path); + /* free path itself */ BLI_freelinkN(&ks->paths, ksp); } @@ -767,7 +990,7 @@ void BKE_keyingsets_free (ListBase *list) * - path: original path string (as stored in F-Curve data) * - dst: destination string to write data to */ -static short animsys_remap_path (AnimMapper *remap, char *path, char **dst) +static short animsys_remap_path (AnimMapper *UNUSED(remap), char *path, char **dst) { /* is there a valid remapping table to use? */ //if (remap) { @@ -1591,9 +1814,6 @@ void nladata_flush_channels (ListBase *channels) */ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) { - ListBase dummy_trackslist = {NULL, NULL}; - NlaStrip dummy_strip; - NlaTrack *nlt; short track_index=0; short has_strips = 0; @@ -1607,7 +1827,7 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) /* 1. get the stack of strips to evaluate at current time (influence calculated here) */ for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) { - /* if tweaking is on and this strip is the tweaking track, stop on this one */ + /* stop here if tweaking is on and this strip is the tweaking track (it will be the first one that's 'disabled')... */ if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) break; @@ -1634,22 +1854,32 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) */ if ((adt->action) && !(adt->flag & ADT_NLA_SOLO_TRACK)) { /* if there are strips, evaluate action as per NLA rules */ - if (has_strips) { + if ((has_strips) || (adt->actstrip)) { /* make dummy NLA strip, and add that to the stack */ - memset(&dummy_strip, 0, sizeof(NlaStrip)); - dummy_trackslist.first= dummy_trackslist.last= &dummy_strip; - - dummy_strip.act= adt->action; - dummy_strip.remap= adt->remap; + NlaStrip dummy_strip= {NULL}; + ListBase dummy_trackslist; - /* action range is calculated taking F-Modifiers into account (which making new strips doesn't do due to the troublesome nature of that) */ - calc_action_range(dummy_strip.act, &dummy_strip.actstart, &dummy_strip.actend, 1); - dummy_strip.start = dummy_strip.actstart; - dummy_strip.end = (IS_EQ(dummy_strip.actstart, dummy_strip.actend)) ? (dummy_strip.actstart + 1.0f): (dummy_strip.actend); + dummy_trackslist.first= dummy_trackslist.last= &dummy_strip; - dummy_strip.blendmode= adt->act_blendmode; - dummy_strip.extendmode= adt->act_extendmode; - dummy_strip.influence= adt->act_influence; + if ((nlt) && !(adt->flag & ADT_NLA_EDIT_NOMAP)) { + /* edit active action in-place according to its active strip, so copy the data */ + memcpy(&dummy_strip, adt->actstrip, sizeof(NlaStrip)); + dummy_strip.next = dummy_strip.prev = NULL; + } + else { + /* set settings of dummy NLA strip from AnimData settings */ + dummy_strip.act= adt->action; + dummy_strip.remap= adt->remap; + + /* action range is calculated taking F-Modifiers into account (which making new strips doesn't do due to the troublesome nature of that) */ + calc_action_range(dummy_strip.act, &dummy_strip.actstart, &dummy_strip.actend, 1); + dummy_strip.start = dummy_strip.actstart; + dummy_strip.end = (IS_EQ(dummy_strip.actstart, dummy_strip.actend)) ? (dummy_strip.actstart + 1.0f): (dummy_strip.actend); + + dummy_strip.blendmode= adt->act_blendmode; + dummy_strip.extendmode= adt->act_extendmode; + dummy_strip.influence= adt->act_influence; + } /* add this to our list of evaluation strips */ nlastrips_ctime_get_strip(&estrips, &dummy_trackslist, -1, ctime); @@ -1685,16 +1915,18 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) /* Clear all overides */ /* Add or get existing Override for given setting */ -AnimOverride *BKE_animsys_validate_override (PointerRNA *ptr, char *path, int array_index) +#if 0 +AnimOverride *BKE_animsys_validate_override (PointerRNA *UNUSED(ptr), char *UNUSED(path), int UNUSED(array_index)) { // FIXME: need to define how to get overrides return NULL; } +#endif /* -------------------- */ /* Evaluate Overrides */ -static void animsys_evaluate_overrides (PointerRNA *ptr, AnimData *adt, float ctime) +static void animsys_evaluate_overrides (PointerRNA *ptr, AnimData *adt) { AnimOverride *aor; @@ -1793,7 +2025,7 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re * - Overrides are cleared upon frame change and/or keyframing * - It is best that we execute this everytime, so that no errors are likely to occur. */ - animsys_evaluate_overrides(&id_ptr, adt, ctime); + animsys_evaluate_overrides(&id_ptr, adt); /* clear recalc flag now */ adt->recalc= 0; @@ -1813,7 +2045,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) if (G.f & G_DEBUG) printf("Evaluate all animation - %f \n", ctime); - /* macro for less typing + /* macros for less typing * - only evaluate animation data for id if it has users (and not just fake ones) * - whether animdata exists is checked for by the evaluation function, though taking * this outside of the function may make things slightly faster? @@ -1825,6 +2057,24 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) BKE_animsys_evaluate_animdata(id, adt, ctime, aflag); \ } \ } + /* another macro for the "embedded" nodetree cases + * - this is like EVAL_ANIM_IDS, but this handles the case "embedded nodetrees" + * (i.e. scene/material/texture->nodetree) which we need a special exception + * for, otherwise they'd get skipped + * - ntp = "node tree parent" = datablock where node tree stuff resides + */ +#define EVAL_ANIM_NODETREE_IDS(first, NtId_Type, aflag) \ + for (id= first; id; id= id->next) { \ + if (ID_REAL_USERS(id) > 0) { \ + AnimData *adt= BKE_animdata_from_id(id); \ + NtId_Type *ntp= (NtId_Type *)id; \ + if (ntp->nodetree) { \ + AnimData *adt2= BKE_animdata_from_id((ID *)ntp->nodetree); \ + BKE_animsys_evaluate_animdata((ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM); \ + } \ + BKE_animsys_evaluate_animdata(id, adt, ctime, aflag); \ + } \ + } /* optimisation: * when there are no actions, don't go over database and loop over heaps of datablocks, @@ -1845,45 +2095,32 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) EVAL_ANIM_IDS(main->nodetree.first, ADT_RECALC_ANIM); /* textures */ - EVAL_ANIM_IDS(main->tex.first, ADT_RECALC_ANIM); + EVAL_ANIM_NODETREE_IDS(main->tex.first, Tex, ADT_RECALC_ANIM); /* lamps */ EVAL_ANIM_IDS(main->lamp.first, ADT_RECALC_ANIM); /* materials */ - EVAL_ANIM_IDS(main->mat.first, ADT_RECALC_ANIM); + EVAL_ANIM_NODETREE_IDS(main->mat.first, Material, ADT_RECALC_ANIM); /* cameras */ EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM); /* shapekeys */ - // TODO: we probably need the same hack as for curves (ctime-hack) EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM); /* metaballs */ EVAL_ANIM_IDS(main->mball.first, ADT_RECALC_ANIM); /* curves */ - /* we need to perform a special hack here to ensure that the ctime - * value of the curve gets set in case there's no animation for that - * - it needs to be set before animation is evaluated just so that - * animation can successfully override... - * - it shouldn't get set when calculating drivers... - */ - for (id= main->curve.first; id; id= id->next) { - AnimData *adt= BKE_animdata_from_id(id); - Curve *cu= (Curve *)id; - - /* set ctime variable for curve */ - cu->ctime= ctime; - - /* now execute animation data on top of this as per normal */ - BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM); - } + EVAL_ANIM_IDS(main->curve.first, ADT_RECALC_ANIM); /* armatures */ EVAL_ANIM_IDS(main->armature.first, ADT_RECALC_ANIM); + /* lattices */ + EVAL_ANIM_IDS(main->latt.first, ADT_RECALC_ANIM); + /* meshes */ EVAL_ANIM_IDS(main->mesh.first, ADT_RECALC_ANIM); @@ -1901,19 +2138,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) EVAL_ANIM_IDS(main->world.first, ADT_RECALC_ANIM); /* scenes */ - for (id= main->scene.first; id; id= id->next) { - AnimData *adt= BKE_animdata_from_id(id); - Scene *scene= (Scene *)id; - - /* do compositing nodes first (since these aren't included in main tree) */ - if (scene->nodetree) { - AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree); - BKE_animsys_evaluate_animdata((ID *)scene->nodetree, adt2, ctime, ADT_RECALC_ANIM); - } - - /* now execute scene animation data as per normal */ - BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM); - } + EVAL_ANIM_NODETREE_IDS(main->scene.first, Scene, ADT_RECALC_ANIM); } /* ***************************************** */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index a482e4051d4..b9ff4c2a30b 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -37,6 +37,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_cellalloc.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -64,13 +65,13 @@ #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_object.h" -#include "BKE_utildefines.h" + #include "BIK_api.h" #include "BKE_sketch.h" /* **************** Generic Functions, data level *************** */ -bArmature *add_armature(char *name) +bArmature *add_armature(const char *name) { bArmature *arm; @@ -136,19 +137,19 @@ void make_local_armature(bArmature *arm) Object *ob; bArmature *newArm; - if (arm->id.lib==0) + if (arm->id.lib==NULL) return; if (arm->id.us==1) { - arm->id.lib= 0; + arm->id.lib= NULL; arm->id.flag= LIB_LOCAL; - new_id(0, (ID*)arm, 0); + new_id(NULL, (ID*)arm, NULL); return; } if(local && lib==0) { - arm->id.lib= 0; + arm->id.lib= NULL; arm->id.flag= LIB_LOCAL; - new_id(0, (ID *)arm, 0); + new_id(NULL, (ID *)arm, NULL); } else if(local && lib) { newArm= copy_armature(arm); @@ -158,7 +159,7 @@ void make_local_armature(bArmature *arm) while(ob) { if(ob->data==arm) { - if(ob->id.lib==0) { + if(ob->id.lib==NULL) { ob->data= newArm; newArm->id.us++; arm->id.us--; @@ -248,20 +249,19 @@ Bone *get_named_bone (bArmature *arm, const char *name) } /* Finds the best possible extension to the name on a particular axis. (For renaming, check for unique names afterwards) - * This assumes that bone names are at most 32 chars long! * strip_number: removes number extensions (TODO: not used) * axis: the axis to name on * head/tail: the head/tail co-ordinate of the bone on the specified axis */ -int bone_autoside_name (char *name, int strip_number, short axis, float head, float tail) +int bone_autoside_name (char name[MAXBONENAME], int UNUSED(strip_number), short axis, float head, float tail) { unsigned int len; - char basename[32]={""}; - char extension[5]={""}; + char basename[MAXBONENAME]= ""; + char extension[5]= ""; len= strlen(name); if (len == 0) return 0; - strcpy(basename, name); + BLI_strncpy(basename, name, sizeof(basename)); /* Figure out extension to append: * - The extension to append is based upon the axis that we are working on. @@ -350,13 +350,13 @@ int bone_autoside_name (char *name, int strip_number, short axis, float head, fl } } } - - if ((32 - len) < strlen(extension) + 1) { /* add 1 for the '.' */ + + if ((MAXBONENAME - len) < strlen(extension) + 1) { /* add 1 for the '.' */ strncpy(name, basename, len-strlen(extension)); } - - sprintf(name, "%s.%s", basename, extension); - + + BLI_snprintf(name, MAXBONENAME, "%s.%s", basename, extension); + return 1; } @@ -578,23 +578,29 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) /* ************ Armature Deform ******************* */ -static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion) +typedef struct bPoseChanDeform { + Mat4 *b_bone_mats; + DualQuat *dual_quat; + DualQuat *b_bone_dual_quats; +} bPoseChanDeform; + +static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info, int use_quaternion) { Bone *bone= pchan->bone; Mat4 *b_bone= b_bone_spline_setup(pchan, 0); Mat4 *b_bone_rest= b_bone_spline_setup(pchan, 1); Mat4 *b_bone_mats; DualQuat *b_bone_dual_quats= NULL; - float tmat[4][4]; + float tmat[4][4]= MAT4_UNITY; int a; /* allocate b_bone matrices and dual quats */ b_bone_mats= MEM_mallocN((1+bone->segments)*sizeof(Mat4), "BBone defmats"); - pchan->b_bone_mats= b_bone_mats; + pdef_info->b_bone_mats= b_bone_mats; if(use_quaternion) { b_bone_dual_quats= MEM_mallocN((bone->segments)*sizeof(DualQuat), "BBone dqs"); - pchan->b_bone_dual_quats= b_bone_dual_quats; + pdef_info->b_bone_dual_quats= b_bone_dual_quats; } /* first matrix is the inverse arm_mat, to bring points in local bone space @@ -606,7 +612,6 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion) - translate over the curve to the bbone mat space - transform with b_bone matrix - transform back into global space */ - unit_m4(tmat); for(a=0; a<bone->segments; a++) { invert_m4_m4(tmat, b_bone_rest[a].mat); @@ -619,9 +624,9 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion) } } -static void b_bone_deform(bPoseChannel *pchan, Bone *bone, float *co, DualQuat *dq, float defmat[][3]) +static void b_bone_deform(bPoseChanDeform *pdef_info, Bone *bone, float *co, DualQuat *dq, float defmat[][3]) { - Mat4 *b_bone= pchan->b_bone_mats; + Mat4 *b_bone= pdef_info->b_bone_mats; float (*mat)[4]= b_bone[0].mat; float segment, y; int a; @@ -638,7 +643,7 @@ static void b_bone_deform(bPoseChannel *pchan, Bone *bone, float *co, DualQuat * CLAMP(a, 0, bone->segments-1); if(dq) { - copy_dq_dq(dq, &((DualQuat*)pchan->b_bone_dual_quats)[a]); + copy_dq_dq(dq, &(pdef_info->b_bone_dual_quats)[a]); } else { mul_m4_v3(b_bone[a+1].mat, co); @@ -712,7 +717,7 @@ static void pchan_deform_mat_add(bPoseChannel *pchan, float weight, float bbonem add_m3_m3m3(mat, mat, wmat); } -static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, float mat[][3], float *co) +static float dist_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, float *vec, DualQuat *dq, float mat[][3], float *co) { Bone *bone= pchan->bone; float fac, contrib=0.0; @@ -733,7 +738,7 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, flo if(vec) { if(bone->segments>1) // applies on cop and bbonemat - b_bone_deform(pchan, bone, cop, NULL, (mat)?bbonemat:NULL); + b_bone_deform(pdef_info, bone, cop, NULL, (mat)?bbonemat:NULL); else mul_m4_v3(pchan->chan_mat, cop); @@ -746,11 +751,11 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, flo } else { if(bone->segments>1) { - b_bone_deform(pchan, bone, cop, &bbonedq, NULL); + b_bone_deform(pdef_info, bone, cop, &bbonedq, NULL); add_weighted_dq_dq(dq, &bbonedq, fac); } else - add_weighted_dq_dq(dq, pchan->dual_quat, fac); + add_weighted_dq_dq(dq, pdef_info->dual_quat, fac); } } } @@ -758,7 +763,7 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, flo return contrib; } -static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, DualQuat *dq, float mat[][3], float *co, float *contrib) +static void pchan_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, float weight, float *vec, DualQuat *dq, float mat[][3], float *co, float *contrib) { float cop[3], bbonemat[3][3]; DualQuat bbonedq; @@ -771,7 +776,7 @@ static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, Dua if(vec) { if(pchan->bone->segments>1) // applies on cop and bbonemat - b_bone_deform(pchan, pchan->bone, cop, NULL, (mat)?bbonemat:NULL); + b_bone_deform(pdef_info, pchan->bone, cop, NULL, (mat)?bbonemat:NULL); else mul_m4_v3(pchan->chan_mat, cop); @@ -784,11 +789,11 @@ static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, Dua } else { if(pchan->bone->segments>1) { - b_bone_deform(pchan, pchan->bone, cop, &bbonedq, NULL); + b_bone_deform(pdef_info, pchan->bone, cop, &bbonedq, NULL); add_weighted_dq_dq(dq, &bbonedq, weight); } else - add_weighted_dq_dq(dq, pchan->dual_quat, weight); + add_weighted_dq_dq(dq, pdef_info->dual_quat, weight); } (*contrib)+=weight; @@ -799,15 +804,18 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, int numVerts, int deformflag, float (*prevCos)[3], const char *defgrp_name) { + bPoseChanDeform *pdef_info_array; + bPoseChanDeform *pdef_info= NULL; bArmature *arm= armOb->data; bPoseChannel *pchan, **defnrToPC = NULL; + int *defnrToPCIndex= NULL; MDeformVert *dverts = NULL; bDeformGroup *dg; DualQuat *dualquats= NULL; float obinv[4][4], premat[4][4], postmat[4][4]; - int use_envelope = deformflag & ARM_DEF_ENVELOPE; - int use_quaternion = deformflag & ARM_DEF_QUATERNION; - int invert_vgroup= deformflag & ARM_DEF_INVERT_VGROUP; + const short use_envelope = deformflag & ARM_DEF_ENVELOPE; + const short use_quaternion = deformflag & ARM_DEF_QUATERNION; + const short invert_vgroup= deformflag & ARM_DEF_INVERT_VGROUP; int numGroups = 0; /* safety for vertexgroup index overflow */ int i, target_totvert = 0; /* safety for vertexgroup overflow */ int use_dverts = 0; @@ -824,20 +832,24 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, /* bone defmats are already in the channels, chan_mat */ /* initialize B_bone matrices and dual quaternions */ + totchan= BLI_countlist(&armOb->pose->chanbase); + if(use_quaternion) { - totchan= BLI_countlist(&armOb->pose->chanbase); dualquats= MEM_callocN(sizeof(DualQuat)*totchan, "dualquats"); } + + pdef_info_array= MEM_callocN(sizeof(bPoseChanDeform)*totchan, "bPoseChanDeform"); totchan= 0; - for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) { + pdef_info= pdef_info_array; + for(pchan= armOb->pose->chanbase.first; pchan; pchan= pchan->next, pdef_info++) { if(!(pchan->bone->flag & BONE_NO_DEFORM)) { if(pchan->bone->segments > 1) - pchan_b_bone_defmats(pchan, use_quaternion); + pchan_b_bone_defmats(pchan, pdef_info, use_quaternion); if(use_quaternion) { - pchan->dual_quat= &dualquats[totchan++]; - mat4_to_dquat( pchan->dual_quat,pchan->bone->arm_mat, pchan->chan_mat); + pdef_info->dual_quat= &dualquats[totchan++]; + mat4_to_dquat( pdef_info->dual_quat,pchan->bone->arm_mat, pchan->chan_mat); } } } @@ -873,15 +885,19 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, else if(dverts) use_dverts = 1; if(use_dverts) { - defnrToPC = MEM_callocN(sizeof(*defnrToPC) * numGroups, - "defnrToBone"); + defnrToPC = MEM_callocN(sizeof(*defnrToPC) * numGroups, "defnrToBone"); + defnrToPCIndex = MEM_callocN(sizeof(*defnrToPCIndex) * numGroups, "defnrToIndex"); for(i = 0, dg = target->defbase.first; dg; i++, dg = dg->next) { defnrToPC[i] = get_pose_channel(armOb->pose, dg->name); /* exclude non-deforming bones */ if(defnrToPC[i]) { - if(defnrToPC[i]->bone->flag & BONE_NO_DEFORM) + if(defnrToPC[i]->bone->flag & BONE_NO_DEFORM) { defnrToPC[i]= NULL; + } + else { + defnrToPCIndex[i]= BLI_findindex(&armOb->pose->chanbase, defnrToPC[i]); + } } } } @@ -921,19 +937,15 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, dvert = NULL; if(armature_def_nr >= 0 && dvert) { - armature_weight = 0.0f; /* a def group was given, so default to 0 */ - for(j = 0; j < dvert->totweight; j++) { - if(dvert->dw[j].def_nr == armature_def_nr) { - armature_weight = dvert->dw[j].weight; - break; - } + armature_weight= defvert_find_weight(dvert, armature_def_nr); + + if(invert_vgroup) { + armature_weight= 1.0f-armature_weight; } + /* hackish: the blending factor can be used for blending with prevCos too */ if(prevCos) { - if(invert_vgroup) - prevco_weight= 1.0f-armature_weight; - else - prevco_weight= armature_weight; + prevco_weight= armature_weight; armature_weight= 1.0f; } } @@ -952,10 +964,10 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, for(j = 0; j < dvert->totweight; j++){ int index = dvert->dw[j].def_nr; - pchan = index < numGroups?defnrToPC[index]:NULL; - if(pchan) { + if(index < numGroups && (pchan= defnrToPC[index])) { float weight = dvert->dw[j].weight; - Bone *bone = pchan->bone; + Bone *bone= pchan->bone; + pdef_info= pdef_info_array + defnrToPCIndex[index]; deformed = 1; @@ -966,25 +978,27 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, bone->rad_tail, bone->dist); } - pchan_bone_deform(pchan, weight, vec, dq, smat, co, &contrib); + pchan_bone_deform(pchan, pdef_info, weight, vec, dq, smat, co, &contrib); } } /* if there are vertexgroups but not groups with bones * (like for softbody groups) */ if(deformed == 0 && use_envelope) { - for(pchan = armOb->pose->chanbase.first; pchan; - pchan = pchan->next) { + pdef_info= pdef_info_array; + for(pchan= armOb->pose->chanbase.first; pchan; + pchan= pchan->next, pdef_info++) { if(!(pchan->bone->flag & BONE_NO_DEFORM)) - contrib += dist_bone_deform(pchan, vec, dq, smat, co); + contrib += dist_bone_deform(pchan, pdef_info, vec, dq, smat, co); } } } else if(use_envelope) { + pdef_info= pdef_info_array; for(pchan = armOb->pose->chanbase.first; pchan; - pchan = pchan->next) { + pchan = pchan->next, pdef_info++) { if(!(pchan->bone->flag & BONE_NO_DEFORM)) - contrib += dist_bone_deform(pchan, vec, dq, smat, co); + contrib += dist_bone_deform(pchan, pdef_info, vec, dq, smat, co); } } @@ -1040,25 +1054,25 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, if(dualquats) MEM_freeN(dualquats); if(defnrToPC) MEM_freeN(defnrToPC); - + if(defnrToPCIndex) MEM_freeN(defnrToPCIndex); + /* free B_bone matrices */ - for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) { - if(pchan->b_bone_mats) { - MEM_freeN(pchan->b_bone_mats); - pchan->b_bone_mats = NULL; + pdef_info= pdef_info_array; + for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next, pdef_info++) { + if(pdef_info->b_bone_mats) { + MEM_freeN(pdef_info->b_bone_mats); } - if(pchan->b_bone_dual_quats) { - MEM_freeN(pchan->b_bone_dual_quats); - pchan->b_bone_dual_quats = NULL; + if(pdef_info->b_bone_dual_quats) { + MEM_freeN(pdef_info->b_bone_dual_quats); } - - pchan->dual_quat = NULL; } + + MEM_freeN(pdef_info_array); } /* ************ END Armature Deform ******************* */ -void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed) +void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int UNUSED(root), int UNUSED(posed)) { copy_m4_m4(M_accumulatedMatrix, bone->arm_mat); } @@ -1086,11 +1100,10 @@ void armature_mat_world_to_pose(Object *ob, float inmat[][4], float outmat[][4]) */ void armature_loc_world_to_pose(Object *ob, float *inloc, float *outloc) { - float xLocMat[4][4]; + float xLocMat[4][4]= MAT4_UNITY; float nLocMat[4][4]; /* build matrix for location */ - unit_m4(xLocMat); VECCOPY(xLocMat[3], inloc); /* get bone-space cursor matrix and extract location */ @@ -1106,22 +1119,50 @@ void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float outm { float pc_trans[4][4], inv_trans[4][4]; float pc_posemat[4][4], inv_posemat[4][4]; - + float pose_mat[4][4]; + /* paranoia: prevent crashes with no pose-channel supplied */ if (pchan==NULL) return; - - /* get the inverse matrix of the pchan's transforms */ - if (pchan->rotmode) - loc_eul_size_to_mat4(pc_trans, pchan->loc, pchan->eul, pchan->size); - else - loc_quat_size_to_mat4(pc_trans, pchan->loc, pchan->quat, pchan->size); + + /* default flag */ + if((pchan->bone->flag & BONE_NO_LOCAL_LOCATION)==0) { + /* get the inverse matrix of the pchan's transforms */ + switch(pchan->rotmode) { + case ROT_MODE_QUAT: + loc_quat_size_to_mat4(pc_trans, pchan->loc, pchan->quat, pchan->size); + break; + case ROT_MODE_AXISANGLE: + loc_axisangle_size_to_mat4(pc_trans, pchan->loc, pchan->rotAxis, pchan->rotAngle, pchan->size); + break; + default: /* euler */ + loc_eul_size_to_mat4(pc_trans, pchan->loc, pchan->eul, pchan->size); + } + + copy_m4_m4(pose_mat, pchan->pose_mat); + } + else { + /* local location, this is not default, different calculation + * note: only tested for location with pose bone snapping. + * If this is not useful in other cases the BONE_NO_LOCAL_LOCATION + * case may have to be split into its own function. */ + unit_m4(pc_trans); + copy_v3_v3(pc_trans[3], pchan->loc); + + /* use parents rotation/scale space + own absolute position */ + if(pchan->parent) copy_m4_m4(pose_mat, pchan->parent->pose_mat); + else unit_m4(pose_mat); + + copy_v3_v3(pose_mat[3], pchan->pose_mat[3]); + } + + invert_m4_m4(inv_trans, pc_trans); /* Remove the pchan's transforms from it's pose_mat. * This should leave behind the effects of restpose + * parenting + constraints */ - mul_m4_m4m4(pc_posemat, inv_trans, pchan->pose_mat); + mul_m4_m4m4(pc_posemat, inv_trans, pose_mat); /* get the inverse of the leftovers so that we can remove * that component from the supplied matrix @@ -1138,11 +1179,10 @@ void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float outm */ void armature_loc_pose_to_bone(bPoseChannel *pchan, float *inloc, float *outloc) { - float xLocMat[4][4]; + float xLocMat[4][4]= MAT4_UNITY; float nLocMat[4][4]; /* build matrix for location */ - unit_m4(xLocMat); VECCOPY(xLocMat[3], inloc); /* get bone-space cursor matrix and extract location */ @@ -1150,32 +1190,30 @@ void armature_loc_pose_to_bone(bPoseChannel *pchan, float *inloc, float *outloc) VECCOPY(outloc, nLocMat[3]); } +/* same as object_mat3_to_rot() */ +void pchan_mat3_to_rot(bPoseChannel *pchan, float mat[][3], short use_compat) +{ + switch(pchan->rotmode) { + case ROT_MODE_QUAT: + mat3_to_quat(pchan->quat, mat); + break; + case ROT_MODE_AXISANGLE: + mat3_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, mat); + break; + default: /* euler */ + if(use_compat) mat3_to_compatible_eulO(pchan->eul, pchan->eul, pchan->rotmode, mat); + else mat3_to_eulO(pchan->eul, pchan->rotmode, mat); + } +} /* Apply a 4x4 matrix to the pose bone, * similar to object_apply_mat4() */ -void pchan_apply_mat4(bPoseChannel *pchan, float mat[][4]) +void pchan_apply_mat4(bPoseChannel *pchan, float mat[][4], short use_compat) { - /* location */ - copy_v3_v3(pchan->loc, mat[3]); - - /* scale */ - mat4_to_size(pchan->size, mat); - - /* rotation */ - if (pchan->rotmode == ROT_MODE_AXISANGLE) { - float tmp_quat[4]; - - /* need to convert to quat first (in temp var)... */ - mat4_to_quat(tmp_quat, mat); - quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, tmp_quat); - } - else if (pchan->rotmode == ROT_MODE_QUAT) { - mat4_to_quat(pchan->quat, mat); - } - else { - mat4_to_eulO(pchan->eul, pchan->rotmode, mat); - } + float rot[3][3]; + mat4_to_loc_rot_size(pchan->loc, rot, pchan->size, mat); + pchan_mat3_to_rot(pchan, rot, use_compat); } /* Remove rest-position effects from pose-transform for obtaining @@ -1207,6 +1245,7 @@ void BKE_rotMode_change_values (float quat[4], float eul[3], float axis[3], floa } else if (oldMode == ROT_MODE_QUAT) { /* quat to euler */ + normalize_qt(quat); quat_to_eulO( eul, newMode,quat); } /* else { no conversion needed } */ @@ -1229,6 +1268,7 @@ void BKE_rotMode_change_values (float quat[4], float eul[3], float axis[3], floa } else if (oldMode == ROT_MODE_QUAT) { /* quat to axis angle */ + normalize_qt(quat); quat_to_axis_angle( axis, angle,quat); } @@ -1290,7 +1330,9 @@ void vec_roll_to_mat3(float *vec, float roll, float mat[][3]) /* Find Axis & Amount for bone matrix*/ cross_v3_v3v3(axis,target,nor); - if (dot_v3v3(axis,axis) > 0.0000000000001) { + /* was 0.0000000000001, caused bug [#23954], smaller values give unstable + * roll when toggling editmode */ + if (dot_v3v3(axis,axis) > 0.00001) { /* if nor is *not* a multiple of target ... */ normalize_v3(axis); @@ -1359,13 +1401,6 @@ void where_is_armature_bone(Bone *bone, Bone *prevbone) VECCOPY(bone->arm_mat[3], bone->head); } - /* head */ - VECCOPY(bone->arm_head, bone->arm_mat[3]); - /* tail is in current local coord system */ - VECCOPY(vec, bone->arm_mat[1]); - mul_v3_fl(vec, bone->length); - add_v3_v3v3(bone->arm_tail, bone->arm_head, vec); - /* and the kiddies */ prevbone= bone; for(bone= bone->childbase.first; bone; bone= bone->next) { @@ -1410,10 +1445,6 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected if(error) return; - /* exception, armature local layer should be proxied too */ - if (pose->proxy_layer) - ((bArmature *)ob->data)->layer= pose->proxy_layer; - /* clear all transformation values from library */ rest_pose(frompose); @@ -1459,7 +1490,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected */ extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints); copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE); - addlisttolist(&pchanw.constraints, &proxylocal_constraints); + BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints); /* constraints - set target ob pointer to own object */ for (con= pchanw.constraints.first; con; con= con->next) { @@ -1615,7 +1646,7 @@ typedef struct tSplineIK_Tree { /* ----------- */ /* Tag the bones in the chain formed by the given bone for IK */ -static void splineik_init_tree_from_pchan(Scene *scene, Object *ob, bPoseChannel *pchan_tip) +static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPoseChannel *pchan_tip) { bPoseChannel *pchan, *pchanRoot=NULL; bPoseChannel *pchanChain[255]; @@ -1688,28 +1719,25 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *ob, bPoseChannel ikData->numpoints= ikData->chainlen+1; ikData->points= MEM_callocN(sizeof(float)*ikData->numpoints, "Spline IK Binding"); + /* bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint) */ + ikData->points[0] = 1.0f; + /* perform binding of the joints to parametric positions along the curve based * proportion of the total length that each bone occupies */ for (i = 0; i < segcount; i++) { - if (i != 0) { - /* 'head' joints - * - 2 methods; the one chosen depends on whether we've got usable lengths - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) { - /* 1) equi-spaced joints */ - ikData->points[i]= ikData->points[i-1] - segmentLen; - } - else { - /* 2) to find this point on the curve, we take a step from the previous joint - * a distance given by the proportion that this bone takes - */ - ikData->points[i]= ikData->points[i-1] - (boneLengths[i] / totLength); - } + /* 'head' joints, travelling towards the root of the chain + * - 2 methods; the one chosen depends on whether we've got usable lengths + */ + if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) { + /* 1) equi-spaced joints */ + ikData->points[i+1]= ikData->points[i] - segmentLen; } else { - /* 'tip' of chain, special exception for the first joint */ - ikData->points[0]= 1.0f; + /* 2) to find this point on the curve, we take a step from the previous joint + * a distance given by the proportion that this bone takes + */ + ikData->points[i+1]= ikData->points[i] - (boneLengths[i] / totLength); } } @@ -1784,7 +1812,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *ob, bPoseChannel } /* Tag which bones are members of Spline IK chains */ -static void splineik_init_tree(Scene *scene, Object *ob, float ctime) +static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime)) { bPoseChannel *pchan; @@ -1989,7 +2017,9 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o /* finally, store the new transform */ copy_m4_m4(pchan->pose_mat, poseMat); VECCOPY(pchan->pose_head, poseHead); - VECCOPY(pchan->pose_tail, poseTail); + + /* recalculate tail, as it's now outdated after the head gets adjusted above! */ + where_is_pose_bone_tail(pchan); /* done! */ pchan->flag |= POSE_DONE; @@ -2054,8 +2084,7 @@ void pchan_to_mat4(bPoseChannel *pchan, float chan_mat[4][4]) * but if this proves to be too problematic, switch back to the old system of operating directly on * the stored copy */ - QUATCOPY(quat, pchan->quat); - normalize_qt(quat); + normalize_qt_qt(quat, pchan->quat); quat_to_mat3(rmat, quat); } @@ -2072,7 +2101,7 @@ void pchan_to_mat4(bPoseChannel *pchan, float chan_mat[4][4]) /* loc/rot/size to mat4 */ /* used in constraint.c too */ -void chan_calc_mat(bPoseChannel *pchan) +void pchan_calc_mat(bPoseChannel *pchan) { /* this is just a wrapper around the copy of this function which calculates the matrix * and stores the result in any given channel @@ -2202,6 +2231,15 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha } } +/* calculate tail of posechannel */ +void where_is_pose_bone_tail(bPoseChannel *pchan) +{ + float vec[3]; + + VECCOPY(vec, pchan->pose_mat[1]); + mul_v3_fl(vec, pchan->bone->length); + add_v3_v3v3(pchan->pose_tail, pchan->pose_head, vec); +} /* The main armature solver, does all constraints excluding IK */ /* pchan is validated, as having bone and parent pointer @@ -2219,7 +2257,7 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti parchan= pchan->parent; /* this gives a chan_mat with actions (ipos) results */ - if(do_extra) chan_calc_mat(pchan); + if(do_extra) pchan_calc_mat(pchan); else unit_m4(pchan->chan_mat); /* construct the posemat based on PoseChannels, that we do before applying constraints */ @@ -2238,13 +2276,28 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti offs_bone[3][1]+= parbone->length; /* Compose the matrix for this bone */ - if(bone->flag & BONE_HINGE) { // uses restposition rotation, but actual position + if((bone->flag & BONE_HINGE) && (bone->flag & BONE_NO_SCALE)) { // uses restposition rotation, but actual position float tmat[4][4]; - /* the rotation of the parent restposition */ copy_m4_m4(tmat, parbone->arm_mat); mul_serie_m4(pchan->pose_mat, tmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); } + else if(bone->flag & BONE_HINGE) { // same as above but apply parent scale + float tmat[4][4]; + + /* apply the parent matrix scale */ + float tsmat[4][4], tscale[3]; + + /* the rotation of the parent restposition */ + copy_m4_m4(tmat, parbone->arm_mat); + + /* extract the scale of the parent matrix */ + mat4_to_size(tscale, parchan->pose_mat); + size_to_mat4(tsmat, tscale); + mul_m4_m4m4(tmat, tmat, tsmat); + + mul_serie_m4(pchan->pose_mat, tmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); + } else if(bone->flag & BONE_NO_SCALE) { float orthmat[4][4]; @@ -2320,9 +2373,7 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti /* calculate head */ VECCOPY(pchan->pose_head, pchan->pose_mat[3]); /* calculate tail */ - VECCOPY(vec, pchan->pose_mat[1]); - mul_v3_fl(vec, bone->length); - add_v3_v3v3(pchan->pose_tail, pchan->pose_head, vec); + where_is_pose_bone_tail(pchan); } /* This only reads anim data from channels, and writes to channels */ @@ -2340,7 +2391,7 @@ void where_is_pose (Scene *scene, Object *ob) if(ELEM(NULL, arm, scene)) return; if((ob->pose==NULL) || (ob->pose->flag & POSE_RECALC)) - armature_rebuild_pose(ob, arm); + armature_rebuild_pose(ob, arm); ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0); /* not accurate... */ diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 0f2218b8766..0556acbdece 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -32,7 +32,6 @@ #ifndef _WIN32 #include <unistd.h> // for read close - #include <sys/param.h> // for MAXPATHLEN #else #include <io.h> // for open close read #define open _open @@ -56,8 +55,10 @@ #include "DNA_sound_types.h" #include "BLI_blenlib.h" +#include "BLI_bpath.h" #include "BLI_dynstr.h" #include "BLI_path_util.h" +#include "BLI_utildefines.h" #include "IMB_imbuf.h" @@ -81,16 +82,16 @@ #include "BLO_readfile.h" #include "BLO_writefile.h" -#include "BKE_utildefines.h" // O_BINARY FALSE +#include "BKE_utildefines.h" #include "WM_api.h" // XXXXX BAD, very BAD dependency (bad level call) - remove asap, elubie Global G; UserDef U; -ListBase WMlist= {NULL, NULL}; +/* ListBase = {NULL, NULL}; */ short ENDIAN_ORDER; -char versionstr[48]= ""; +static char versionstr[48]= ""; /* ********** free ********** */ @@ -123,9 +124,9 @@ void initglobals(void) ENDIAN_ORDER= (((char*)&ENDIAN_ORDER)[0])? L_ENDIAN: B_ENDIAN; if(BLENDER_SUBVERSION) - sprintf(versionstr, "www.blender.org %d.%d", BLENDER_VERSION, BLENDER_SUBVERSION); + BLI_snprintf(versionstr, sizeof(versionstr), "www.blender.org %d.%d", BLENDER_VERSION, BLENDER_SUBVERSION); else - sprintf(versionstr, "www.blender.org %d", BLENDER_VERSION); + BLI_snprintf(versionstr, sizeof(versionstr), "www.blender.org %d", BLENDER_VERSION); #ifdef _WIN32 // FULLSCREEN G.windowstate = G_WINDOWSTATE_USERDEF; @@ -155,50 +156,33 @@ static void clear_global(void) /* make sure path names are correct for OS */ static void clean_paths(Main *main) { - Image *image= main->image.first; - bSound *sound= main->sound.first; - Scene *scene= main->scene.first; - Editing *ed; - Sequence *seq; - Strip *strip; - - while(image) { - BLI_clean(image->name); - image= image->id.next; - } - - while(sound) { - BLI_clean(sound->name); - sound= sound->id.next; - } - - while(scene) { - ed= seq_give_editing(scene, 0); - if(ed) { - seq= ed->seqbasep->first; - while(seq) { - if(seq->plugin) { - BLI_clean(seq->plugin->name); - } - strip= seq->strip; - while(strip) { - BLI_clean(strip->dir); - strip= strip->next; - } - seq= seq->next; - } - } + struct BPathIterator *bpi; + char filepath_expanded[1024]; + Scene *scene; + + for(BLI_bpathIterator_init(&bpi, main, main->name, BPATH_USE_PACKED); !BLI_bpathIterator_isDone(bpi); BLI_bpathIterator_step(bpi)) { + BLI_bpathIterator_getPath(bpi, filepath_expanded); + + BLI_clean(filepath_expanded); + + BLI_bpathIterator_setPath(bpi, filepath_expanded); + } + + BLI_bpathIterator_free(bpi); + + for(scene= main->scene.first; scene; scene= scene->id.next) { BLI_clean(scene->r.backbuf); BLI_clean(scene->r.pic); - - scene= scene->id.next; } } /* context matching */ /* handle no-ui case */ -static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename) +/* note, this is called on Undo so any slow conversion functions here + * should be avoided or check (mode!='u') */ + +static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filename) { bScreen *curscreen= NULL; Scene *curscene= NULL; @@ -211,9 +195,12 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename) else mode= 0; recover= (G.fileflags & G_FILE_RECOVER); - - clean_paths(bfd->main); - + + /* Only make filepaths compatible when loading for real (not undo) */ + if(mode != 'u') { + clean_paths(bfd->main); + } + /* XXX here the complex windowmanager matching */ /* no load screens? */ @@ -238,6 +225,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename) } /* free G.main Main database */ +// CTX_wm_manager_set(C, NULL); clear_global(); G.main= bfd->main; @@ -262,7 +250,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename) G.winpos= bfd->winpos; G.displaymode= bfd->displaymode; G.fileflags= bfd->fileflags; - + CTX_wm_manager_set(C, bfd->main->wm.first); CTX_wm_screen_set(C, bfd->curscreen); CTX_data_scene_set(C, bfd->curscreen->scene); CTX_wm_area_set(C, NULL); @@ -309,10 +297,8 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename) #endif /* these are the same at times, should never copy to the same location */ - if(G.sce != filename) - BLI_strncpy(G.sce, filename, FILE_MAX); - - BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */ + if(G.main->name != filename) + BLI_strncpy(G.main->name, filename, FILE_MAX); /* baseflags, groups, make depsgraph, etc */ set_scene_bg(G.main, CTX_data_scene(C)); @@ -328,7 +314,7 @@ static int handle_subversion_warning(Main *main) char str[128]; - sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile); + BLI_snprintf(str, sizeof(str), "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile); // XXX error(str); } return 1; @@ -359,18 +345,12 @@ void BKE_userdef_free(void) BLI_freelistN(&U.addons); } -/* returns: - 0: no load file - 1: OK - 2: OK, and with new user settings -*/ - -int BKE_read_file(bContext *C, char *dir, void *unused, ReportList *reports) +int BKE_read_file(bContext *C, const char *dir, ReportList *reports) { BlendFileData *bfd; int retval= 1; - if(strstr(dir, BLENDER_STARTUP_FILE)==0) /* dont print user-pref loading */ + if(strstr(dir, BLENDER_STARTUP_FILE)==NULL) /* dont print user-pref loading */ printf("read blend: %s\n", dir); bfd= BLO_read_from_file(dir, reports); @@ -392,7 +372,7 @@ int BKE_read_file(bContext *C, char *dir, void *unused, ReportList *reports) return (bfd?retval:0); } -int BKE_read_file_from_memory(bContext *C, char* filebuf, int filelength, void *unused, ReportList *reports) +int BKE_read_file_from_memory(bContext *C, char* filebuf, int filelength, ReportList *reports) { BlendFileData *bfd; @@ -410,7 +390,7 @@ int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *report { BlendFileData *bfd; - bfd= BLO_read_from_memfile(CTX_data_main(C), G.sce, memfile, reports); + bfd= BLO_read_from_memfile(CTX_data_main(C), G.main->name, memfile, reports); if (bfd) setup_app_data(C, bfd, "<memory1>"); else @@ -460,37 +440,38 @@ static UndoElem *curundo= NULL; static int read_undosave(bContext *C, UndoElem *uel) { - char scestr[FILE_MAXDIR+FILE_MAXFILE]; /* we should eventually just use G.main->name */ - char mainstr[FILE_MAXDIR+FILE_MAXFILE]; + char mainstr[sizeof(G.main->name)]; int success=0, fileflags; /* This is needed so undoing/redoing doesnt crash with threaded previews going */ WM_jobs_stop_all(CTX_wm_manager(C)); - - strcpy(scestr, G.sce); /* temporal store */ + + BLI_strncpy(mainstr, G.main->name, sizeof(mainstr)); /* temporal store */ + strcpy(mainstr, G.main->name); /* temporal store */ fileflags= G.fileflags; G.fileflags |= G_FILE_NO_UI; if(UNDO_DISK) - success= BKE_read_file(C, uel->str, NULL, NULL); + success= (BKE_read_file(C, uel->str, NULL) != BKE_READ_FILE_FAIL); else success= BKE_read_file_from_memfile(C, &uel->memfile, NULL); /* restore */ - strcpy(G.sce, scestr); /* restore */ - strcpy(G.main->name, mainstr); /* restore */ + BLI_strncpy(G.main->name, mainstr, sizeof(G.main->name)); /* restore */ G.fileflags= fileflags; - if(success) - DAG_on_load_update(G.main); + if(success) { + /* important not to update time here, else non keyed tranforms are lost */ + DAG_on_load_update(G.main, FALSE); + } return success; } /* name can be a dynamic string */ -void BKE_write_undo(bContext *C, char *name) +void BKE_write_undo(bContext *C, const char *name) { uintptr_t maxmem, totmem, memused; int nr, success; @@ -541,12 +522,12 @@ void BKE_write_undo(bContext *C, char *name) counter++; counter= counter % U.undosteps; - sprintf(numstr, "%d.blend", counter); + BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter); BLI_make_file_string("/", tstr, btempdir, numstr); success= BLO_write_file(CTX_data_main(C), tstr, G.fileflags, NULL, NULL); - strcpy(curundo->str, tstr); + BLI_strncpy(curundo->str, tstr, sizeof(curundo->str)); } else { MemFile *prevfile=NULL; @@ -554,7 +535,7 @@ void BKE_write_undo(bContext *C, char *name) if(curundo->prev) prevfile= &(curundo->prev->memfile); memused= MEM_get_memory_in_use(); - success= BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags, NULL); + success= BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags); curundo->undosize= MEM_get_memory_in_use() - memused; } @@ -657,6 +638,22 @@ void BKE_undo_name(bContext *C, const char *name) } } +/* name optional */ +int BKE_undo_valid(const char *name) +{ + if(name) { + UndoElem *uel; + + for(uel= undobase.last; uel; uel= uel->prev) + if(strcmp(name, uel->name)==0) + break; + + return uel && uel->prev; + } + + return undobase.last != undobase.first; +} + char *BKE_undo_menu_string(void) { @@ -726,7 +723,7 @@ void BKE_undo_save(char *fname) Main *BKE_undo_get_main(Scene **scene) { Main *mainp= NULL; - BlendFileData *bfd= BLO_read_from_memfile(G.main, G.sce, &curundo->memfile, NULL); + BlendFileData *bfd= BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL); if(bfd) { mainp= bfd->main; diff --git a/source/blender/blenkernel/intern/bmesh_private.h b/source/blender/blenkernel/intern/bmesh_private.h index 713194c9806..b14383378ab 100644 --- a/source/blender/blenkernel/intern/bmesh_private.h +++ b/source/blender/blenkernel/intern/bmesh_private.h @@ -1,4 +1,4 @@ -/** +/* * BME_private.h jan 2007 * * low level, 'private' function prototypes for bmesh kernel. diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index e2a6c04450b..1d4bdf8bf44 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -1,4 +1,4 @@ -/** +/* * bmfont.c * * 04-10-2000 frank @@ -54,6 +54,7 @@ #include "BKE_global.h" #include "IMB_imbuf_types.h" +#include "BKE_bmfont.h" #include "BKE_bmfont_types.h" void printfGlyph(bmGlyph * glyph) diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 54ffda6c0a9..ae4882b0eca 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -41,11 +41,13 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_kdtree.h" +#include "BLI_utildefines.h" + #include "BKE_collision.h" #include "BKE_effect.h" #include "BKE_boids.h" #include "BKE_particle.h" -#include "BKE_utildefines.h" + #include "BKE_modifier.h" #include "RNA_enum_types.h" @@ -58,7 +60,7 @@ typedef struct BoidValues { static int apply_boid_rule(BoidBrainData *bbd, BoidRule *rule, BoidValues *val, ParticleData *pa, float fuzziness); -static int rule_none(BoidRule *rule, BoidBrainData *data, BoidValues *val, ParticleData *pa) +static int rule_none(BoidRule *UNUSED(rule), BoidBrainData *UNUSED(data), BoidValues *UNUSED(val), ParticleData *UNUSED(pa)) { return 0; } @@ -205,7 +207,9 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * add_v3_v3v3(col.co2, pa->prev_state.co, pa->prev_state.vel); sub_v3_v3v3(ray_dir, col.co2, col.co1); mul_v3_fl(ray_dir, acbr->look_ahead); - col.t = 0.0f; + col.f = 0.0f; + col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f); + col.dfra = bbd->dfra; hit.index = -1; hit.dist = col.ray_len = len_v3(ray_dir); @@ -240,6 +244,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size); bbd->wanted_speed = sqrt(t) * len_v3(pa->prev_state.vel); + bbd->wanted_speed = MAX2(bbd->wanted_speed, val->min_speed); return 1; } @@ -343,7 +348,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * return ret; } -static int rule_separate(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa) +static int rule_separate(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *val, ParticleData *pa) { KDTreeNearest *ptn = NULL; ParticleTarget *pt; @@ -383,7 +388,7 @@ static int rule_separate(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Pa } return ret; } -static int rule_flock(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa) +static int rule_flock(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *UNUSED(val), ParticleData *pa) { KDTreeNearest ptn[11]; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; @@ -736,6 +741,7 @@ static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData * val->jump_speed = 0.0f; /* no jumping in air */ } } + static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *ground_co, float *ground_nor) { BoidParticle *bpa = pa->boid; @@ -765,16 +771,17 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro if(!bbd->sim->colliders) return NULL; + /* first try to find below boid */ copy_v3_v3(col.co1, pa->state.co); - copy_v3_v3(col.co2, pa->state.co); - add_v3_v3(col.co1, zvec); + sub_v3_v3v3(col.co2, pa->state.co, zvec); sub_v3_v3(col.co2, zvec); sub_v3_v3v3(ray_dir, col.co2, col.co1); - col.t = 0.0f; + col.f = 0.0f; + col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f); + col.dfra = bbd->dfra; hit.index = -1; hit.dist = col.ray_len = len_v3(ray_dir); - /* find out upmost deflector object */ for(coll = bbd->sim->colliders->first; coll; coll = coll->next){ col.ob = coll->ob; col.md = coll->collmd; @@ -789,17 +796,42 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro normalize_v3_v3(ground_nor, col.nor); return col.hit_ob; } - else { - /* default to z=0 */ - VECCOPY(ground_co, pa->state.co); - ground_co[2] = 0; - ground_nor[0] = ground_nor[1] = 0.0f; - ground_nor[2] = 1.0f; - return NULL; + + /* couldn't find below, so find upmost deflector object */ + add_v3_v3v3(col.co1, pa->state.co, zvec); + sub_v3_v3v3(col.co2, pa->state.co, zvec); + sub_v3_v3(col.co2, zvec); + sub_v3_v3v3(ray_dir, col.co2, col.co1); + col.f = 0.0f; + col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f); + col.dfra = bbd->dfra; + hit.index = -1; + hit.dist = col.ray_len = len_v3(ray_dir); + + for(coll = bbd->sim->colliders->first; coll; coll = coll->next){ + col.ob = coll->ob; + col.md = coll->collmd; + + if(col.md && col.md->bvhtree) + BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); + } + /* then use that object */ + if(hit.index>=0) { + t = hit.dist/col.ray_len; + interp_v3_v3v3(ground_co, col.co1, col.co2, t); + normalize_v3_v3(ground_nor, col.nor); + return col.hit_ob; } + + /* default to z=0 */ + VECCOPY(ground_co, pa->state.co); + ground_co[2] = 0; + ground_nor[0] = ground_nor[1] = 0.0f; + ground_nor[2] = 1.0f; + return NULL; } } -static int boid_rule_applies(ParticleData *pa, BoidSettings *boids, BoidRule *rule) +static int boid_rule_applies(ParticleData *pa, BoidSettings *UNUSED(boids), BoidRule *rule) { BoidParticle *bpa = pa->boid; @@ -1226,14 +1258,18 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) VECADDFAC(pa->state.vel, pa->state.vel, acc, dtime); - if(bpa->data.mode != eBoidMode_InAir) - bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor); + //if(bpa->data.mode != eBoidMode_InAir) + bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor); /* change modes, constrain movement & keep track of down vector */ switch(bpa->data.mode) { case eBoidMode_InAir: { - float grav[3] = {0.0f, 0.0f, bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f}; + float grav[3]; + + grav[0]= 0.0f; + grav[1]= 0.0f; + grav[2]= bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f; /* don't take forward acceleration into account (better banking) */ if(dot_v3v3(bpa->data.acc, pa->state.vel) > 0.0f) { @@ -1255,17 +1291,29 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) boid_find_ground(bbd, pa, ground_co, ground_nor); boid_climb(boids, pa, ground_co, ground_nor); } - /* land boid when belowg ground */ - else if(boids->options & BOID_ALLOW_LAND && pa->state.co[2] <= ground_co[2] + pa->size * boids->height) { - pa->state.co[2] = ground_co[2] + pa->size * boids->height; - pa->state.vel[2] = 0.0f; - bpa->data.mode = eBoidMode_OnLand; + else if(pa->state.co[2] <= ground_co[2] + pa->size * boids->height) { + /* land boid when below ground */ + if(boids->options & BOID_ALLOW_LAND) { + pa->state.co[2] = ground_co[2] + pa->size * boids->height; + pa->state.vel[2] = 0.0f; + bpa->data.mode = eBoidMode_OnLand; + } + /* fly above ground */ + else { + pa->state.co[2] = ground_co[2] + pa->size * boids->height; + pa->state.vel[2] = 0.0f; + } } break; } case eBoidMode_Falling: { - float grav[3] = {0.0f, 0.0f, bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f}; + float grav[3]; + + grav[0]= 0.0f; + grav[1]= 0.0f; + grav[2]= bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f; + /* gather apparent gravity */ VECADDFAC(bpa->gravity, bpa->gravity, grav, dtime); @@ -1355,7 +1403,9 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) /* save direction to state.ave unless the boid is falling */ /* (boids can't effect their direction when falling) */ if(bpa->data.mode!=eBoidMode_Falling && len_v3(pa->state.vel) > 0.1*pa->size) { - normalize_v3_v3(pa->state.ave, pa->state.vel); + copy_v3_v3(pa->state.ave, pa->state.vel); + pa->state.ave[2] *= bbd->part->boids->pitch; + normalize_v3(pa->state.ave); } /* apply damping */ @@ -1420,7 +1470,7 @@ BoidRule *boid_new_rule(int type) rule->type = type; rule->flag |= BOIDRULE_IN_AIR|BOIDRULE_ON_LAND; - strcpy(rule->name, boidrule_type_items[type-1].name); + BLI_strncpy(rule->name, boidrule_type_items[type-1].name, sizeof(rule->name)); return rule; } @@ -1440,6 +1490,7 @@ void boid_default_settings(BoidSettings *boids) boids->landing_smoothness = 3.0f; boids->banking = 1.0f; + boids->pitch = 1.0f; boids->height = 1.0f; boids->health = 1.0f; diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 71a43994363..15404acc105 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -45,6 +45,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_rand.h" +#include "BLI_utildefines.h" #include "BKE_brush.h" #include "BKE_colortools.h" @@ -67,7 +68,7 @@ static void brush_set_defaults(Brush *brush) brush->blend = 0; brush->flag = 0; - brush->ob_mode = (OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT); + brush->ob_mode = OB_MODE_ALL_PAINT; /* BRUSH SCULPT TOOL SETTINGS */ brush->size= 35; /* radius of the brush in pixels */ @@ -147,6 +148,8 @@ Brush *copy_brush(Brush *brush) if (brush->icon_imbuf) brushn->icon_imbuf= IMB_dupImBuf(brush->icon_imbuf); + brushn->preview = NULL; + brushn->curve= curvemapping_copy(brush->curve); /* enable fake user by default */ @@ -183,13 +186,13 @@ void make_local_brush(Brush *brush) Scene *scene; int local= 0, lib= 0; - if(brush->id.lib==0) return; + if(brush->id.lib==NULL) return; if(brush->clone.image) { /* special case: ima always local immediately */ - brush->clone.image->id.lib= 0; + brush->clone.image->id.lib= NULL; brush->clone.image->id.flag= LIB_LOCAL; - new_id(0, (ID *)brush->clone.image, 0); + new_id(NULL, (ID *)brush->clone.image, NULL); } for(scene= G.main->scene.first; scene; scene=scene->id.next) @@ -199,9 +202,9 @@ void make_local_brush(Brush *brush) } if(local && lib==0) { - brush->id.lib= 0; + brush->id.lib= NULL; brush->id.flag= LIB_LOCAL; - new_id(0, (ID *)brush, 0); + new_id(NULL, (ID *)brush, NULL); /* enable fake user by default */ if (!(brush->id.flag & LIB_FAKEUSER)) { @@ -216,7 +219,7 @@ void make_local_brush(Brush *brush) for(scene= G.main->scene.first; scene; scene=scene->id.next) if(paint_brush(&scene->toolsettings->imapaint.paint)==brush) - if(scene->id.lib==0) { + if(scene->id.lib==NULL) { paint_brush_set(&scene->toolsettings->imapaint.paint, brushn); brushn->id.us++; brush->id.us--; @@ -226,10 +229,8 @@ void make_local_brush(Brush *brush) void brush_debug_print_state(Brush *br) { - Brush def; - /* create a fake brush and set it to the defaults */ - memset(&def, 0, sizeof(Brush)); + Brush def= {{NULL}}; brush_set_defaults(&def); #define BR_TEST(field, t) \ @@ -423,7 +424,7 @@ int brush_texture_set_nr(Brush *brush, int nr) id= (ID *)brush->mtex.tex; idtest= (ID*)BLI_findlink(&G.main->tex, nr-1); - if(idtest==0) { /* new tex */ + if(idtest==NULL) { /* new tex */ if(id) idtest= (ID *)copy_texture((Tex *)id); else idtest= (ID *)add_texture("Tex"); idtest->us--; @@ -478,7 +479,7 @@ int brush_clone_image_delete(Brush *brush) } /* Brush Sampling */ -void brush_sample_tex(Brush *brush, float *xy, float *rgba) +void brush_sample_tex(Brush *brush, float *xy, float *rgba, const int thread) { MTex *mtex= &brush->mtex; @@ -491,7 +492,7 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba) co[1]= xy[1]/radius; co[2]= 0.0f; - hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta); + hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); if (hasrgb) { rgba[0]= tr; @@ -528,7 +529,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf if (*outbuf) ibuf= *outbuf; else - ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag, 0); + ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag); if (flt) { for (y=0; y < ibuf->y; y++) { @@ -545,12 +546,12 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius); } else if (texfall == 1) { - brush_sample_tex(brush, xy, dstf); + brush_sample_tex(brush, xy, dstf, 0); } else { dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); - brush_sample_tex(brush, xy, rgba); + brush_sample_tex(brush, xy, rgba, 0); dstf[0] = rgba[0]*brush->rgb[0]; dstf[1] = rgba[1]*brush->rgb[1]; @@ -581,7 +582,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf dst[3]= FTOCHAR(alpha*brush_curve_strength(brush, dist, radius)); } else if (texfall == 1) { - brush_sample_tex(brush, xy, rgba); + brush_sample_tex(brush, xy, rgba, 0); dst[0]= FTOCHAR(rgba[0]); dst[1]= FTOCHAR(rgba[1]); dst[2]= FTOCHAR(rgba[2]); @@ -590,7 +591,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf else { dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); - brush_sample_tex(brush, xy, rgba); + brush_sample_tex(brush, xy, rgba, 0); dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]); dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]); dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]); @@ -737,7 +738,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i xy[0] = x + xoff; xy[1] = y + yoff; - brush_sample_tex(brush, xy, tf); + brush_sample_tex(brush, xy, tf, 0); } bf[0] = tf[0]*mf[0]; @@ -768,7 +769,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i xy[0] = x + xoff; xy[1] = y + yoff; - brush_sample_tex(brush, xy, rgba); + brush_sample_tex(brush, xy, rgba, 0); t[0]= FTOCHAR(rgba[0]); t[1]= FTOCHAR(rgba[1]); t[2]= FTOCHAR(rgba[2]); @@ -794,11 +795,11 @@ static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float imbflag= (cache->flt)? IB_rectfloat: IB_rect; if (!cache->ibuf) - cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag, 0); + cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag); ibuf= cache->ibuf; oldtexibuf= cache->texibuf; - cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag, 0); + cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag); if (oldtexibuf) { srcx= srcy= 0; @@ -906,7 +907,13 @@ static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pres void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos) { - if(brush->jitter){ + int use_jitter= brush->jitter != 0; + + /* jitter-ed brush gives wierd and unpredictable result for this + kinds of stroke, so manyally disable jitter usage (sergey) */ + use_jitter&= (brush->flag & (BRUSH_RESTORE_MESH|BRUSH_ANCHORED)) == 0; + + if(use_jitter){ float rand_pos[2]; const int radius= brush_size(brush); const int diameter= 2*radius; @@ -1096,11 +1103,9 @@ unsigned int *brush_gen_texture_cache(Brush *br, int half_side) { unsigned int *texcache = NULL; MTex *mtex = &br->mtex; - TexResult texres; + TexResult texres= {0}; int hasrgb, ix, iy; int side = half_side * 2; - - memset(&texres, 0, sizeof(TexResult)); if(mtex->tex) { float x, y, step = 2.0 / side, co[3]; diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 0b2f491b28d..7a3c4bd5928 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -1,4 +1,4 @@ -/** +/* * * $Id$ * @@ -23,7 +23,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): André Pinto. + * Contributor(s): Andr Pinto. * * ***** END GPL LICENSE BLOCK ***** */ @@ -34,15 +34,18 @@ #include "DNA_meshdata_types.h" +#include "BLI_editVert.h" +#include "BLI_utildefines.h" + #include "BKE_DerivedMesh.h" -#include "BKE_utildefines.h" + #include "BLI_math.h" #include "MEM_guardedalloc.h" /* Math stuff for ray casting on mesh faces and for nearest surface */ -static float ray_tri_intersection(const BVHTreeRay *ray, const float m_dist, const float *v0, const float *v1, const float *v2) +static float ray_tri_intersection(const BVHTreeRay *ray, const float UNUSED(m_dist), const float *v0, const float *v1, const float *v2) { float dist; @@ -577,16 +580,34 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis); if(tree != NULL) { - for(i = 0; i < numFaces; i++) - { - float co[4][3]; - VECCOPY(co[0], vert[ face[i].v1 ].co); - VECCOPY(co[1], vert[ face[i].v2 ].co); - VECCOPY(co[2], vert[ face[i].v3 ].co); - if(face[i].v4) - VECCOPY(co[3], vert[ face[i].v4 ].co); - - BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3); + /* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */ + EditMesh *em= data->em_evil; + if(em) { + EditFace *efa= em->faces.first; + for(i = 0; i < numFaces; i++, efa= efa->next) { + if(!(efa->f & 1) && efa->h==0 && !((efa->v1->f&1)+(efa->v2->f&1)+(efa->v3->f&1)+(efa->v4?efa->v4->f&1:0))) { + float co[4][3]; + VECCOPY(co[0], vert[ face[i].v1 ].co); + VECCOPY(co[1], vert[ face[i].v2 ].co); + VECCOPY(co[2], vert[ face[i].v3 ].co); + if(face[i].v4) + VECCOPY(co[3], vert[ face[i].v4 ].co); + + BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3); + } + } + } + else { + for(i = 0; i < numFaces; i++) { + float co[4][3]; + VECCOPY(co[0], vert[ face[i].v1 ].co); + VECCOPY(co[1], vert[ face[i].v2 ].co); + VECCOPY(co[2], vert[ face[i].v3 ].co); + if(face[i].v4) + VECCOPY(co[3], vert[ face[i].v4 ].co); + + BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3); + } } BLI_bvhtree_balance(tree); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 0374f4856ca..368e84cce30 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -53,6 +53,13 @@ #include "BLI_pbvh.h" #include "BLI_array.h" #include "BLI_smallhash.h" +#include "BLI_utildefines.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_paint.h" + #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -83,6 +90,7 @@ typedef struct { /* Cached */ struct PBVH *pbvh; int pbvh_draw; + /* Mesh connectivity */ struct ListBase *fmap; struct IndexNode *fmap_mem; @@ -204,7 +212,7 @@ static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm) static int can_pbvh_draw(Object *ob, DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; - Mesh *me= (ob)? ob->data: NULL; + Mesh *me= ob->data; if(ob->sculpt->modifiers_active) return 0; @@ -214,7 +222,6 @@ static int can_pbvh_draw(Object *ob, DerivedMesh *dm) static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; - Mesh *me= (ob)? ob->data: NULL; if(!ob) { cddm->pbvh= NULL; @@ -232,15 +239,42 @@ static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) this derivedmesh is just original mesh. it's the multires subsurf dm that this is actually for, to support a pbvh on a modified mesh */ if(!cddm->pbvh && ob->type == OB_MESH) { + Mesh *me= ob->data; cddm->pbvh = BLI_pbvh_new(); cddm->pbvh_draw = can_pbvh_draw(ob, dm); BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert, me->totface, me->totvert); + + if(ob->sculpt->modifiers_active) { + float (*vertCos)[3]; + int totvert; + + totvert= dm->getNumVerts(dm); + vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos"); + dm->getVertCos(dm, vertCos); + BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos); + MEM_freeN(vertCos); + } } return cddm->pbvh; } +/* update vertex normals so that drawing smooth faces works during sculpt + TODO: proper fix is to support the pbvh in all drawing modes */ +static void cdDM_update_normals_from_pbvh(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*) dm; + float (*face_nors)[3]; + + if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData) + return; + + face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); + + BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors); +} + static void cdDM_drawVerts(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; @@ -304,7 +338,7 @@ static void cdDM_drawUVEdges(DerivedMesh *dm) GPU_uvedge_setup(dm); if( !GPU_buffer_legacy(dm) ) { for(i = 0; i < dm->numFaceData; i++, mf++) { - if(mf->flag&ME_LOOSEEDGE) { + if(!(mf->flag&ME_HIDE)) { draw = 1; } else { @@ -433,7 +467,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm) static void cdDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], - int fast, int (*setMaterial)(int, void *attribs)) + int UNUSED(fast), int (*setMaterial)(int, void *attribs)) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mvert = cddm->mvert; @@ -553,6 +587,8 @@ static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned cha if(col1 && col2) glEnable(GL_CULL_FACE); + cdDM_update_normals_from_pbvh(dm); + if( GPU_buffer_legacy(dm) ) { DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" ); glShadeModel(GL_SMOOTH); @@ -632,6 +668,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, if(!mcol) mcol = dm->getTessFaceDataArray(dm, CD_MCOL); + cdDM_update_normals_from_pbvh(dm); + if( GPU_buffer_legacy(dm) ) { DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" ); for(i = 0; i < dm->numFaceData; i++, mf++) { @@ -712,7 +750,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, GPU_vertex_setup( dm ); GPU_normal_setup( dm ); GPU_uv_setup( dm ); - if( col != 0 ) { + if( col != NULL ) { /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL ) { col = 0; } else if( mcol && dm->drawObject->colType == CD_MCOL ) { @@ -740,6 +778,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, if( !GPU_buffer_legacy(dm) ) { glShadeModel( GL_SMOOTH ); + lastFlag = 0; for(i = 0; i < dm->drawObject->nelements/3; i++) { int actualFace = dm->drawObject->faceRemap[i]; int flag = 1; @@ -750,6 +789,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, else { if(index) { orig = index[actualFace]; + if(orig == ORIGINDEX_NONE) continue; if(drawParamsMapped) flag = drawParamsMapped(userData, orig); } @@ -792,7 +832,7 @@ static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tfa cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL); } -static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) +static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs)) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mv = cddm->mvert; @@ -807,22 +847,24 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us if(!mc) mc = DM_get_tessface_data_layer(dm, CD_MCOL); + cdDM_update_normals_from_pbvh(dm); + /* back-buffer always uses legacy since VBO's would need the * color array temporarily overwritten for drawing, then reset. */ if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) { DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" ); for(i = 0; i < dm->numFaceData; i++, mf++) { int drawSmooth = (mf->flag & ME_SMOOTH); + int draw= 1; - if(index) { - orig = *index++; - if(setDrawOptions && orig == ORIGINDEX_NONE) - { if(nors) nors += 3; continue; } - } - else - orig = i; + orig= (index==NULL) ? i : *index++; + + if(orig == ORIGINDEX_NONE) + draw= setMaterial(mf->mat_nr + 1, NULL); + else if (setDrawOptions != NULL) + draw= setDrawOptions(userData, orig, &drawSmooth); - if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) { + if(draw) { unsigned char *cp = NULL; if(useColors && mc) @@ -887,34 +929,48 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us if( !GPU_buffer_legacy(dm) ) { int tottri = dm->drawObject->nelements/3; glShadeModel(GL_SMOOTH); - - for( i = 0; i < tottri; i++ ) { - int actualFace = dm->drawObject->faceRemap[i]; - int drawSmooth = (mf[actualFace].flag & ME_SMOOTH); - int draw = 1; - - if(index) { - orig = index[actualFace]; - if(setDrawOptions && orig == ORIGINDEX_NONE) - draw = 0; - } - else - orig = actualFace; - - if(draw && setDrawOptions && !setDrawOptions(userData, orig, &drawSmooth)) - draw = 0; - - /* Goal is to draw as long of a contiguous triangle - array as possible, so draw when we hit either an - invisible triangle or at the end of the array */ - if(!draw || i == tottri - 1) { - if(prevstart != i) - /* Add one to the length (via `draw') - if we're drawing at the end of the array */ - glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3); - prevstart = i + 1; + + if(tottri == 0) { + /* avoid buffer problems in following code */ + } + if(setDrawOptions == NULL) { + /* just draw the entire face array */ + glDrawArrays(GL_TRIANGLES, 0, (tottri-1) * 3); + } + else { + /* we need to check if the next material changes */ + int next_actualFace= dm->drawObject->faceRemap[0]; + + for( i = 0; i < tottri; i++ ) { + //int actualFace = dm->drawObject->faceRemap[i]; + int actualFace = next_actualFace; + MFace *mface= mf + actualFace; + int drawSmooth= (mface->flag & ME_SMOOTH); + int draw = 1; + + if(i != tottri-1) + next_actualFace= dm->drawObject->faceRemap[i+1]; + + orig= (index==NULL) ? actualFace : index[actualFace]; + + if(orig == ORIGINDEX_NONE) + draw= setMaterial(mface->mat_nr + 1, NULL); + else if (setDrawOptions != NULL) + draw= setDrawOptions(userData, orig, &drawSmooth); + + /* Goal is to draw as long of a contiguous triangle + array as possible, so draw when we hit either an + invisible triangle or at the end of the array */ + if(!draw || i == tottri - 1 || mf[actualFace].mat_nr != mf[next_actualFace].mat_nr) { + if(prevstart != i) + /* Add one to the length (via `draw') + if we're drawing at the end of the array */ + glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3); + prevstart = i + 1; + } } } + glShadeModel(GL_FLAT); } GPU_buffer_unbind(); @@ -926,28 +982,6 @@ static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); } -#define PASSVERT(index, vert) { \ - if(attribs.totorco) \ - glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \ - for(b = 0; b < attribs.tottface; b++) { \ - MTFace *tf = &attribs.tface[b].array[a]; \ - glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ - } \ - for(b = 0; b < attribs.totmcol; b++) { \ - MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \ - GLubyte col[4]; \ - col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ - glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ - } \ - if(attribs.tottang) { \ - float *tang = attribs.tang.array[a*4 + vert]; \ - glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ - } \ - if(smoothnormal) \ - glNormal3sv(mvert[index].no); \ - glVertex3fv(mvert[index].co); \ - } - static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; @@ -957,25 +991,27 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo MFace *mface = cddm->mface; MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); - int a, b, dodraw, smoothnormal, matnr, new_matnr; + int a, b, dodraw, matnr, new_matnr; int transp, new_transp, orig_transp; int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + cdDM_update_normals_from_pbvh(dm); + matnr = -1; - smoothnormal = 0; dodraw = 0; transp = GPU_get_material_blend_mode(); orig_transp = transp; glShadeModel(GL_SMOOTH); - if( GPU_buffer_legacy(dm) || setDrawOptions != 0 ) { + if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) { DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" ); memset(&attribs, 0, sizeof(attribs)); glBegin(GL_QUADS); for(a = 0; a < dm->numFaceData; a++, mface++) { + const int smoothnormal = (mface->flag & ME_SMOOTH); new_matnr = mface->mat_nr + 1; if(new_matnr != matnr) { @@ -994,8 +1030,12 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo else if(setDrawOptions) { orig = (index)? index[a]: a; - if(orig == ORIGINDEX_NONE) - continue; + if(orig == ORIGINDEX_NONE) { + /* since the material is set by setMaterial(), faces with no + * origin can be assumed to be generated by a modifier */ + + /* continue */ + } else if(!setDrawOptions(userData, orig)) continue; } @@ -1016,8 +1056,6 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo } } - smoothnormal = (mface->flag & ME_SMOOTH); - if(!smoothnormal) { if(nors) { glNormal3fv(nors[a]); @@ -1034,6 +1072,28 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo } } +#define PASSVERT(index, vert) { \ + if(attribs.totorco) \ + glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \ + for(b = 0; b < attribs.tottface; b++) { \ + MTFace *tf = &attribs.tface[b].array[a]; \ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ + } \ + for(b = 0; b < attribs.totmcol; b++) { \ + MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \ + GLubyte col[4]; \ + col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ + glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ + } \ + if(attribs.tottang) { \ + float *tang = attribs.tang.array[a*4 + vert]; \ + glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \ + } \ + if(smoothnormal) \ + glNormal3sv(mvert[index].no); \ + glVertex3fv(mvert[index].co); \ + } + PASSVERT(mface->v1, 0); PASSVERT(mface->v2, 1); PASSVERT(mface->v3, 2); @@ -1042,13 +1102,12 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo else PASSVERT(mface->v3, 2) -#undef PASSVERT } glEnd(); } else { - GPUBuffer *buffer = 0; - char *varray = 0; + GPUBuffer *buffer = NULL; + char *varray = NULL; int numdata = 0, elementsize = 0, offset; int start = 0, numfaces = 0, prevdraw = 0, curface = 0; int i; @@ -1085,9 +1144,9 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo if( numdata != 0 ) { - GPU_buffer_free(buffer,0); + GPU_buffer_free(buffer, NULL); - buffer = 0; + buffer = NULL; } } @@ -1119,22 +1178,22 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo } if(attribs.tottang) { datatypes[numdata].index = attribs.tang.glIndex; - datatypes[numdata].size = 3; + datatypes[numdata].size = 4; datatypes[numdata].type = GL_FLOAT; numdata++; } if( numdata != 0 ) { elementsize = GPU_attrib_element_size( datatypes, numdata ); - buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, 0 ); - if( buffer == 0 ) { + buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, NULL ); + if( buffer == NULL ) { GPU_buffer_unbind(); dm->drawObject->legacy = 1; return; } varray = GPU_buffer_lock_stream(buffer); - if( varray == 0 ) { + if( varray == NULL ) { GPU_buffer_unbind(); - GPU_buffer_free(buffer, 0); + GPU_buffer_free(buffer, NULL); dm->drawObject->legacy = 1; return; } @@ -1209,12 +1268,12 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo } if(attribs.tottang) { float *tang = attribs.tang.array[a*4 + 0]; - VECCOPY((float *)&varray[elementsize*curface*3+offset], tang); + QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang); tang = attribs.tang.array[a*4 + 1]; - VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang); + QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang); tang = attribs.tang.array[a*4 + 2]; - VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang); - offset += sizeof(float)*3; + QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang); + offset += sizeof(float)*4; } } curface++; @@ -1249,12 +1308,12 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo } if(attribs.tottang) { float *tang = attribs.tang.array[a*4 + 2]; - VECCOPY((float *)&varray[elementsize*curface*3+offset], tang); + QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang); tang = attribs.tang.array[a*4 + 3]; - VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang); + QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang); tang = attribs.tang.array[a*4 + 0]; - VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang); - offset += sizeof(float)*3; + QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang); + offset += sizeof(float)*4; } } curface++; @@ -1273,7 +1332,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo } GPU_buffer_unbind(); } - GPU_buffer_free( buffer, 0 ); + GPU_buffer_free( buffer, NULL ); } glShadeModel(GL_FLAT); @@ -1406,6 +1465,11 @@ static void cdDM_recalcTesselation(DerivedMesh *dm) cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); } +void CDDM_recalc_tesselation(DerivedMesh *dm) +{ + cdDM_recalcTesselation(dm); +} + /*ignores original poly origindex layer*/ static void cdDM_recalcTesselation2(DerivedMesh *dm) { @@ -1531,7 +1595,7 @@ DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, in return dm; } -DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob) +DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) { CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm"); DerivedMesh *dm = &cddm->dm; @@ -1570,7 +1634,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob) return dm; } -DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me) +DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) { DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts), BLI_countlist(&em->edges), @@ -1622,7 +1686,6 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me) mv->no[2] = eve->no[2] * 32767.0; mv->bweight = (unsigned char) (eve->bweight * 255.0f); - mv->mat_nr = 0; mv->flag = 0; *index = i; @@ -1673,7 +1736,7 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me) DerivedMesh *CDDM_from_curve(Object *ob) { - return CDDM_from_curve_customDB(ob, &((Curve *)ob->data)->disp); + return CDDM_from_curve_customDB(ob, &ob->disp); } DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase) @@ -1821,7 +1884,6 @@ DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *me) mv->no[1] = eve->no[1] * 32767.0; mv->no[2] = eve->no[2] * 32767.0; - mv->mat_nr = 0; mv->flag = BMFlags_To_MEFlags(eve); if (add_orig) *index = i; @@ -2076,6 +2138,8 @@ DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces) return dm; } +/* note, the CD_ORIGINDEX layers are all 0, so if there is a direct + * relationship betwen mesh data this needs to be set by the caller. */ DerivedMesh *CDDM_from_template(DerivedMesh *source, int numVerts, int numEdges, int numFaces, int numLoops, int numPolys) @@ -2679,6 +2743,11 @@ MFace *CDDM_get_tessfaces(DerivedMesh *dm) return ((CDDerivedMesh*)dm)->mface; } +MPoly *CDDM_get_polys(DerivedMesh *dm) +{ + return ((CDDerivedMesh*)dm)->mpoly; +} + void CDDM_tessfaces_to_faces(DerivedMesh *dm) { /*converts mfaces to mpolys/mloops*/ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 8d4bacb977f..c115f6aa470 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -1,29 +1,29 @@ -/* cloth.c -* -* -* ***** 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) Blender Foundation -* All rights reserved. -* -* Contributor(s): Daniel Genrich -* -* ***** END GPL LICENSE BLOCK ***** -*/ +/* + * $Id$ + * + * ***** 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) Blender Foundation + * All rights reserved. + * + * Contributor(s): Daniel Genrich + * + * ***** END GPL LICENSE BLOCK ***** + */ #include "MEM_guardedalloc.h" @@ -34,6 +34,7 @@ #include "BLI_math.h" #include "BLI_edgehash.h" +#include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" #include "BKE_cloth.h" @@ -41,12 +42,6 @@ #include "BKE_global.h" #include "BKE_modifier.h" #include "BKE_pointcache.h" -#include "BKE_utildefines.h" - -#include "BKE_pointcache.h" - -#include "BLI_kdopbvh.h" -#include "BLI_cellalloc.h" #ifdef _WIN32 void tstart ( void ) @@ -54,7 +49,7 @@ void tstart ( void ) void tend ( void ) { } -double tval() +double tval( void ) { return 0; } @@ -70,7 +65,7 @@ void tend ( void ) { gettimeofday ( &_tend,&tz ); } -double tval() +double tval(void) { double t1, t2; t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 ); @@ -92,7 +87,7 @@ static CM_SOLVER_DEF solvers [] = /* Prototypes for internal functions. */ static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); -static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); +static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first); static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ); @@ -168,7 +163,6 @@ static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float eps BVHTree *bvhtree; Cloth *cloth; ClothVertex *verts; - MFace *mfaces; float co[12]; if(!clmd) @@ -180,7 +174,6 @@ static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float eps return NULL; verts = cloth->verts; - mfaces = cloth->mfaces; // in the moment, return zero if no faces there if(!cloth->numverts) @@ -390,7 +383,8 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul Cloth *cloth; ListBase *effectors = NULL; MVert *mvert; - int i, ret = 0; + unsigned int i = 0; + int ret = 0; /* simulate 1 frame forward */ cloth = clmd->clothObject; @@ -428,13 +422,13 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul /************************************************ * clothModifier_do - main simulation function ************************************************/ -DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) +DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm) { DerivedMesh *result; PointCache *cache; PTCacheID pid; float timescale; - int framedelta, framenr, startframe, endframe; + int framenr, startframe, endframe; int cache_result; clmd->scene= scene; /* nice to pass on later :) */ @@ -451,7 +445,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, return dm; } - if(clmd->sim_parms->reset || (framenr == (startframe - clmd->sim_parms->preroll))) + if(clmd->sim_parms->reset + || (framenr == (startframe - clmd->sim_parms->preroll) && clmd->sim_parms->preroll != 0) + || (clmd->clothObject && result->getNumVerts(result) != clmd->clothObject->numverts)) { clmd->sim_parms->reset = 0; cache->flag |= PTCACHE_OUTDATED; @@ -462,17 +458,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, return result; } - /* verify we still have the same number of vertices, if not do nothing. - * note that this should only happen if the number of vertices changes - * during an animation due to a preceding modifier, this should not - * happen because of object changes! */ - if(clmd->clothObject) { - if(result->getNumVerts(result) != clmd->clothObject->numverts) { - BKE_ptcache_invalidate(cache); - return result; - } - } - // unused in the moment, calculated separately in implicit.c clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame; @@ -481,10 +466,10 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, BKE_ptcache_invalidate(cache); /* do simulation */ - if(!do_init_cloth(ob, clmd, result, framenr)) + if(!do_init_cloth(ob, clmd, dm, framenr)) return result; - do_step_cloth(ob, clmd, result, framenr); + do_step_cloth(ob, clmd, dm, framenr); cloth_to_object(ob, clmd, result); return result; @@ -499,25 +484,20 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, framenr= endframe; } - if(cache->flag & PTCACHE_SIMULATION_VALID) - framedelta= framenr - cache->simframe; - else - framedelta= -1; - /* initialize simulation data if it didn't exist already */ - if(!do_init_cloth(ob, clmd, result, framenr)) + if(!do_init_cloth(ob, clmd, dm, framenr)) return result; if((framenr == startframe) && (clmd->sim_parms->preroll == 0)) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); - do_init_cloth(ob, clmd, result, framenr); + do_init_cloth(ob, clmd, dm, framenr); BKE_ptcache_validate(cache, framenr); cache->flag &= ~PTCACHE_REDO_NEEDED; return result; } /* try to read from cache */ - cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec); + cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { implicit_set_positions(clmd); @@ -526,7 +506,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, BKE_ptcache_validate(cache, framenr); if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) - BKE_ptcache_write_cache(&pid, framenr); + BKE_ptcache_write(&pid, framenr); return result; } @@ -541,18 +521,18 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, /* if on second frame, write cache for first frame */ if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - BKE_ptcache_write_cache(&pid, startframe); + BKE_ptcache_write(&pid, startframe); clmd->sim_parms->timescale *= framenr - cache->simframe; /* do simulation */ BKE_ptcache_validate(cache, framenr); - if(!do_step_cloth(ob, clmd, result, framenr)) { + if(!do_step_cloth(ob, clmd, dm, framenr)) { BKE_ptcache_invalidate(cache); } else - BKE_ptcache_write_cache(&pid, framenr); + BKE_ptcache_write(&pid, framenr); cloth_to_object (ob, clmd, result); @@ -560,7 +540,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, } /* frees all */ -void cloth_free_modifier ( Object *ob, ClothModifierData *clmd ) +void cloth_free_modifier(ClothModifierData *clmd ) { Cloth *cloth = NULL; @@ -818,7 +798,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) } } -static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first) +static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float UNUSED(framenr), int first) { int i = 0; MVert *mvert = NULL; @@ -831,7 +811,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d // If we have a clothObject, free it. if ( clmd->clothObject != NULL ) { - cloth_free_modifier ( ob, clmd ); + cloth_free_modifier ( clmd ); if(G.rt > 0) printf("cloth_free_modifier cloth_from_object\n"); } @@ -855,7 +835,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if ( !dm ) return 0; - cloth_from_mesh ( ob, clmd, dm ); + cloth_from_mesh ( clmd, dm ); // create springs clmd->clothObject->springs = NULL; @@ -911,7 +891,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if ( !cloth_build_springs ( clmd, dm ) ) { - cloth_free_modifier ( ob, clmd ); + cloth_free_modifier ( clmd ); modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); printf("cloth_free_modifier cloth_build_springs\n"); return 0; @@ -945,11 +925,11 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d return 1; } -static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) +static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ) { unsigned int numverts = dm->getNumVerts ( dm ); unsigned int numfaces = dm->getNumTessFaces ( dm ); - MFace *mface = CDDM_get_tessfaces(dm); + MFace *mface = dm->getTessFaceArray( dm ); unsigned int i = 0; /* Allocate our vertices. */ @@ -957,7 +937,7 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh * clmd->clothObject->verts = MEM_callocN ( sizeof ( ClothVertex ) * clmd->clothObject->numverts, "clothVertex" ); if ( clmd->clothObject->verts == NULL ) { - cloth_free_modifier ( ob, clmd ); + cloth_free_modifier ( clmd ); modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." ); printf("cloth_free_modifier clmd->clothObject->verts\n"); return; @@ -968,7 +948,7 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh * clmd->clothObject->mfaces = MEM_callocN ( sizeof ( MFace ) * clmd->clothObject->numfaces, "clothMFaces" ); if ( clmd->clothObject->mfaces == NULL ) { - cloth_free_modifier ( ob, clmd ); + cloth_free_modifier ( clmd ); modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->mfaces." ); printf("cloth_free_modifier clmd->clothObject->mfaces\n"); return; @@ -1020,7 +1000,7 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in return 0; } -static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist) +static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *UNUSED(edgehash), LinkNode **edgelist) { unsigned int i = 0; @@ -1058,12 +1038,12 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) Cloth *cloth = clmd->clothObject; ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0; - int i = 0; - int numverts = dm->getNumVerts ( dm ); - int numedges = dm->getNumEdges ( dm ); - int numfaces = dm->getNumTessFaces ( dm ); - MEdge *medge = CDDM_get_edges ( dm ); - MFace *mface = CDDM_get_tessfaces ( dm ); + unsigned int i = 0; + unsigned int numverts = (unsigned int)dm->getNumVerts ( dm ); + unsigned int numedges = (unsigned int)dm->getNumEdges ( dm ); + unsigned int numfaces = (unsigned int)dm->getNumTessFaces ( dm ); + MEdge *medge = dm->getEdgeArray ( dm ); + MFace *mface = dm->getTessFaceArray ( dm ); int index2 = 0; // our second vertex index LinkNode **edgelist = NULL; EdgeHash *edgehash = NULL; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index af12d23b2c2..623ba26e86d 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1,31 +1,31 @@ -/* collision.c -* -* -* ***** 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) Blender Foundation -* All rights reserved. -* -* The Original Code is: all of this file. -* -* Contributor(s): none yet. -* -* ***** END GPL LICENSE BLOCK ***** -*/ +/* + * $Id$ + * + * ***** 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) Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ #include "MEM_guardedalloc.h" @@ -42,6 +42,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_edgehash.h" +#include "BLI_utildefines.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" @@ -49,7 +50,7 @@ #include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_modifier.h" -#include "BKE_utildefines.h" + #include "BKE_DerivedMesh.h" #ifdef USE_BULLET #include "Bullet-C-Api.h" @@ -79,11 +80,11 @@ void collision_move_object ( CollisionModifierData *collmd, float step, float pr bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 ); } -BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon ) +BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int UNUSED(numverts), float epsilon ) { BVHTree *tree; float co[12]; - int i; + unsigned int i; MFace *tface = mfaces; tree = BLI_bvhtree_new ( numfaces*2, epsilon, 4, 26 ); @@ -106,7 +107,7 @@ BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert return tree; } -void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving ) +void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int UNUSED(numverts), int moving ) { int i; MFace *mfaces = faces; @@ -163,8 +164,8 @@ Collision modifier code end */ #define mySWAP(a,b) do { double tmp = b ; b = a ; a = tmp ; } while(0) - -int +#if 0 /* UNUSED */ +static int gsl_poly_solve_cubic (double a, double b, double c, double *x0, double *x1, double *x2) { @@ -254,7 +255,7 @@ gsl_poly_solve_cubic (double a, double b, double c, * * copied from GSL */ -int +static int gsl_poly_solve_quadratic (double a, double b, double c, double *x0, double *x1) { @@ -312,7 +313,7 @@ gsl_poly_solve_quadratic (double a, double b, double c, return 0; } } - +#endif /* UNUSED */ @@ -481,7 +482,7 @@ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float } -int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; Cloth *cloth1; @@ -597,7 +598,7 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier } //Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned -CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair ) +static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair ) { ClothModifierData *clmd = ( ClothModifierData * ) md1; CollisionModifierData *collmd = ( CollisionModifierData * ) md2; @@ -1307,7 +1308,7 @@ static int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierDa } #endif -static void add_collision_object(Object ***objs, int *numobj, int *maxobj, Object *ob, Object *self, int level) +static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned int *maxobj, Object *ob, Object *self, int level) { CollisionModifierData *cmd= NULL; @@ -1342,12 +1343,12 @@ static void add_collision_object(Object ***objs, int *numobj, int *maxobj, Objec // return all collision objects in scene // collision object will exclude self -Object **get_collisionobjects(Scene *scene, Object *self, Group *group, int *numcollobj) +Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj) { Base *base; Object **objs; GroupObject *go; - int numobj= 0, maxobj= 100; + unsigned int numobj= 0, maxobj= 100; objs= MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray"); @@ -1358,9 +1359,9 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, int *num add_collision_object(&objs, &numobj, &maxobj, go->ob, self, 0); } else { - Scene *sce; /* for SETLOOPER macro */ + Scene *sce_iter; /* add objects in same layer in scene */ - for(SETLOOPER(scene, base)) { + for(SETLOOPER(scene, sce_iter, base)) { if(base->lay & self->lay) add_collision_object(&objs, &numobj, &maxobj, base->object, self, 0); @@ -1417,11 +1418,11 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group) add_collider_cache_object(&objs, go->ob, self, 0); } else { - Scene *sce; /* for SETLOOPER macro */ + Scene *sce_iter; Base *base; /* add objects in same layer in scene */ - for(SETLOOPER(scene, base)) { + for(SETLOOPER(scene, sce_iter, base)) { if(!self || (base->lay & self->lay)) add_collider_cache_object(&objs, base->object, self, 0); @@ -1456,13 +1457,13 @@ static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, Collis static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index) { Cloth *cloth = clmd->clothObject; - int i=0, j = 0, numfaces = 0, numverts = 0; + int i=0, j = 0, /*numfaces = 0,*/ numverts = 0; ClothVertex *verts = NULL; int ret = 0; int result = 0; float tnull[3] = {0,0,0}; - numfaces = clmd->clothObject->numfaces; + /*numfaces = clmd->clothObject->numfaces;*/ /*UNUSED*/ numverts = clmd->clothObject->numverts; verts = cloth->verts; @@ -1503,12 +1504,12 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl { Cloth *cloth= clmd->clothObject; BVHTree *cloth_bvh= cloth->bvhtree; - int i=0, numfaces = 0, numverts = 0, k, l, j; + unsigned int i=0, numfaces = 0, numverts = 0, k, l, j; int rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0, ret2 = 0; Object **collobjs = NULL; - int numcollobj = 0; + unsigned int numcollobj = 0; if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || cloth_bvh==NULL) return 0; @@ -1545,7 +1546,7 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl Object *collob= collobjs[i]; CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision); BVHTreeOverlap *overlap = NULL; - int result = 0; + unsigned int result = 0; if(!collmd->bvhtree) continue; @@ -1605,11 +1606,11 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl //////////////////////////////////////////////////////////// if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { - for(l = 0; l < clmd->coll_parms->self_loop_count; l++) + for(l = 0; l < (unsigned int)clmd->coll_parms->self_loop_count; l++) { // TODO: add coll quality rounds again BVHTreeOverlap *overlap = NULL; - int result = 0; + unsigned int result = 0; // collisions = 1; verts = cloth->verts; // needed for openMP diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 90ffa39c88f..7cf6b21e2f1 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -41,19 +41,20 @@ #include "DNA_color_types.h" #include "DNA_curve_types.h" +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + #include "BKE_colortools.h" #include "BKE_curve.h" -#include "BKE_ipo.h" -#include "BKE_utildefines.h" +#include "BKE_fcurve.h" -#include "BLI_blenlib.h" -#include "BLI_math.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w) +void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w)) { int x, y; float *rf= rectf; @@ -74,7 +75,7 @@ void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, i } } -void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w) +void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w)) { int x, y; float *rf= rectf; @@ -356,7 +357,7 @@ void curvemap_sethandle(CurveMap *cuma, int type) /* *********************** Making the tables and display ************** */ /* reduced copy of garbled calchandleNurb() code in curve.c */ -static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode) +static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *next, int UNUSED(mode)) { float *p1,*p2,*p3,pt[3]; float dx1,dy1, dx,dy, vx,vy, len,len1,len2; @@ -830,6 +831,10 @@ void colorcorrection_do_ibuf(ImBuf *ibuf, const char *profile) cmsCloseProfile(proofingProfile); } } +#else + /* unused */ + (void)ibuf; + (void)profile; #endif } @@ -865,7 +870,7 @@ void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) if(ibuf->channels) stride= ibuf->channels; - for(pixel= ibuf->x*ibuf->y; pixel>0; pixel--, pix_in+=stride, pix_out+=4) { + for(pixel= ibuf->x*ibuf->y; pixel>0; pixel--, pix_in+=stride, pix_out+=stride) { if(stride<3) { col[0]= curvemap_evaluateF(cumap->cm, *pix_in); @@ -952,13 +957,11 @@ void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size) DO_INLINE int get_bin_float(float f) { - int bin= (int)(f*255); + int bin= (int)((f*255) + 0.5); /* 0.5 to prevent quantisation differences */ /* note: clamp integer instead of float to avoid problems with NaN */ CLAMP(bin, 0, 255); - - //return (int) (((f + 0.25) / 1.5) * 255); - + return bin; } @@ -1000,7 +1003,8 @@ DO_INLINE void save_sample_line(Scopes *scopes, const int idx, const float fx, f void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) { - int x, y, c, n, nl; + int x, y, c; + unsigned int n, nl; double div, divl; float *rf=NULL; unsigned char *rc=NULL; @@ -1008,6 +1012,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) int savedlines, saveline; float rgb[3], ycc[3], luma; int ycc_mode=-1; + const short is_float = (ibuf->rect_float != NULL); + + if (ibuf->rect==NULL && ibuf->rect_float==NULL) return; if (scopes->ok == 1 ) return; @@ -1015,6 +1022,7 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) /* hmmmm */ if (!(ELEM(ibuf->channels, 3, 4))) return; + scopes->hist.channels = 3; scopes->hist.x_resolution = 256; @@ -1069,9 +1077,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) scopes->waveform_3= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3"); scopes->vecscope= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "vectorscope point channel"); - if (ibuf->rect_float) + if (is_float) rf = ibuf->rect_float; - else if (ibuf->rect) + else rc = (unsigned char *)ibuf->rect; for (y = 0; y < ibuf->y; y++) { @@ -1080,13 +1088,13 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) } else saveline=0; for (x = 0; x < ibuf->x; x++) { - if (ibuf->rect_float) { + if (is_float) { if (use_color_management) linearrgb_to_srgb_v3_v3(rgb, rf); else copy_v3_v3(rgb, rf); } - else if (ibuf->rect) { + else { for (c=0; c<3; c++) rgb[c] = rc[c] * INV_255; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index fd8bd67e8f4..36d19b53ed2 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -40,6 +40,7 @@ #include "BLI_math.h" #include "BLI_editVert.h" #include "BLI_cellalloc.h" +#include "BLI_utildefines.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -54,7 +55,7 @@ #include "DNA_text_types.h" #include "DNA_windowmanager_types.h" -#include "BKE_utildefines.h" + #include "BKE_action.h" #include "BKE_anim.h" /* for the curve calculation part */ #include "BKE_armature.h" @@ -74,7 +75,7 @@ #include "BKE_mesh.h" #include "BKE_tessmesh.h" -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON #include "BPY_extern.h" #endif @@ -375,7 +376,7 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 else { /* objects */ if (from==CONSTRAINT_SPACE_WORLD && to==CONSTRAINT_SPACE_LOCAL) { - /* check if object has a parent - otherwise this won't work */ + /* check if object has a parent */ if (ob->parent) { /* 'subtract' parent's effects from owner */ mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat); @@ -383,6 +384,18 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 copy_m4_m4(tempmat, mat); mul_m4_m4m4(mat, tempmat, imat); } + else { + /* Local space in this case will have to be defined as local to the owner's + * transform-property-rotated axes. So subtract this rotation component. + */ + object_to_mat4(ob, diff_mat); + normalize_m4(diff_mat); + zero_v3(diff_mat[3]); + + invert_m4_m4(imat, diff_mat); + copy_m4_m4(tempmat, mat); + mul_m4_m4m4(mat, tempmat, imat); + } } else if (from==CONSTRAINT_SPACE_LOCAL && to==CONSTRAINT_SPACE_WORLD) { /* check that object has a parent - otherwise this won't work */ @@ -392,6 +405,17 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat); mul_m4_m4m4(mat, tempmat, diff_mat); } + else { + /* Local space in this case will have to be defined as local to the owner's + * transform-property-rotated axes. So add back this rotation component. + */ + object_to_mat4(ob, diff_mat); + normalize_m4(diff_mat); + zero_v3(diff_mat[3]); + + copy_m4_m4(tempmat, mat); + mul_m4_m4m4(mat, tempmat, diff_mat); + } } } } @@ -399,7 +423,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 (Scene *scene, Object *ob, char *substring, float mat[][4]) +static void contarget_get_mesh_mat (Scene *scene, Object *ob, const char *substring, float mat[][4]) { DerivedMesh *dm = NULL; Mesh *me= ob->data; @@ -502,7 +526,7 @@ static void contarget_get_mesh_mat (Scene *scene, Object *ob, char *substring, f } /* function that sets the given matrix based on given vertex group in lattice */ -static void contarget_get_lattice_mat (Object *ob, char *substring, float mat[][4]) +static void contarget_get_lattice_mat (Object *ob, const char *substring, float mat[][4]) { Lattice *lt= (Lattice *)ob->data; @@ -560,7 +584,7 @@ static void contarget_get_lattice_mat (Object *ob, char *substring, float mat[][ /* 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 (Scene *scene, Object *ob, char *substring, float mat[][4], short from, short to, float headtail) +static void constraint_target_to_mat4 (Scene *scene, Object *ob, const char *substring, float mat[][4], short from, short to, float headtail) { /* Case OBJECT */ if (!strlen(substring)) { @@ -657,7 +681,7 @@ static bConstraintTypeInfo CTI_CONSTRNAME = { /* This function should be used for the get_target_matrix member of all * constraints that are not picky about what happens to their target matrix. */ -static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) +static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { if (VALID_CONS_TARGET(ct)) constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); @@ -676,7 +700,7 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \ \ ct->tar= datatar; \ - strcpy(ct->subtarget, datasubtarget); \ + BLI_strncpy(ct->subtarget, datasubtarget, sizeof(ct->subtarget)); \ ct->space= con->tarspace; \ ct->flag= CONSTRAINT_TAR_TEMP; \ \ @@ -730,7 +754,7 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain bConstraintTarget *ctn = ct->next; \ if (nocopy == 0) { \ datatar= ct->tar; \ - strcpy(datasubtarget, ct->subtarget); \ + BLI_strncpy(datasubtarget, ct->subtarget, sizeof(datasubtarget)); \ con->tarspace= (char)ct->space; \ } \ \ @@ -812,50 +836,75 @@ static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta /* only evaluate if there is a target */ if (VALID_CONS_TARGET(ct)) { - float parmat[4][4], invmat[4][4], tempmat[4][4]; - float loc[3], eul[3], size[3]; - float loco[3], eulo[3], sizo[3]; - - /* get offset (parent-inverse) matrix */ - copy_m4_m4(invmat, data->invmat); - - /* extract components of both matrices */ - copy_v3_v3(loc, ct->matrix[3]); - mat4_to_eulO(eul, ct->rotOrder, ct->matrix); - mat4_to_size(size, ct->matrix); - - copy_v3_v3(loco, invmat[3]); - mat4_to_eulO(eulo, cob->rotOrder, invmat); - mat4_to_size(sizo, invmat); - - /* disable channels not enabled */ - if (!(data->flag & CHILDOF_LOCX)) loc[0]= loco[0]= 0.0f; - if (!(data->flag & CHILDOF_LOCY)) loc[1]= loco[1]= 0.0f; - if (!(data->flag & CHILDOF_LOCZ)) loc[2]= loco[2]= 0.0f; - if (!(data->flag & CHILDOF_ROTX)) eul[0]= eulo[0]= 0.0f; - if (!(data->flag & CHILDOF_ROTY)) eul[1]= eulo[1]= 0.0f; - if (!(data->flag & CHILDOF_ROTZ)) eul[2]= eulo[2]= 0.0f; - if (!(data->flag & CHILDOF_SIZEX)) size[0]= sizo[0]= 1.0f; - if (!(data->flag & CHILDOF_SIZEY)) size[1]= sizo[1]= 1.0f; - if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f; - - /* make new target mat and offset mat */ - loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder); - loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder); - - /* multiply target (parent matrix) by offset (parent inverse) to get - * the effect of the parent that will be exherted on the owner - */ - mul_m4_m4m4(parmat, invmat, ct->matrix); + float parmat[4][4]; - /* now multiply the parent matrix by the owner matrix to get the - * the effect of this constraint (i.e. owner is 'parented' to parent) - */ - copy_m4_m4(tempmat, cob->matrix); - mul_m4_m4m4(cob->matrix, tempmat, parmat); + /* simple matrix parenting */ + if(data->flag == CHILDOF_ALL) { + + /* multiply target (parent matrix) by offset (parent inverse) to get + * the effect of the parent that will be exherted on the owner + */ + mul_m4_m4m4(parmat, data->invmat, ct->matrix); + + /* now multiply the parent matrix by the owner matrix to get the + * the effect of this constraint (i.e. owner is 'parented' to parent) + */ + mul_m4_m4m4(cob->matrix, cob->matrix, parmat); + } + else { + float invmat[4][4], tempmat[4][4]; + float loc[3], eul[3], size[3]; + float loco[3], eulo[3], sizo[3]; + + /* get offset (parent-inverse) matrix */ + copy_m4_m4(invmat, data->invmat); + + /* extract components of both matrices */ + copy_v3_v3(loc, ct->matrix[3]); + mat4_to_eulO(eul, ct->rotOrder, ct->matrix); + mat4_to_size(size, ct->matrix); + + copy_v3_v3(loco, invmat[3]); + mat4_to_eulO(eulo, cob->rotOrder, invmat); + mat4_to_size(sizo, invmat); + + /* disable channels not enabled */ + if (!(data->flag & CHILDOF_LOCX)) loc[0]= loco[0]= 0.0f; + if (!(data->flag & CHILDOF_LOCY)) loc[1]= loco[1]= 0.0f; + if (!(data->flag & CHILDOF_LOCZ)) loc[2]= loco[2]= 0.0f; + if (!(data->flag & CHILDOF_ROTX)) eul[0]= eulo[0]= 0.0f; + if (!(data->flag & CHILDOF_ROTY)) eul[1]= eulo[1]= 0.0f; + if (!(data->flag & CHILDOF_ROTZ)) eul[2]= eulo[2]= 0.0f; + if (!(data->flag & CHILDOF_SIZEX)) size[0]= sizo[0]= 1.0f; + if (!(data->flag & CHILDOF_SIZEY)) size[1]= sizo[1]= 1.0f; + if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f; + + /* make new target mat and offset mat */ + loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder); + loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder); + + /* multiply target (parent matrix) by offset (parent inverse) to get + * the effect of the parent that will be exherted on the owner + */ + mul_m4_m4m4(parmat, invmat, ct->matrix); + + /* now multiply the parent matrix by the owner matrix to get the + * the effect of this constraint (i.e. owner is 'parented' to parent) + */ + copy_m4_m4(tempmat, cob->matrix); + mul_m4_m4m4(cob->matrix, tempmat, parmat); + + /* without this, changes to scale and rotation can change location + * of a parentless bone or a disconnected bone. Even though its set + * to zero above. */ + if (!(data->flag & CHILDOF_LOCX)) cob->matrix[3][0]= tempmat[3][0]; + if (!(data->flag & CHILDOF_LOCY)) cob->matrix[3][1]= tempmat[3][1]; + if (!(data->flag & CHILDOF_LOCZ)) cob->matrix[3][2]= tempmat[3][2]; + } } } +/* XXX note, con->flag should be CONSTRAINT_SPACEONCE for bone-childof, patched in readfile.c */ static bConstraintTypeInfo CTI_CHILDOF = { CONSTRAINT_TYPE_CHILDOF, /* type */ sizeof(bChildOfConstraint), /* size */ @@ -1102,7 +1151,7 @@ static void kinematic_flush_tars (bConstraint *con, ListBase *list, short nocopy } } -static void kinematic_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) +static void kinematic_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { bKinematicConstraint *data= con->data; @@ -1190,19 +1239,18 @@ static void followpath_flush_tars (bConstraint *con, ListBase *list, short nocop } } -static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) +static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { bFollowPathConstraint *data= con->data; if (VALID_CONS_TARGET(ct)) { Curve *cu= ct->tar->data; - float q[4], vec[4], dir[3], quat[4], radius, x1; - float totmat[4][4]; + float vec[4], dir[3], radius; + float totmat[4][4]= MAT4_UNITY; float curvetime; - - unit_m4(totmat); + unit_m4(ct->matrix); - + /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, * currently for paths to work it needs to go through the bevlist/displist system (ton) */ @@ -1212,7 +1260,8 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr makeDispListCurveTypes(cob->scene, ct->tar, 0); if (cu->path && cu->path->data) { - if ((data->followflag & FOLLOWPATH_STATIC) == 0) { + float quat[4]; + if ((data->followflag & FOLLOWPATH_STATIC) == 0) { /* animated position along curve depending on time */ if (cob->scene) curvetime= bsystem_time(cob->scene, ct->tar, cu->ctime, 0.0) - data->offset; @@ -1233,8 +1282,10 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr curvetime= data->offset_fac; } - if ( where_on_path(ct->tar, curvetime, vec, dir, NULL, &radius, NULL) ) { + if ( where_on_path(ct->tar, curvetime, vec, dir, (data->followflag & FOLLOWPATH_FOLLOW) ? quat : NULL, &radius, NULL) ) { /* quat_pt is quat or NULL*/ if (data->followflag & FOLLOWPATH_FOLLOW) { +#if 0 + float x1, q[4]; vec_to_quat(quat, dir, (short)data->trackflag, (short)data->upflag); normalize_v3(dir); @@ -1244,10 +1295,13 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr q[2]= -x1*dir[1]; q[3]= -x1*dir[2]; mul_qt_qtqt(quat, q, quat); - +#else + quat_apply_track(quat, data->trackflag, data->upflag); +#endif + quat_to_mat4(totmat, quat); } - + if (data->followflag & FOLLOWPATH_RADIUS) { float tmat[4][4], rmat[4][4]; scale_m4_fl(tmat, radius); @@ -1319,7 +1373,7 @@ static bConstraintTypeInfo CTI_FOLLOWPATH = { /* --------- Limit Location --------- */ -static void loclimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) +static void loclimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) { bLocLimitConstraint *data = con->data; @@ -1367,7 +1421,7 @@ static bConstraintTypeInfo CTI_LOCLIMIT = { /* -------- Limit Rotation --------- */ -static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) +static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) { bRotLimitConstraint *data = con->data; float loc[3]; @@ -1376,9 +1430,9 @@ static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t copy_v3_v3(loc, cob->matrix[3]); mat4_to_size(size, cob->matrix); - + mat4_to_eulO(eul, cob->rotOrder, cob->matrix); - + /* constraint data uses radians internally */ /* limiting of euler values... */ @@ -1426,7 +1480,7 @@ static bConstraintTypeInfo CTI_ROTLIMIT = { /* --------- Limit Scaling --------- */ -static void sizelimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) +static void sizelimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) { bSizeLimitConstraint *data = con->data; float obsize[3], size[3]; @@ -1631,8 +1685,9 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta mat4_to_size(size, cob->matrix); /* to allow compatible rotations, must get both rotations in the order of the owner... */ - mat4_to_eulO(eul, cob->rotOrder, ct->matrix); mat4_to_eulO(obeul, cob->rotOrder, cob->matrix); + /* we must get compatible eulers from the beginning because some of them can be modified below (see bug #21875) */ + mat4_to_compatible_eulO(eul, obeul, cob->rotOrder, ct->matrix); if ((data->flag & ROTLIKE_X)==0) eul[0] = obeul[0]; @@ -1664,6 +1719,7 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta eul[2] *= -1; } + /* good to make eulers compatible again, since we don't know how much they were changed above */ compatible_eul(eul, obeul); loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder); } @@ -1818,7 +1874,7 @@ static void translike_flush_tars (bConstraint *con, ListBase *list, short nocopy } } -static void translike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) +static void translike_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets) { bConstraintTarget *ct= targets->first; @@ -1854,7 +1910,7 @@ static void samevolume_new_data (void *cdata) data->volume = 1.0f; } -static void samevolume_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) +static void samevolume_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) { bSameVolumeConstraint *data= con->data; @@ -1968,9 +2024,9 @@ static void pycon_id_looper (bConstraint *con, ConstraintIDFunc func, void *user } /* Whether this approach is maintained remains to be seen (aligorith) */ -static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) +static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON bPythonConstraint *data= con->data; #endif @@ -1990,7 +2046,7 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); /* only execute target calculation if allowed */ -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON if (G.f & G_SCRIPT_AUTOEXEC) BPY_pyconstraint_target(data, ct); #endif @@ -2001,7 +2057,8 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) { -#ifdef DISABLE_PYTHON +#ifndef WITH_PYTHON + (void)con; (void)cob; (void)targets; /* unused */ return; #else bPythonConstraint *data= con->data; @@ -2019,8 +2076,8 @@ static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targ #endif /* Now, run the actual 'constraint' function, which should only access the matrices */ - BPY_pyconstraint_eval(data, cob, targets); -#endif /* DISABLE_PYTHON */ + BPY_pyconstraint_exec(data, cob, targets); +#endif /* WITH_PYTHON */ } static bConstraintTypeInfo CTI_PYTHON = { @@ -2092,9 +2149,8 @@ static void actcon_flush_tars (bConstraint *con, ListBase *list, short nocopy) } } -static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) +static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { - extern void chan_calc_mat(bPoseChannel *chan); bActionConstraint *data = con->data; if (VALID_CONS_TARGET(ct)) { @@ -2162,7 +2218,7 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint what_does_obaction(cob->scene, cob->ob, &workob, pose, data->act, pchan->name, t); /* convert animation to matrices for use here */ - chan_calc_mat(tchan); + pchan_calc_mat(tchan); copy_m4_m4(ct->matrix, tchan->chan_mat); /* Clean up */ @@ -2183,7 +2239,7 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint } } -static void actcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) +static void actcon_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets) { bConstraintTarget *ct= targets->first; @@ -2983,6 +3039,7 @@ static void rbj_id_looper (bConstraint *con, ConstraintIDFunc func, void *userda /* target only */ func(con, (ID**)&data->tar, userdata); + func(con, (ID**)&data->child, userdata); } static int rbj_get_tars (bConstraint *con, ListBase *list) @@ -3063,7 +3120,7 @@ static void clampto_flush_tars (bConstraint *con, ListBase *list, short nocopy) } } -static void clampto_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) +static void clampto_get_tarmat (bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { if (VALID_CONS_TARGET(ct)) { Curve *cu= ct->tar->data; @@ -3092,11 +3149,11 @@ static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta /* only evaluate if there is a target and it is a curve */ if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) { Curve *cu= data->tar->data; - float obmat[4][4], targetMatrix[4][4], ownLoc[3]; + float obmat[4][4], ownLoc[3]; float curveMin[3], curveMax[3]; + float targetMatrix[4][4]= MAT4_UNITY; copy_m4_m4(obmat, cob->matrix); - unit_m4(targetMatrix); copy_v3_v3(ownLoc, obmat[3]); INIT_MINMAX(curveMin, curveMax) @@ -3397,7 +3454,7 @@ static void shrinkwrap_flush_tars (bConstraint *con, ListBase *list, short nocop } -static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) +static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data; @@ -3409,12 +3466,11 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr float dist; SpaceTransform transform; - DerivedMesh *target = object_get_derived_final(cob->scene, ct->tar, CD_MASK_BAREMESH); + DerivedMesh *target = object_get_derived_final(ct->tar); BVHTreeRayHit hit; BVHTreeNearest nearest; - BVHTreeFromMesh treeData; - memset(&treeData, 0, sizeof(treeData)); + BVHTreeFromMesh treeData= {NULL}; nearest.index = -1; nearest.dist = FLT_MAX; @@ -3449,7 +3505,9 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData); dist = len_v3v3(co, nearest.co); - interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist)/dist); /* linear interpolation */ + if(dist != 0.0f) { + interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist)/dist); /* linear interpolation */ + } space_transform_invert(&transform, co); break; @@ -3500,7 +3558,7 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr } } -static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) +static void shrinkwrap_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets) { bConstraintTarget *ct= targets->first; @@ -3716,7 +3774,7 @@ static void splineik_flush_tars (bConstraint *con, ListBase *list, short nocopy) } } -static void splineik_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) +static void splineik_get_tarmat (bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { if (VALID_CONS_TARGET(ct)) { Curve *cu= ct->tar->data; @@ -3796,6 +3854,9 @@ static void pivotcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t float pivot[3], vec[3]; float rotMat[3][3]; + + /* pivot correction */ + float axis[3], angle; /* firstly, check if pivoting should take place based on the current rotation */ if (data->rotAxis != PIVOTCON_AXIS_NONE) { @@ -3838,10 +3899,20 @@ static void pivotcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t // TODO: perhaps we might want to include scaling based on the pivot too? copy_m3_m4(rotMat, cob->matrix); normalize_m3(rotMat); - + + + /* correct the pivot by the rotation axis otherwise the pivot translates when it shouldnt */ + mat3_to_axis_angle(axis, &angle, rotMat); + if(angle) { + float dvec[3]; + sub_v3_v3v3(vec, pivot, cob->matrix[3]); + project_v3_v3v3(dvec, vec, axis); + sub_v3_v3(pivot, dvec); + } + /* perform the pivoting... */ /* 1. take the vector from owner to the pivot */ - sub_v3_v3v3(vec, pivot, cob->matrix[3]); + sub_v3_v3v3(vec, cob->matrix[3], pivot); /* 2. rotate this vector by the rotation of the object... */ mul_m3_v3(rotMat, vec); /* 3. make the rotation in terms of the pivot now */ @@ -3875,7 +3946,7 @@ static bConstraintTypeInfo *constraintsTypeInfo[NUM_CONSTRAINT_TYPES]; static short CTI_INIT= 1; /* when non-zero, the list needs to be updated */ /* This function only gets called when CTI_INIT is non-zero */ -static void constraints_init_typeinfo () { +static void constraints_init_typeinfo (void) { constraintsTypeInfo[0]= NULL; /* 'Null' Constraint */ constraintsTypeInfo[1]= &CTI_CHILDOF; /* ChildOf Constraint */ constraintsTypeInfo[2]= &CTI_TRACKTO; /* TrackTo Constraint */ @@ -4078,6 +4149,21 @@ static bConstraint *add_new_constraint (Object *ob, bPoseChannel *pchan, const c constraints_set_active(list, con); } + /* set type+owner specific immutable settings */ + // TODO: does action constraint need anything here - i.e. spaceonce? + switch (type) { + case CONSTRAINT_TYPE_CHILDOF: + { + /* if this constraint is being added to a posechannel, make sure + * the constraint gets evaluated in pose-space */ + if (pchan) { + con->ownspace = CONSTRAINT_SPACE_POSE; + con->flag |= CONSTRAINT_SPACEONCE; + } + } + break; + } + return con; } @@ -4148,7 +4234,7 @@ void id_loop_constraints (ListBase *conlist, ConstraintIDFunc func, void *userda /* ......... */ /* helper for copy_constraints(), to be used for making sure that ID's are valid */ -static void con_extern_cb(bConstraint *con, ID **idpoin, void *userdata) +static void con_extern_cb(bConstraint *UNUSED(con), ID **idpoin, void *UNUSED(userData)) { if (*idpoin && (*idpoin)->lib) id_lib_extern(*idpoin); @@ -4351,8 +4437,7 @@ void get_constraint_target_matrix (struct Scene *scene, bConstraint *con, int n, void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) { bConstraint *con; - float solution[4][4], delta[4][4]; - float oldmat[4][4], imat[4][4]; + float oldmat[4][4]; float enf; /* check that there is a valid constraint object to evaluate */ @@ -4404,7 +4489,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) } } - /* Solve the constraint */ + /* Solve the constraint and put result in cob->matrix */ cti->evaluate_constraint(con, cob, &targets); /* clear targets after use @@ -4416,23 +4501,13 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) } /* Interpolate the enforcement, to blend result of constraint into final owner transform */ - /* 1. Remove effects of original matrix from constraint solution ==> delta */ - invert_m4_m4(imat, oldmat); - copy_m4_m4(solution, cob->matrix); - mul_m4_m4m4(delta, solution, imat); - - /* 2. If constraint influence is not full strength, then interpolate - * identity_matrix --> delta_matrix to get the effect the constraint actually exerts - */ + /* Note: all kind of stuff here before (caused trouble), much easier to just interpolate, or did I miss something? -jahka */ if (enf < 1.0) { - float identity[4][4]; - unit_m4(identity); - blend_m4_m4m4(delta, identity, delta, enf); + float solution[4][4]; + copy_m4_m4(solution, cob->matrix); + blend_m4_m4m4(cob->matrix, oldmat, solution, enf); } - /* 3. Now multiply the delta by the matrix in use before the evaluation */ - mul_m4_m4m4(cob->matrix, delta, oldmat); - /* move owner back into worldspace for next constraint/other business */ if ((con->flag & CONSTRAINT_SPACEONCE) == 0) constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 4b1ea2809bc..6f7188115e0 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -52,8 +52,10 @@ #endif #ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON #include "BPY_extern.h" #endif +#endif /* struct */ @@ -69,6 +71,7 @@ struct bContext { struct ARegion *region; struct ARegion *menu; struct bContextStore *store; + const char *operator_poll_msg; /* reason for poll failing */ } wm; /* data context */ @@ -95,7 +98,7 @@ struct bContext { /* context */ -bContext *CTX_create() +bContext *CTX_create(void) { bContext *C; @@ -174,7 +177,7 @@ void CTX_free(bContext *C) /* store */ -bContextStore *CTX_store_add(ListBase *contexts, char *name, PointerRNA *ptr) +bContextStore *CTX_store_add(ListBase *contexts, const char *name, PointerRNA *ptr) { bContextStoreEntry *entry; bContextStore *ctx, *lastctx; @@ -245,7 +248,7 @@ void CTX_py_init_set(bContext *C, int value) C->data.py_init= value; } -void *CTX_py_dict_get(bContext *C) +void *CTX_py_dict_get(const bContext *C) { return C->data.py_context; } @@ -466,6 +469,16 @@ void CTX_wm_menu_set(bContext *C, ARegion *menu) C->wm.menu= menu; } +void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg) +{ + C->wm.operator_poll_msg= msg; +} + +const char *CTX_wm_operator_poll_msg_get(bContext *C) +{ + return C->wm.operator_poll_msg; +} + /* data context utility functions */ struct bContextDataResult { @@ -481,10 +494,10 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res int ret= 0; memset(result, 0, sizeof(bContextDataResult)); -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON if(CTX_py_dict_get(C)) { - return BPY_context_get(C, member, result); -// if (BPY_context_get(C, member, result)) + return BPY_context_member_get(C, member, result); +// if (BPY_context_member_get(C, member, result)) // return 1; } #endif @@ -610,8 +623,7 @@ ListBase CTX_data_collection_get(const bContext *C, const char *member) return result.list; } else { - ListBase list; - memset(&list, 0, sizeof(list)); + ListBase list= {NULL, NULL}; return list; } } @@ -830,7 +842,7 @@ int CTX_data_mode_enum(const bContext *C) /* would prefer if we can use the enum version below over this one - Campbell */ /* must be aligned with above enum */ -static char *data_mode_strings[] = { +static const char *data_mode_strings[] = { "mesh_edit", "curve_edit", "surface_edit", @@ -845,9 +857,9 @@ static char *data_mode_strings[] = { "texturepaint", "particlemode", "objectmode", - 0 + NULL }; -char *CTX_data_mode_string(const bContext *C) +const char *CTX_data_mode_string(const bContext *C) { return data_mode_strings[CTX_data_mode_enum(C)]; } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 5f5958f8893..67e988249f5 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -35,8 +35,10 @@ #include <stdlib.h> #include "MEM_guardedalloc.h" + #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_utildefines.h" #include "DNA_curve_types.h" #include "DNA_material_types.h" @@ -58,7 +60,7 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_object.h" -#include "BKE_utildefines.h" // VECCOPY + #include "ED_curve.h" @@ -75,12 +77,22 @@ void unlink_curve(Curve *cu) for(a=0; a<cu->totcol; a++) { if(cu->mat[a]) cu->mat[a]->id.us--; - cu->mat[a]= 0; + cu->mat[a]= NULL; } if(cu->vfont) cu->vfont->id.us--; - cu->vfont= 0; + cu->vfont= NULL; + + if(cu->vfontb) cu->vfontb->id.us--; + cu->vfontb= NULL; + + if(cu->vfonti) cu->vfonti->id.us--; + cu->vfonti= NULL; + + if(cu->vfontbi) cu->vfontbi->id.us--; + cu->vfontbi= NULL; + if(cu->key) cu->key->id.us--; - cu->key= 0; + cu->key= NULL; } /* frees editcurve entirely */ @@ -121,7 +133,7 @@ void free_curve(Curve *cu) if(cu->tb) MEM_freeN(cu->tb); } -Curve *add_curve(char *name, int type) +Curve *add_curve(const char *name, int type) { Curve *cu; @@ -130,7 +142,7 @@ Curve *add_curve(char *name, int type) cu->size[0]= cu->size[1]= cu->size[2]= 1.0; cu->flag= CU_FRONT|CU_BACK|CU_DEFORM_BOUNDS_OFF|CU_PATH_RADIUS; cu->pathlen= 100; - cu->resolu= cu->resolv= 12; + cu->resolu= cu->resolv= (type == OB_SURF) ? 4 : 12; cu->width= 1.0; cu->wordspace = 1.0; cu->spacing= cu->linedist= 1.0; @@ -146,7 +158,7 @@ Curve *add_curve(char *name, int type) cu->vfont= cu->vfontb= cu->vfonti= cu->vfontbi= get_builtin_font(); cu->vfont->id.us+=4; cu->str= MEM_mallocN(12, "str"); - strcpy(cu->str, "Text"); + BLI_strncpy(cu->str, "Text", 12); cu->len= cu->pos= 4; cu->strinfo= MEM_callocN(12*sizeof(CharInfo), "strinfo new"); cu->totbox= cu->actbox= 1; @@ -163,7 +175,7 @@ Curve *copy_curve(Curve *cu) int a; cun= copy_libblock(cu); - cun->nurb.first= cun->nurb.last= 0; + cun->nurb.first= cun->nurb.last= NULL; duplicateNurblist( &(cun->nurb), &(cu->nurb)); cun->mat= MEM_dupallocN(cu->mat); @@ -179,9 +191,9 @@ Curve *copy_curve(Curve *cu) cun->key= copy_key(cu->key); if(cun->key) cun->key->from= (ID *)cun; - cun->disp.first= cun->disp.last= 0; - cun->bev.first= cun->bev.last= 0; - cun->path= 0; + cun->disp.first= cun->disp.last= NULL; + cun->bev.first= cun->bev.last= NULL; + cun->path= NULL; cun->editnurb= NULL; cun->editfont= NULL; @@ -201,7 +213,7 @@ Curve *copy_curve(Curve *cu) void make_local_curve(Curve *cu) { - Object *ob = 0; + Object *ob = NULL; Curve *cun; int local=0, lib=0; @@ -210,14 +222,17 @@ void make_local_curve(Curve *cu) * - mixed: do a copy */ - if(cu->id.lib==0) return; - - if(cu->vfont) cu->vfont->id.lib= 0; - + if(cu->id.lib==NULL) return; + + if(cu->vfont) cu->vfont->id.lib= NULL; + if(cu->vfontb) cu->vfontb->id.lib= NULL; + if(cu->vfonti) cu->vfonti->id.lib= NULL; + if(cu->vfontbi) cu->vfontbi->id.lib= NULL; + if(cu->id.us==1) { - cu->id.lib= 0; + cu->id.lib= NULL; cu->id.flag= LIB_LOCAL; - new_id(0, (ID *)cu, 0); + new_id(NULL, (ID *)cu, NULL); return; } @@ -231,9 +246,9 @@ void make_local_curve(Curve *cu) } if(local && lib==0) { - cu->id.lib= 0; + cu->id.lib= NULL; cu->id.flag= LIB_LOCAL; - new_id(0, (ID *)cu, 0); + new_id(NULL, (ID *)cu, NULL); } else if(local && lib) { cun= copy_curve(cu); @@ -243,7 +258,7 @@ void make_local_curve(Curve *cu) while(ob) { if(ob->data==cu) { - if(ob->id.lib==0) { + if(ob->id.lib==NULL) { ob->data= cun; cun->id.us++; cu->id.us--; @@ -367,12 +382,12 @@ int count_curveverts_without_handles(ListBase *nurb) void freeNurb(Nurb *nu) { - if(nu==0) return; + if(nu==NULL) return; if(nu->bezt) MEM_freeN(nu->bezt); - nu->bezt= 0; + nu->bezt= NULL; if(nu->bp) MEM_freeN(nu->bp); - nu->bp= 0; + nu->bp= NULL; if(nu->knotsu) MEM_freeN(nu->knotsu); nu->knotsu= NULL; if(nu->knotsv) MEM_freeN(nu->knotsv); @@ -388,7 +403,7 @@ void freeNurblist(ListBase *lb) { Nurb *nu, *next; - if(lb==0) return; + if(lb==NULL) return; nu= lb->first; while(nu) { @@ -396,7 +411,7 @@ void freeNurblist(ListBase *lb) freeNurb(nu); nu= next; } - lb->first= lb->last= 0; + lb->first= lb->last= NULL; } Nurb *duplicateNurb(Nurb *nu) @@ -405,7 +420,7 @@ Nurb *duplicateNurb(Nurb *nu) int len; newnu= (Nurb*)MEM_mallocN(sizeof(Nurb),"duplicateNurb"); - if(newnu==0) return 0; + if(newnu==NULL) return NULL; memcpy(newnu, nu, sizeof(Nurb)); if(nu->bezt) { @@ -601,7 +616,7 @@ static void makecyclicknots(float *knots, short pnts, short order) { int a, b, order2, c; - if(knots==0) return; + if(knots==NULL) return; order2=order-1; @@ -624,7 +639,7 @@ static void makecyclicknots(float *knots, short pnts, short order) -void makeknots(Nurb *nu, short uv) +static void makeknots(Nurb *nu, short uv) { if(nu->type == CU_NURBS) { if(uv == 1) { @@ -656,6 +671,16 @@ void makeknots(Nurb *nu, short uv) } } +void nurbs_knot_calc_u(Nurb *nu) +{ + makeknots(nu, 1); +} + +void nurbs_knot_calc_v(Nurb *nu) +{ + makeknots(nu, 2); +} + static void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end) { float d, e; @@ -719,16 +744,16 @@ static void basisNurb(float t, short order, short pnts, float *knots, float *bas } -void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride) +void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv) /* coord_array has to be 3*4*resolu*resolv in size, and zero-ed */ { BPoint *bp; float *basisu, *basis, *basisv, *sum, *fp, *in; float u, v, ustart, uend, ustep, vstart, vend, vstep, sumdiv; - int i, j, iofs, jofs, cycl, len, resolu, resolv; + int i, j, iofs, jofs, cycl, len, curu, curv; int istart, iend, jsta, jen, *jstart, *jend, ratcomp; - int totu = nu->pntsu*nu->resolu, totv = nu->pntsv*nu->resolv; + int totu = nu->pntsu*resolu, totv = nu->pntsv*resolv; if(nu->knotsu==NULL || nu->knotsv==NULL) return; if(nu->orderu>nu->pntsu) return; @@ -785,9 +810,9 @@ void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride) else cycl= 0; v= vstart; basis= basisv; - resolv= totv; - while(resolv--) { - basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+resolv, jend+resolv); + curv= totv; + while(curv--) { + basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+curv, jend+curv); basis+= KNOTSV(nu); v+= vstep; } @@ -796,17 +821,17 @@ void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride) else cycl= 0; in= coord_array; u= ustart; - resolu= totu; - while(resolu--) { + curu= totu; + while(curu--) { basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend); basis= basisv; - resolv= totv; - while(resolv--) { + curv= totv; + while(curv--) { - jsta= jstart[resolv]; - jen= jend[resolv]; + jsta= jstart[curv]; + jen= jend[curv]; /* calculate sum */ sumdiv= 0.0; @@ -894,7 +919,7 @@ void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radiu if(nu->knotsu==NULL) return; if(nu->orderu>nu->pntsu) return; - if(coord_array==0) return; + if(coord_array==NULL) return; /* allocate and initialize */ len= nu->pntsu; @@ -1034,10 +1059,13 @@ static void forward_diff_bezier_cotangent(float *p0, float *p1, float *p2, float float *make_orco_surf(Object *ob) { + /* Note: this function is used in convertblender only atm, so + * suppose nonzero curve's render resolution should always be used */ Curve *cu= ob->data; Nurb *nu; int a, b, tot=0; int sizeu, sizev; + int resolu, resolv; float *fp, *coord_array; /* first calculate the size of the datablock */ @@ -1051,9 +1079,12 @@ float *make_orco_surf(Object *ob) See also convertblender.c: init_render_surf() */ + + resolu= cu->resolu_ren ? cu->resolu_ren : nu->resolu; + resolv= cu->resolv_ren ? cu->resolv_ren : nu->resolv; - sizeu = nu->pntsu*nu->resolu; - sizev = nu->pntsv*nu->resolv; + sizeu = nu->pntsu*resolu; + sizev = nu->pntsv*resolv; if (nu->flagu & CU_NURB_CYCLIC) sizeu++; if (nu->flagv & CU_NURB_CYCLIC) sizev++; if(nu->pntsv>1) tot+= sizeu * sizev; @@ -1065,9 +1096,12 @@ float *make_orco_surf(Object *ob) nu= cu->nurb.first; while(nu) { + resolu= cu->resolu_ren ? cu->resolu_ren : nu->resolu; + resolv= cu->resolv_ren ? cu->resolv_ren : nu->resolv; + if(nu->pntsv>1) { - sizeu = nu->pntsu*nu->resolu; - sizev = nu->pntsv*nu->resolv; + sizeu = nu->pntsu*resolu; + sizev = nu->pntsv*resolv; if (nu->flagu & CU_NURB_CYCLIC) sizeu++; if (nu->flagv & CU_NURB_CYCLIC) sizev++; @@ -1088,10 +1122,10 @@ float *make_orco_surf(Object *ob) } } else { - float *_tdata= MEM_callocN((nu->pntsu*nu->resolu) * (nu->pntsv*nu->resolv) *3*sizeof(float), "temp data"); + float *_tdata= MEM_callocN((nu->pntsu*resolu) * (nu->pntsv*resolv) *3*sizeof(float), "temp data"); float *tdata= _tdata; - makeNurbfaces(nu, tdata, 0); + makeNurbfaces(nu, tdata, 0, resolu, resolv); for(b=0; b<sizeu; b++) { int use_b= b; @@ -1103,7 +1137,7 @@ float *make_orco_surf(Object *ob) if (a==sizev-1 && (nu->flagv & CU_NURB_CYCLIC)) use_a= 0; - tdata = _tdata + 3 * (use_b * (nu->pntsv*nu->resolv) + use_a); + tdata = _tdata + 3 * (use_b * (nu->pntsv*resolv) + use_a); fp[0]= (tdata[0]-cu->loc[0])/cu->size[0]; fp[1]= (tdata[1]-cu->loc[1])/cu->size[1]; @@ -1181,8 +1215,8 @@ float *make_orco_curve(Scene *scene, Object *ob) for (u=0; u<sizev; u++) { for (v=0; v<sizeu; v++,fp+=3) { if (cu->flag & CU_UV_ORCO) { - fp[0]= 2.0f*u/(dl->parts-1) - 1.0f; - fp[1]= 2.0f*v/(dl->nr-1) - 1.0f; + fp[0]= 2.0f*u/(sizev - 1) - 1.0f; + fp[1]= 2.0f*v/(sizeu - 1) - 1.0f; fp[2]= 0.0; } else { float *vert; @@ -1235,10 +1269,10 @@ void makebevelcurve(Scene *scene, Object *ob, ListBase *disp, int forRender) makeDispListCurveTypes_forRender(scene, cu->bevobj, &bevdisp, NULL, 0); dl= bevdisp.first; } else { - dl= bevcu->disp.first; - if(dl==0) { + dl= cu->bevobj->disp.first; + if(dl==NULL) { makeDispListCurveTypes(scene, cu->bevobj, 0); - dl= bevcu->disp.first; + dl= cu->bevobj->disp.first; } } @@ -1713,7 +1747,7 @@ static void bevel_list_smooth(BevList *bl, int smooth_iter) if(bl->poly== -1) { /* check its not cyclic */ /* skip the first point */ - bevp0= bevp1; + /* bevp0= bevp1; */ bevp1= bevp2; bevp2++; nr--; @@ -1744,7 +1778,7 @@ static void bevel_list_smooth(BevList *bl, int smooth_iter) normalize_qt(bevp1->quat); - bevp0= bevp1; + /* bevp0= bevp1; */ /* UNUSED */ bevp1= bevp2; bevp2++; } @@ -1778,8 +1812,6 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl) int nr; float q[4]; - float cross_tmp[3]; - bevel_list_calc_bisect(bl); bevp2= (BevPoint *)(bl+1); @@ -1796,6 +1828,7 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl) float angle= angle_normalized_v3v3(bevp0->dir, bevp1->dir); if(angle > 0.0f) { /* otherwise we can keep as is */ + float cross_tmp[3]; cross_v3_v3v3(cross_tmp, bevp0->dir, bevp1->dir); axis_angle_to_quat(q, cross_tmp, angle); mul_qt_qtqt(bevp1->quat, q, bevp0->quat); @@ -1923,7 +1956,7 @@ static void make_bevel_list_3D_tangent(BevList *bl) normalize_v3(cross_tmp); tri_to_quat( bevp1->quat,zero, cross_tmp, bevp1->tan); /* XXX - could be faster */ - bevp0= bevp1; + /* bevp0= bevp1; */ /* UNUSED */ bevp1= bevp2; bevp2++; } @@ -2393,7 +2426,7 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode) p2= bezt->vec[1]; - if(prev==0) { + if(prev==NULL) { p3= next->vec[1]; pt[0]= 2*p2[0]- p3[0]; pt[1]= 2*p2[1]- p3[1]; @@ -2402,7 +2435,7 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode) } else p1= prev->vec[1]; - if(next==0) { + if(next==NULL) { pt[0]= 2*p2[0]- p1[0]; pt[1]= 2*p2[1]- p1[1]; pt[2]= 2*p2[2]- p1[2]; @@ -2583,7 +2616,7 @@ void calchandlesNurb(Nurb *nu) /* first, if needed, set handle flags */ a= nu->pntsu; bezt= nu->bezt; if(nu->flagu & CU_NURB_CYCLIC) prev= bezt+(a-1); - else prev= 0; + else prev= NULL; next= bezt+1; while(a--) { @@ -2591,7 +2624,7 @@ void calchandlesNurb(Nurb *nu) /* first, if needed, set handle flags */ prev= bezt; if(a==1) { if(nu->flagu & CU_NURB_CYCLIC) next= nu->bezt; - else next= 0; + else next= NULL; } else next++; @@ -2650,7 +2683,7 @@ void autocalchandlesNurb(Nurb *nu, int flag) BezTriple *bezt2, *bezt1, *bezt0; int i, align, leftsmall, rightsmall; - if(nu==0 || nu->bezt==0) return; + if(nu==NULL || nu->bezt==NULL) return; bezt2 = nu->bezt; bezt1 = bezt2 + (nu->pntsu-1); @@ -2875,38 +2908,41 @@ void switchdirectionNurb(Nurb *nu) bp2--; } if(nu->type == CU_NURBS) { - /* inverse knots */ - a= KNOTSU(nu); - fp1= nu->knotsu; - fp2= fp1+(a-1); - a/= 2; - while(fp1!=fp2 && a>0) { - SWAP(float, *fp1, *fp2); - a--; - fp1++; - fp2--; - } - /* and make in increasing order again */ - a= KNOTSU(nu); - fp1= nu->knotsu; - fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect"); - while(a--) { - fp2[0]= fabs(fp1[1]-fp1[0]); - fp1++; - fp2++; - } - - a= KNOTSU(nu)-1; - fp1= nu->knotsu; - fp2= tempf; - fp1[0]= 0.0; - fp1++; - while(a--) { - fp1[0]= fp1[-1]+fp2[0]; + /* no knots for too short paths */ + if(nu->knotsu) { + /* inverse knots */ + a= KNOTSU(nu); + fp1= nu->knotsu; + fp2= fp1+(a-1); + a/= 2; + while(fp1!=fp2 && a>0) { + SWAP(float, *fp1, *fp2); + a--; + fp1++; + fp2--; + } + /* and make in increasing order again */ + a= KNOTSU(nu); + fp1= nu->knotsu; + fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect"); + while(a--) { + fp2[0]= fabs(fp1[1]-fp1[0]); + fp1++; + fp2++; + } + + a= KNOTSU(nu)-1; + fp1= nu->knotsu; + fp2= tempf; + fp1[0]= 0.0; fp1++; - fp2++; + while(a--) { + fp1[0]= fp1[-1]+fp2[0]; + fp1++; + fp2++; + } + MEM_freeN(tempf); } - MEM_freeN(tempf); } } else { @@ -2929,7 +2965,7 @@ void switchdirectionNurb(Nurb *nu) } -float (*curve_getVertexCos(Curve *cu, ListBase *lb, int *numVerts_r))[3] +float (*curve_getVertexCos(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r))[3] { int i, numVerts = *numVerts_r = count_curveverts(lb); float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "cu_vcos"); @@ -2957,7 +2993,7 @@ float (*curve_getVertexCos(Curve *cu, ListBase *lb, int *numVerts_r))[3] return cos; } -void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3]) +void curve_applyVertexCos(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos)[3]) { float *co = vertexCos[0]; Nurb *nu; @@ -2982,7 +3018,7 @@ void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3]) } } -float (*curve_getKeyVertexCos(Curve *cu, ListBase *lb, float *key))[3] +float (*curve_getKeyVertexCos(Curve *UNUSED(cu), ListBase *lb, float *key))[3] { int i, numVerts = count_curveverts(lb); float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "cu_vcos"); @@ -3013,7 +3049,7 @@ float (*curve_getKeyVertexCos(Curve *cu, ListBase *lb, float *key))[3] return cos; } -void curve_applyKeyVertexTilts(Curve *cu, ListBase *lb, float *key) +void curve_applyKeyVertexTilts(Curve *UNUSED(cu), ListBase *lb, float *key) { Nurb *nu; int i; @@ -3025,7 +3061,7 @@ void curve_applyKeyVertexTilts(Curve *cu, ListBase *lb, float *key) for(i=0; i<nu->pntsu; i++,bezt++) { key+=3*3; bezt->alfa= *key; - key++; + key+=3; } } else { diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index b067001cb98..0612a57d85d 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -34,7 +34,8 @@ #include <math.h> #include <string.h> -#include "BLI_cellalloc.h" + +#include <assert.h> #include "MEM_guardedalloc.h" @@ -42,13 +43,19 @@ #include "DNA_ID.h" #include "BLI_blenlib.h" +#include "BLI_path_util.h" #include "BLI_linklist.h" +#include "BLI_math.h" #include "BLI_mempool.h" +#include "BLI_cellalloc.h" +#include "BLI_utildefines.h" #include "BKE_customdata.h" #include "BKE_customdata_file.h" #include "BKE_global.h" +#include "BKE_main.h" #include "BKE_utildefines.h" +#include "BKE_multires.h" #include "bmesh.h" @@ -61,9 +68,9 @@ /********************* Layer type information **********************/ typedef struct LayerTypeInfo { int size; /* the memory size of one element of this layer's data */ - char *structname; /* name of the struct used, for file writing */ + const char *structname; /* name of the struct used, for file writing */ int structnum; /* number of structs per element, for file writing */ - char *defaultname; /* default layer name */ + const char *defaultname; /* default layer name */ /* a function to copy count elements of this layer's data * (deep copy if appropriate) @@ -113,6 +120,11 @@ typedef struct LayerTypeInfo { /* a function to determine file size */ size_t (*filesize)(CDataFile *cdf, void *data, int count); + + /* a function to validate layer contents depending on + * sub-elements count + */ + void (*validate)(void *source, int sub_elements); } LayerTypeInfo; static void layerCopy_mdeformvert(const void *source, void *dest, @@ -158,7 +170,7 @@ static void linklist_free_simple(void *link) } static void layerInterp_mdeformvert(void **sources, float *weights, - float *sub_weights, int count, void *dest) + float *UNUSED(sub_weights), int count, void *dest) { MDeformVert *dvert = dest; LinkNode *dest_dw = NULL; /* a list of lists of MDeformWeight pointers */ @@ -216,7 +228,7 @@ static void layerInterp_mdeformvert(void **sources, float *weights, static void layerInterp_msticky(void **sources, float *weights, - float *sub_weights, int count, void *dest) + float *UNUSED(sub_weights), int count, void *dest) { float co[2], w; MSticky *mst; @@ -406,130 +418,149 @@ static void layerDefault_origspace_face(void *data, int count) osf[i] = default_osf; } -#if 0 -/* Adapted from sculptmode.c */ -static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v) -{ - int x, y, x2, y2; - const int st_max = st - 1; - float urat, vrat, uopp; - float d[4][3], d2[2][3]; - - if(u < 0) - u = 0; - else if(u >= st) - u = st_max; - if(v < 0) - v = 0; - else if(v >= st) - v = st_max; - - x = floor(u); - y = floor(v); - x2 = x + 1; - y2 = y + 1; - - if(x2 >= st) x2 = st_max; - if(y2 >= st) y2 = st_max; - - urat = u - x; - vrat = v - y; - uopp = 1 - urat; - - copy_v3_v3(d[0], disps[y * st + x]); - copy_v3_v3(d[1], disps[y * st + x2]); - copy_v3_v3(d[2], disps[y2 * st + x]); - copy_v3_v3(d[3], disps[y2 * st + x2]); - mul_v3_fl(d[0], uopp); - mul_v3_fl(d[1], urat); - mul_v3_fl(d[2], uopp); - mul_v3_fl(d[3], urat); - - add_v3_v3v3(d2[0], d[0], d[1]); - add_v3_v3v3(d2[1], d[2], d[3]); - mul_v3_fl(d2[0], 1 - vrat); - mul_v3_fl(d2[1], vrat); - - add_v3_v3v3(out, d2[0], d2[1]); -} -#endif - -static int mdisp_corners(MDisps *s) -{ - /* silly trick because we don't get it from callback */ - return (s->totdisp % (3*3) == 0)? 3: 4; -} - static void layerSwap_mdisps(void *data, const int *ci) { MDisps *s = data; float (*d)[3] = NULL; int corners, cornersize, S; - /* this function is untested .. */ - corners = mdisp_corners(s); - cornersize = s->totdisp/corners; + if(s->disps) { + int nverts= (ci[1] == 3) ? 4 : 3; /* silly way to know vertex count of face */ + corners= multires_mdisp_corners(s); + cornersize= s->totdisp/corners; - d = MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap"); + if(corners!=nverts) { + /* happens when face changed vertex count in edit mode + if it happened, just forgot displacement */ - for(S = 0; S < corners; S++) - memcpy(d + cornersize*S, s->disps + cornersize*ci[S], cornersize*3*sizeof(float)); - - if(s->disps) + MEM_freeN(s->disps); + s->totdisp= (s->totdisp/corners)*nverts; + s->disps= MEM_callocN(s->totdisp*sizeof(float)*3, "mdisp swap"); + return; + } + + d= MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap"); + + for(S = 0; S < corners; S++) + memcpy(d + cornersize*S, s->disps + cornersize*ci[S], cornersize*3*sizeof(float)); + MEM_freeN(s->disps); - s->disps = d; + s->disps= d; + } } -static void layerInterp_mdisps(void **sources, float *weights, float *sub_weights, - int count, void *dest) +static void layerInterp_mdisps(void **sources, float *UNUSED(weights), + float *sub_weights, int count, void *dest) { - // XXX -#if 0 MDisps *d = dest; MDisps *s = NULL; int st, stl; int i, x, y; - float crn[4][2]; - float (*sw)[4] = NULL; + int side, S, dst_corners, src_corners; + float crn_weight[4][2]; + float (*sw)[4] = (void*)sub_weights; + float (*disps)[3], (*out)[3]; - /* Initialize the destination */ - for(i = 0; i < d->totdisp; ++i) { - float z[3] = {0,0,0}; - copy_v3_v3(d->disps[i], z); + /* happens when flipping normals of newly created mesh */ + if(!d->totdisp) + return; + + s = sources[0]; + dst_corners = multires_mdisp_corners(d); + src_corners = multires_mdisp_corners(s); + + if(sub_weights && count == 2 && src_corners == 3) { + src_corners = multires_mdisp_corners(sources[1]); + + /* special case -- converting two triangles to quad */ + if(src_corners == 3 && dst_corners == 4) { + MDisps tris[2]; + int vindex[4] = {0}; + + S = 0; + for(i = 0; i < 2; i++) + for(y = 0; y < 4; y++) + for(x = 0; x < 4; x++) + if(sw[x+i*4][y]) + vindex[x] = y; + + for(i = 0; i < 2; i++) { + float sw_m4[4][4] = {{0}}; + int a = 7 & ~(1 << vindex[i*2] | 1 << vindex[i*2+1]); + + sw_m4[0][vindex[i*2+1]] = 1; + sw_m4[1][vindex[i*2]] = 1; + + for(x = 0; x < 3; x++) + if(a & (1 << x)) + sw_m4[2][x] = 1; + + tris[i] = *((MDisps*)sources[i]); + tris[i].disps = MEM_dupallocN(tris[i].disps); + layerInterp_mdisps(&sources[i], NULL, (float*)sw_m4, 1, &tris[i]); + } + + mdisp_join_tris(d, &tris[0], &tris[1]); + + for(i = 0; i < 2; i++) + MEM_freeN(tris[i].disps); + + return; + } } /* For now, some restrictions on the input */ - if(count != 1 || !sub_weights) return; + if(count != 1 || !sub_weights) { + for(i = 0; i < d->totdisp; ++i) + zero_v3(d->disps[i]); - st = sqrt(d->totdisp); + return; + } + + /* Initialize the destination */ + out = disps = MEM_callocN(3*d->totdisp*sizeof(float), "iterp disps"); + + side = sqrt(d->totdisp / dst_corners); + st = (side<<1)-1; stl = st - 1; - sw = (void*)sub_weights; + sw= (void*)sub_weights; for(i = 0; i < 4; ++i) { - crn[i][0] = 0 * sw[i][0] + stl * sw[i][1] + stl * sw[i][2] + 0 * sw[i][3]; - crn[i][1] = 0 * sw[i][0] + 0 * sw[i][1] + stl * sw[i][2] + stl * sw[i][3]; + crn_weight[i][0] = 0 * sw[i][0] + stl * sw[i][1] + stl * sw[i][2] + 0 * sw[i][3]; + crn_weight[i][1] = 0 * sw[i][0] + 0 * sw[i][1] + stl * sw[i][2] + stl * sw[i][3]; } - s = sources[0]; - for(y = 0; y < st; ++y) { - for(x = 0; x < st; ++x) { - /* One suspects this code could be cleaner. */ - float xl = (float)x / (st - 1); - float yl = (float)y / (st - 1); - float mid1[2] = {crn[0][0] * (1 - xl) + crn[1][0] * xl, - crn[0][1] * (1 - xl) + crn[1][1] * xl}; - float mid2[2] = {crn[3][0] * (1 - xl) + crn[2][0] * xl, - crn[3][1] * (1 - xl) + crn[2][1] * xl}; - float mid3[2] = {mid1[0] * (1 - yl) + mid2[0] * yl, - mid1[1] * (1 - yl) + mid2[1] * yl}; - - float srcdisp[3]; - - mdisps_bilinear(srcdisp, s->disps, st, mid3[0], mid3[1]); - copy_v3_v3(d->disps[y * st + x], srcdisp); + multires_mdisp_smooth_bounds(s); + + out = disps; + for(S = 0; S < dst_corners; S++) { + float base[2], axis_x[2], axis_y[2]; + + mdisp_apply_weight(S, dst_corners, 0, 0, st, crn_weight, &base[0], &base[1]); + mdisp_apply_weight(S, dst_corners, side-1, 0, st, crn_weight, &axis_x[0], &axis_x[1]); + mdisp_apply_weight(S, dst_corners, 0, side-1, st, crn_weight, &axis_y[0], &axis_y[1]); + + sub_v2_v2(axis_x, base); + sub_v2_v2(axis_y, base); + normalize_v2(axis_x); + normalize_v2(axis_y); + + for(y = 0; y < side; ++y) { + for(x = 0; x < side; ++x, ++out) { + int crn; + float face_u, face_v, crn_u, crn_v; + + mdisp_apply_weight(S, dst_corners, x, y, st, crn_weight, &face_u, &face_v); + crn = mdisp_rot_face_to_crn(src_corners, st, face_u, face_v, &crn_u, &crn_v); + + old_mdisps_bilinear((*out), &s->disps[crn*side*side], side, crn_u, crn_v); + mdisp_flip_disp(crn, dst_corners, axis_x, axis_y, *out); + } } } -#endif + + MEM_freeN(d->disps); + d->disps = disps; } static void layerCopy_mdisps(const void *source, void *dest, int count) @@ -551,7 +582,21 @@ static void layerCopy_mdisps(const void *source, void *dest, int count) } } -static void layerFree_mdisps(void *data, int count, int size) +static void layerValidate_mdisps(void *data, int sub_elements) +{ + MDisps *disps = data; + if(disps->disps) { + int corners = multires_mdisp_corners(disps); + + if(corners != sub_elements) { + MEM_freeN(disps->disps); + disps->totdisp = disps->totdisp / corners * sub_elements; + disps->disps = MEM_callocN(3*disps->totdisp*sizeof(float), "layerValidate_mdisps"); + } + } +} + +static void layerFree_mdisps(void *data, int count, int UNUSED(size)) { int i; MDisps *d = data; @@ -597,7 +642,7 @@ static int layerWrite_mdisps(CDataFile *cdf, void *data, int count) return 1; } -static size_t layerFilesize_mdisps(CDataFile *cdf, void *data, int count) +static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count) { MDisps *d = data; size_t size = 0; @@ -936,7 +981,7 @@ static void layerInterp_shapekey(void **sources, float *weights, } } -const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { +static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, NULL, NULL}, @@ -966,11 +1011,11 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, - {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps}, + layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps, layerValidate_mdisps}, {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, {sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL}, @@ -989,7 +1034,7 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, }; -const char *LAYERTYPENAMES[CD_NUMTYPES] = { +static const char *LAYERTYPENAMES[CD_NUMTYPES] = { "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", @@ -1064,13 +1109,13 @@ void customData_update_typemap(CustomData *data) void CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem) { - const LayerTypeInfo *typeInfo; + /*const LayerTypeInfo *typeInfo;*/ CustomDataLayer *layer, *newlayer; int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0; for(i = 0; i < source->totlayer; ++i) { layer = &source->layers[i]; - typeInfo = layerType_getInfo(layer->type); + /*typeInfo = layerType_getInfo(layer->type);*/ /*UNUSED*/ type = layer->type; @@ -1195,7 +1240,7 @@ int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n) return -1; } -int CustomData_get_named_layer_index(const CustomData *data, int type, char *name) +int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name) { int i; @@ -1444,7 +1489,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, data->layers[index].data = newlayerdata; if(name || (name=typeInfo->defaultname)) { - strcpy(data->layers[index].name, name); + BLI_strncpy(data->layers[index].name, name, 32); CustomData_set_layer_unique_name(data, index); } else @@ -1586,7 +1631,7 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type) } void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, - int type, char *name) + int type, const char *name) { CustomDataLayer *layer; int layer_index; @@ -1841,7 +1886,7 @@ void *CustomData_get_layer_n(const CustomData *data, int type, int n) } void *CustomData_get_layer_named(const struct CustomData *data, int type, - char *name) + const char *name) { int layer_index = CustomData_get_named_layer_index(data, type, name); if(layer_index < 0) return NULL; @@ -1967,6 +2012,18 @@ void CustomData_em_copy_data(const CustomData *source, CustomData *dest, } } +void CustomData_em_validate_data(CustomData *data, void *block, int sub_elements) +{ + int i; + for(i = 0; i < data->totlayer; i++) { + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type); + char *leayer_data = (char*)block + data->layers[i].offset; + + if(typeInfo->validate) + typeInfo->validate(leayer_data, sub_elements); + } +} + void *CustomData_em_get(const CustomData *data, void *block, int type) { int layer_index; @@ -2593,7 +2650,7 @@ void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest, } -void CustomData_file_write_info(int type, char **structname, int *structnum) +void CustomData_file_write_info(int type, const char **structname, int *structnum) { const LayerTypeInfo *typeInfo = layerType_getInfo(type); @@ -2620,69 +2677,50 @@ static int CustomData_is_property_layer(int type) return 0; } -void CustomData_set_layer_unique_name(CustomData *data, int index) +static int cd_layer_find_dupe(CustomData *data, const char *name, int type, int index) { - char tempname[64]; - int number, i, type; - char *dot, *name; - CustomDataLayer *layer, *nlayer= &data->layers[index]; - const LayerTypeInfo *typeInfo= layerType_getInfo(nlayer->type); - - if (!typeInfo->defaultname) - return; - - type = nlayer->type; - name = nlayer->name; - - if (name[0] == '\0') - BLI_strncpy(nlayer->name, typeInfo->defaultname, sizeof(nlayer->name)); - + int i; /* see if there is a duplicate */ for(i=0; i<data->totlayer; i++) { - layer = &data->layers[i]; - - if(CustomData_is_property_layer(type)){ - if(i!=index && CustomData_is_property_layer(layer->type) && - strcmp(layer->name, name)==0) - break; - - } - else{ - if(i!=index && layer->type==type && strcmp(layer->name, name)==0) - break; - } - } - - if(i == data->totlayer) - return; - - /* strip off the suffix */ - dot = strchr(nlayer->name, '.'); - if(dot) *dot=0; - - for(number=1; number <=999; number++) { - sprintf(tempname, "%s.%03d", nlayer->name, number); - - for(i=0; i<data->totlayer; i++) { - layer = &data->layers[i]; + if(i != index) { + CustomDataLayer *layer= &data->layers[i]; - if(CustomData_is_property_layer(type)){ - if(i!=index && CustomData_is_property_layer(layer->type) && - strcmp(layer->name, tempname)==0) - - break; + if(CustomData_is_property_layer(type)) { + if(CustomData_is_property_layer(layer->type) && strcmp(layer->name, name)==0) { + return 1; + } } else{ - if(i!=index && layer->type==type && strcmp(layer->name, tempname)==0) - break; + if(i!=index && layer->type==type && strcmp(layer->name, name)==0) { + return 1; + } } } + } + + return 0; +} - if(i == data->totlayer) { - BLI_strncpy(nlayer->name, tempname, sizeof(nlayer->name)); - return; - } - } +static int customdata_unique_check(void *arg, const char *name) +{ + struct {CustomData *data; int type; int index;} *data_arg= arg; + return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index); +} + +void CustomData_set_layer_unique_name(CustomData *data, int index) +{ + CustomDataLayer *nlayer= &data->layers[index]; + const LayerTypeInfo *typeInfo= layerType_getInfo(nlayer->type); + + struct {CustomData *data; int type; int index;} data_arg; + data_arg.data= data; + data_arg.type= nlayer->type; + data_arg.index= index; + + if (!typeInfo->defaultname) + return; + + BLI_uniquename_cb(customdata_unique_check, &data_arg, typeInfo->defaultname, '.', nlayer->name, sizeof(nlayer->name)); } int CustomData_verify_versions(struct CustomData *data, int index) @@ -2715,13 +2753,13 @@ int CustomData_verify_versions(struct CustomData *data, int index) static void customdata_external_filename(char filename[FILE_MAX], ID *id, CustomDataExternal *external) { - char *path = (id->lib)? id->lib->filepath: G.sce; + char *path = (id->lib)? id->lib->filepath: G.main->name; BLI_strncpy(filename, external->filename, FILE_MAX); BLI_path_abs(filename, path); } -void CustomData_external_reload(CustomData *data, ID *id, CustomDataMask mask, int totelem) +void CustomData_external_reload(CustomData *data, ID *UNUSED(id), CustomDataMask mask, int totelem) { CustomDataLayer *layer; const LayerTypeInfo *typeInfo; @@ -2891,7 +2929,7 @@ void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, in cdf_free(cdf); } -void CustomData_external_add(CustomData *data, ID *id, int type, int totelem, const char *filename) +void CustomData_external_add(CustomData *data, ID *UNUSED(id), int type, int UNUSED(totelem), const char *filename) { CustomDataExternal *external= data->external; CustomDataLayer *layer; diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c index 65a0d731beb..6fb79a0df28 100644 --- a/source/blender/blenkernel/intern/customdata_file.c +++ b/source/blender/blenkernel/intern/customdata_file.c @@ -28,10 +28,11 @@ #include "BLI_fileops.h" #include "BLI_string.h" +#include "BLI_utildefines.h" #include "BKE_customdata_file.h" #include "BKE_global.h" -#include "BKE_utildefines.h" + /************************* File Format Definitions ***************************/ @@ -379,7 +380,7 @@ int cdf_write_open(CDataFile *cdf, char *filename) return 1; } -int cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay) +int cdf_write_layer(CDataFile *UNUSED(cdf), CDataFileLayer *UNUSED(blay)) { return 1; } diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index be28553f347..616bcb17f90 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -51,7 +51,7 @@ void defgroup_copy_list (ListBase *outbase, ListBase *inbase) { bDeformGroup *defgroup, *defgroupn; - outbase->first= outbase->last= 0; + outbase->first= outbase->last= NULL; for (defgroup = inbase->first; defgroup; defgroup=defgroup->next){ defgroupn= defgroup_duplicate(defgroup); @@ -305,89 +305,65 @@ int defgroup_flip_index(Object *ob, int index, int use_default) return (flip_index==-1 && use_default) ? index : flip_index; } -void defgroup_unique_name (bDeformGroup *dg, Object *ob) +static int defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob) { bDeformGroup *curdef; - int number; - int exists = 0; - char tempname[64]; - char *dot; - if (!ob) - return; - - /* See if we are given an empty string */ - if (dg->name[0] == '\0') { - /* give it default name first */ - strcpy (dg->name, "Group"); - } - - /* See if we even need to do this */ for (curdef = ob->defbase.first; curdef; curdef=curdef->next) { if (dg!=curdef) { - if (!strcmp(curdef->name, dg->name)) { - exists = 1; - break; + if (!strcmp(curdef->name, name)) { + return 1; } } } - - if (!exists) - return; - /* Strip off the suffix */ - dot=strchr(dg->name, '.'); - if (dot) - *dot=0; - - for (number = 1; number <=999; number++) { - sprintf (tempname, "%s.%03d", dg->name, number); - - exists = 0; - for (curdef=ob->defbase.first; curdef; curdef=curdef->next) { - if (dg!=curdef) { - if (!strcmp (curdef->name, tempname)) { - exists = 1; - break; - } - } - } - if (!exists) { - BLI_strncpy (dg->name, tempname, 32); - return; - } - } + return 0; } +static int defgroup_unique_check(void *arg, const char *name) +{ + struct {Object *ob; void *dg;} *data= arg; + return defgroup_find_name_dupe(name, data->dg, data->ob); +} + +void defgroup_unique_name (bDeformGroup *dg, Object *ob) +{ + struct {Object *ob; void *dg;} data; + data.ob= ob; + data.dg= dg; + + BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name)); +} /* finds the best possible flipped name. For renaming; check for unique names afterwards */ -/* if strip_number: removes number extensions */ -void flip_side_name (char *name, const char *from_name, int strip_number) +/* if strip_number: removes number extensions + * note: dont use sizeof() for 'name' or 'from_name' */ +void flip_side_name (char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number) { int len; - char prefix[sizeof(((bDeformGroup *)NULL)->name)]= {""}; /* The part before the facing */ - char suffix[sizeof(((bDeformGroup *)NULL)->name)]= {""}; /* The part after the facing */ - char replace[sizeof(((bDeformGroup *)NULL)->name)]= {""}; /* The replacement string */ - char number[sizeof(((bDeformGroup *)NULL)->name)]= {""}; /* The number extension string */ + char prefix[MAX_VGROUP_NAME]= ""; /* The part before the facing */ + char suffix[MAX_VGROUP_NAME]= ""; /* The part after the facing */ + char replace[MAX_VGROUP_NAME]= ""; /* The replacement string */ + char number[MAX_VGROUP_NAME]= ""; /* The number extension string */ char *index=NULL; - len= strlen(from_name); + len= BLI_strnlen(from_name, MAX_VGROUP_NAME); if(len<3) return; // we don't do names like .R or .L - strcpy(name, from_name); + BLI_strncpy(name, from_name, MAX_VGROUP_NAME); /* We first check the case with a .### extension, let's find the last period */ if(isdigit(name[len-1])) { index= strrchr(name, '.'); // last occurrence if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever! if(strip_number==0) - strcpy(number, index); + BLI_strncpy(number, index, sizeof(number)); *index= 0; - len= strlen(name); + len= BLI_strnlen(name, MAX_VGROUP_NAME); } } - strcpy (prefix, name); + BLI_strncpy(prefix, name, sizeof(prefix)); #define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_') @@ -471,10 +447,10 @@ void flip_side_name (char *name, const char *from_name, int strip_number) #undef IS_SEPARATOR - sprintf (name, "%s%s%s%s", prefix, replace, suffix, number); + BLI_snprintf (name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number); } -float defvert_find_weight(const struct MDeformVert *dvert, int group_num) +float defvert_find_weight(const struct MDeformVert *dvert, const int group_num) { MDeformWeight *dw= defvert_find_index(dvert, group_num); return dw ? dw->weight : 0.0f; @@ -489,7 +465,7 @@ float defvert_array_find_weight_safe(const struct MDeformVert *dvert, int index, } -MDeformWeight *defvert_find_index(const MDeformVert *dvert, int defgroup) +MDeformWeight *defvert_find_index(const MDeformVert *dvert, const int defgroup) { if(dvert && defgroup >= 0) { MDeformWeight *dw = dvert->dw; @@ -505,7 +481,7 @@ MDeformWeight *defvert_find_index(const MDeformVert *dvert, int defgroup) /* Ensures that mv has a deform weight entry for the specified defweight group */ /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */ -MDeformWeight *defvert_verify_index(MDeformVert *dv, int defgroup) +MDeformWeight *defvert_verify_index(MDeformVert *dv, const int defgroup) { MDeformWeight *newdw; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 382c0690ae3..c437c4fe61f 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -29,22 +29,24 @@ #include <string.h> #include <math.h> +#include "MEM_guardedalloc.h" + #include "BLI_winstuff.h" +#include "BLI_utildefines.h" +#include "BLI_ghash.h" #include "DNA_anim_types.h" #include "DNA_camera_types.h" #include "DNA_group_types.h" #include "DNA_lattice_types.h" #include "DNA_key_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" +#include "DNA_node_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" -#include "MEM_guardedalloc.h" - -#include "BLI_ghash.h" - #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_effect.h" @@ -52,7 +54,9 @@ #include "BKE_global.h" #include "BKE_group.h" #include "BKE_key.h" +#include "BKE_library.h" #include "BKE_main.h" +#include "BKE_node.h" #include "BKE_mball.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -60,6 +64,7 @@ #include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_utildefines.h" #include "depsgraph_private.h" @@ -273,7 +278,7 @@ int queue_count(struct DagNodeQueue *queue){ } -DagForest * dag_init() +DagForest *dag_init(void) { DagForest *forest; /* use callocN to init all zero */ @@ -846,7 +851,7 @@ DagNode * dag_get_sub_node (DagForest *forest,void * fob) return node; } -static void dag_add_parent_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name) +static void dag_add_parent_relation(DagForest *UNUSED(forest), DagNode *fob1, DagNode *fob2, short rel, const char *name) { DagAdjList *itA = fob2->parent; @@ -868,7 +873,7 @@ static void dag_add_parent_relation(DagForest *forest, DagNode *fob1, DagNode *f fob2->parent = itA; } -void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name) +void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name) { DagAdjList *itA = fob1->child; @@ -893,7 +898,7 @@ void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel fob1->child = itA; } -static char *dag_node_name(DagNode *node) +static const char *dag_node_name(DagNode *node) { if(node->ob == NULL) return "null"; @@ -938,7 +943,7 @@ static int dag_node_print_dependency_recurs(DagNode *node, DagNode *endnode) return 0; } -static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, DagNode *endnode, char *name) +static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, DagNode *endnode, const char *name) { DagNode *node; @@ -1075,7 +1080,7 @@ void graph_bfs(void) minheight = pos[node->BFS_dist]; itA = node->child; while(itA != NULL) { - if((itA->node->color == DAG_WHITE) ) { + if(itA->node->color == DAG_WHITE) { itA->node->color = DAG_GRAY; itA->node->BFS_dist = node->BFS_dist + 1; itA->node->k = (float) minheight; @@ -1222,7 +1227,7 @@ DagNodeQueue * graph_dfs(void) itA = node->child; while(itA != NULL) { - if((itA->node->color == DAG_WHITE) ) { + if(itA->node->color == DAG_WHITE) { itA->node->DFS_dvtm = time; itA->node->color = DAG_GRAY; @@ -1476,7 +1481,7 @@ struct DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob) itA = node->child; while(itA != NULL) { - if((itA->node->color == DAG_WHITE) ) { + if(itA->node->color == DAG_WHITE) { itA->node->DFS_dvtm = time; itA->node->color = DAG_GRAY; @@ -1510,7 +1515,7 @@ short are_obs_related(struct DagForest *dag, void *ob1, void *ob2) { itA = node->child; while(itA != NULL) { - if((itA->node->ob == ob2) ) { + if(itA->node->ob == ob2) { return itA->node->type; } itA = itA->next; @@ -1682,7 +1687,7 @@ void DAG_scene_sort(Main *bmain, Scene *sce) itA = node->child; while(itA != NULL) { - if((itA->node->color == DAG_WHITE) ) { + if(itA->node->color == DAG_WHITE) { itA->node->DFS_dvtm = time; itA->node->color = DAG_GRAY; @@ -1858,7 +1863,7 @@ static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int for(itA = node->child; itA; itA= itA->next) { if(itA->node->type==ID_OB) { if(itA->node->lasttime!=curtime) { - ob= (Object*)(node->ob); + ob= (Object*)(itA->node->ob); if(reset || (ob->recalc & OB_RECALC_ALL)) { if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) @@ -1921,8 +1926,30 @@ static void dag_scene_flush_layers(Scene *sce, int lay) flush_layer_node(sce, itA->node, lasttime); } +static void dag_tag_renderlayers(Scene *sce, unsigned int lay) +{ + if(sce->nodetree) { + bNode *node; + Base *base; + unsigned int lay_changed= 0; + + for(base= sce->base.first; base; base= base->next) + if(base->lay & lay) + if(base->object->recalc) + lay_changed |= base->lay; + + for(node= sce->nodetree->nodes.first; node; node= node->next) { + if(node->id==(ID *)sce) { + SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1); + if(srl && (srl->lay & lay_changed)) + NodeTagChanged(sce->nodetree, node); + } + } + } +} + /* flushes all recalc flags in objects down the dependency tree */ -void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, int time) +void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const short time) { DagNode *firstnode; DagAdjList *itA; @@ -1965,6 +1992,8 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, int time) } } } + + dag_tag_renderlayers(sce, lay); } static int object_modifiers_use_time(Object *ob) @@ -2131,50 +2160,57 @@ static void dag_object_time_update_flags(Object *ob) } } /* flag all objects that need recalc, for changes in time for example */ -void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay) +/* do_time: make this optional because undo resets objects to their animated locations without this */ +void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const short do_time) { Base *base; Object *ob; Group *group; GroupObject *go; - Scene *sce; - + Scene *sce_iter; + /* set ob flags where animated systems are */ - for(SETLOOPER(scene, base)) { + for(SETLOOPER(scene, sce_iter, base)) { ob= base->object; - - /* now if DagNode were part of base, the node->lay could be checked... */ - /* we do all now, since the scene_flush checks layers and clears recalc flags even */ - dag_object_time_update_flags(ob); - + + if(do_time) { + /* now if DagNode were part of base, the node->lay could be checked... */ + /* we do all now, since the scene_flush checks layers and clears recalc flags even */ + dag_object_time_update_flags(ob); + } + /* handled in next loop */ - if(ob->dup_group) + if(ob->dup_group) ob->dup_group->id.flag |= LIB_DOIT; - } - - /* we do groups each once */ - for(group= bmain->group.first; group; group= group->id.next) { - if(group->id.flag & LIB_DOIT) { - for(go= group->gobject.first; go; go= go->next) { - dag_object_time_update_flags(go->ob); + } + + if(do_time) { + /* we do groups each once */ + for(group= bmain->group.first; group; group= group->id.next) { + if(group->id.flag & LIB_DOIT) { + for(go= group->gobject.first; go; go= go->next) { + dag_object_time_update_flags(go->ob); + } } } } + + for(sce_iter= scene; sce_iter; sce_iter= sce_iter->set) + DAG_scene_flush_update(bmain, sce_iter, lay, 1); - for(sce= scene; sce; sce= sce->set) - DAG_scene_flush_update(bmain, sce, lay, 1); - - /* test: set time flag, to disable baked systems to update */ - for(SETLOOPER(scene, base)) { - ob= base->object; - if(ob->recalc) - ob->recalc |= OB_RECALC_TIME; + if(do_time) { + /* test: set time flag, to disable baked systems to update */ + for(SETLOOPER(scene, sce_iter, base)) { + ob= base->object; + if(ob->recalc) + ob->recalc |= OB_RECALC_TIME; + } + + /* hrmf... an exception to look at once, for invisible camera object we do it over */ + if(scene->camera) + dag_object_time_update_flags(scene->camera); } - - /* hrmf... an exception to look at once, for invisible camera object we do it over */ - if(scene->camera) - dag_object_time_update_flags(scene->camera); - + /* and store the info in groupobject */ for(group= bmain->group.first; group; group= group->id.next) { if(group->id.flag & LIB_DOIT) { @@ -2230,9 +2266,9 @@ void DAG_ids_flush_update(Main *bmain, int time) DAG_scene_flush_update(bmain, sce, lay, time); } -void DAG_on_load_update(Main *bmain) +void DAG_on_load_update(Main *bmain, const short do_time) { - Scene *scene, *sce; + Scene *scene; Base *base; Object *ob; Group *group; @@ -2243,19 +2279,20 @@ void DAG_on_load_update(Main *bmain) dag_current_scene_layers(bmain, &scene, &lay); if(scene && scene->theDag) { + Scene *sce_iter; /* 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 require updates, so we skip those */ dag_scene_flush_layers(scene, lay); - for(SETLOOPER(scene, base)) { + for(SETLOOPER(scene, sce_iter, base)) { ob= base->object; - node= (sce->theDag)? dag_get_node(sce->theDag, ob): NULL; + node= (sce_iter->theDag)? dag_get_node(sce_iter->theDag, ob): NULL; oblay= (node)? node->lay: ob->lay; if(oblay & lay) { - if(ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) + if(ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) ob->recalc |= OB_RECALC_DATA; if(ob->dup_group) ob->dup_group->id.flag |= LIB_DOIT; @@ -2265,7 +2302,7 @@ void DAG_on_load_update(Main *bmain) for(group= bmain->group.first; group; group= group->id.next) { if(group->id.flag & LIB_DOIT) { for(go= group->gobject.first; go; go= go->next) { - if(ELEM5(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) + if(ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) go->ob->recalc |= OB_RECALC_DATA; if(go->ob->proxy_from) go->ob->recalc |= OB_RECALC_OB; @@ -2276,11 +2313,11 @@ void DAG_on_load_update(Main *bmain) } /* now tag update flags, to ensure deformers get calculated on redraw */ - DAG_scene_update_flags(bmain, scene, lay); + DAG_scene_update_flags(bmain, scene, lay, do_time); } } -static void dag_id_flush_update__isDependentTexture(void *userData, Object *ob, ID **idpoin) +static void dag_id_flush_update__isDependentTexture(void *userData, Object *UNUSED(ob), ID **idpoin) { struct { ID *id; int is_dependent; } *data = userData; @@ -2290,26 +2327,21 @@ static void dag_id_flush_update__isDependentTexture(void *userData, Object *ob, } } -void DAG_id_flush_update(ID *id, short flag) +static void dag_id_flush_update(Scene *sce, ID *id) { Main *bmain= G.main; - Scene *sce; Object *obt, *ob= NULL; short idtype; - unsigned int lay; - dag_current_scene_layers(bmain, &sce, &lay); - - if(!id || !sce || !sce->theDag) - return; + /* here we flush a few things before actual scene wide flush, mostly + due to only objects and not other datablocks being in the depsgraph */ /* set flags & pointcache for object */ if(GS(id->name) == ID_OB) { ob= (Object*)id; - ob->recalc |= (flag & OB_RECALC_ALL); BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH); - if(flag & OB_RECALC_DATA) { + if(ob->recalc & OB_RECALC_DATA) { /* all users of this ob->data should be checked */ id= ob->data; @@ -2326,23 +2358,10 @@ void DAG_id_flush_update(ID *id, short flag) idtype= GS(id->name); if(ELEM7(idtype, ID_ME, ID_CU, ID_MB, ID_LA, ID_LT, ID_CA, ID_AR)) { - int first_ob= 1; for(obt=bmain->object.first; obt; obt= obt->id.next) { if(!(ob && obt == ob) && obt->data == id) { - - /* try to avoid displist recalculation for linked curves */ - if (!first_ob && ELEM(obt->type, OB_CURVE, OB_SURF)) { - /* if curve object has got derivedFinal it means this - object has got constructive modifiers and object - should be recalculated anyhow */ - if (!obt->derivedFinal) - continue; - } - obt->recalc |= OB_RECALC_DATA; BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); - - first_ob= 0; } } } @@ -2350,11 +2369,36 @@ void DAG_id_flush_update(ID *id, short flag) /* set flags based on textures - can influence depgraph via modifiers */ if(idtype == ID_TE) { for(obt=bmain->object.first; obt; obt= obt->id.next) { - struct { ID *id; int is_dependent; } data = {id, 0}; - + struct { ID *id; int is_dependent; } data; + data.id= id; + data.is_dependent= 0; + modifiers_foreachIDLink(obt, dag_id_flush_update__isDependentTexture, &data); if (data.is_dependent) obt->recalc |= OB_RECALC_DATA; + + /* particle settings can use the texture as well */ + if(obt->particlesystem.first) { + ParticleSystem *psys = obt->particlesystem.first; + MTex **mtexp, *mtex; + int a; + for(; psys; psys=psys->next) { + mtexp = psys->part->mtex; + for(a=0; a<MAX_MTEX; a++, mtexp++) { + mtex = *mtexp; + if(mtex && mtex->tex == (Tex*)id) { + obt->recalc |= OB_RECALC_DATA; + + if(mtex->mapto & PAMAP_INIT) + psys->recalc |= PSYS_RECALC_RESET; + if(mtex->mapto & PAMAP_CHILD) + psys->recalc |= PSYS_RECALC_CHILD; + + BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); + } + } + } + } } } @@ -2372,25 +2416,100 @@ void DAG_id_flush_update(ID *id, short flag) /* set flags based on particle settings */ if(idtype == ID_PA) { ParticleSystem *psys; - for(obt=bmain->object.first; obt; obt= obt->id.next) { - for(psys=obt->particlesystem.first; psys; psys=psys->next) { - if(&psys->part->id == id) { + for(obt=bmain->object.first; obt; obt= obt->id.next) + for(psys=obt->particlesystem.first; psys; psys=psys->next) + if(&psys->part->id == id) BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); - obt->recalc |= (flag & OB_RECALC_ALL); - psys->recalc |= (flag & PSYS_RECALC); - } - } - } } /* update editors */ dag_editors_update(bmain, id); } +} + +void DAG_ids_flush_tagged(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + Scene *sce; + unsigned int lay; + int a, have_tag = 0; + + dag_current_scene_layers(bmain, &sce, &lay); + + if(!sce || !sce->theDag) + return; + + /* loop over all ID types */ + a = set_listbasepointers(bmain, lbarray); + + while(a--) { + ListBase *lb = lbarray[a]; + ID *id = lb->first; + + /* we tag based on first ID type character to avoid + looping over all ID's in case there are no tags */ + if(id && bmain->id_tag_update[id->name[0]]) { + for(; id; id=id->next) { + if(id->flag & LIB_ID_RECALC) { + dag_id_flush_update(sce, id); + id->flag &= ~LIB_ID_RECALC; + } + } + + have_tag = 1; + } + } + + if(have_tag) { + /* clear tags */ + memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update)); + + /* flush changes to other objects */ + DAG_scene_flush_update(bmain, sce, lay, 0); + } +} - /* flush to other objects that depend on this one */ - DAG_scene_flush_update(bmain, sce, lay, 0); +void DAG_id_tag_update(ID *id, short flag) +{ + Main *bmain= G.main; + + if(id==NULL) return; + + /* tag ID for update */ + id->flag |= LIB_ID_RECALC; + bmain->id_tag_update[id->name[0]] = 1; + + /* flag is for objects and particle systems */ + if(flag) { + Object *ob; + ParticleSystem *psys; + short idtype = GS(id->name); + + if(idtype == ID_OB) { + /* only quick tag */ + ob = (Object*)id; + ob->recalc |= (flag & OB_RECALC_ALL); + } + else if(idtype == ID_PA) { + /* this is weak still, should be done delayed as well */ + for(ob=bmain->object.first; ob; ob=ob->id.next) { + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + if(&psys->part->id == id) { + ob->recalc |= (flag & OB_RECALC_ALL); + psys->recalc |= (flag & PSYS_RECALC); + } + } + } + } + else { + /* disable because this is called on various ID types automatically. + * where printing warning is not useful. for now just ignore */ + /* BLI_assert(!"invalid flag for this 'idtype'"); */ + } + } } +#if 0 // UNUSED /* recursively descends tree, each node only checked once */ /* node is checked to be of type object */ static int parent_check_node(DagNode *node, int curtime) @@ -2420,68 +2539,7 @@ static int parent_check_node(DagNode *node, int curtime) return DAG_WHITE; } - -/* all nodes that influence this object get tagged, for calculating the exact - position of this object at a given timeframe */ -void DAG_id_update_flags(ID *id) -{ - Main *bmain= G.main; - Scene *sce; - DagNode *node; - DagAdjList *itA; - Object *ob; - unsigned int lay; - - dag_current_scene_layers(bmain, &sce, &lay); - - if(!id || !sce || !sce->theDag) - return; - - /* objects only currently */ - if(GS(id->name) != ID_OB) - return; - - ob= (Object*)id; - - /* tag nodes unchecked */ - for(node = sce->theDag->DagNode.first; node; node= node->next) - node->color = DAG_WHITE; - - node= dag_find_node(sce->theDag, ob); - - /* object not in scene? then handle group exception. needs to be dagged once too */ - if(node==NULL) { - Group *group= NULL; - while( (group = find_group(ob, group)) ) { - GroupObject *go; - /* primitive; tag all... this call helps building groups for particles */ - for(go= group->gobject.first; go; go= go->next) - go->ob->recalc= OB_RECALC_ALL; - } - } - else { - - node->color = DAG_GRAY; - - sce->theDag->time++; - node= sce->theDag->DagNode.first; - for(itA = node->child; itA; itA= itA->next) { - if(itA->node->type==ID_OB && itA->node->lasttime!=sce->theDag->time) - itA->node->color= parent_check_node(itA->node, sce->theDag->time); - } - - /* set recalcs and flushes */ - DAG_scene_update_flags(bmain, sce, lay); - - /* now we clear recalcs, unless color is set */ - for(node = sce->theDag->DagNode.first; node; node= node->next) { - if(node->type==ID_OB && node->color==DAG_WHITE) { - Object *ob= node->ob; - ob->recalc= 0; - } - } - } -} +#endif /* ******************* DAG FOR ARMATURE POSE ***************** */ @@ -2588,7 +2646,7 @@ void DAG_pose_sort(Object *ob) itA = node->child; while(itA != NULL) { - if((itA->node->color == DAG_WHITE) ) { + if(itA->node->color == DAG_WHITE) { itA->node->color = DAG_GRAY; push_stack(nqueue,itA->node); skip = 1; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 666a62d96de..59e5aa7ade6 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -35,7 +35,6 @@ #include "MEM_guardedalloc.h" - #include "DNA_curve_types.h" #include "DNA_meshdata_types.h" #include "DNA_scene_types.h" @@ -45,6 +44,8 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_editVert.h" +#include "BLI_scanfill.h" +#include "BLI_utildefines.h" #include "BKE_global.h" #include "BKE_displist.h" @@ -120,7 +121,7 @@ DispList *find_displist(ListBase *lb, int type) dl= dl->next; } - return 0; + return NULL; } int displist_has_faces(ListBase *lb) @@ -137,7 +138,7 @@ void copy_displist(ListBase *lbn, ListBase *lb) { DispList *dln, *dl; - lbn->first= lbn->last= 0; + freedisplist(lbn); dl= lb->first; while(dl) { @@ -149,7 +150,10 @@ void copy_displist(ListBase *lbn, ListBase *lb) dln->index= MEM_dupallocN(dl->index); dln->col1= MEM_dupallocN(dl->col1); dln->col2= MEM_dupallocN(dl->col2); - + + if(dl->bevelSplitFlag) + dln->bevelSplitFlag= MEM_dupallocN(dl->bevelSplitFlag); + dl= dl->next; } } @@ -289,7 +293,7 @@ static void init_fastshade_shadeinput(Render *re) shi.combinedflag= -1; } -static Render *fastshade_get_render(Scene *scene) +static Render *fastshade_get_render(Scene *UNUSED(scene)) { // XXX 2.5: this crashes combined with previewrender // due to global R so disabled for now @@ -621,7 +625,6 @@ void shadeDispList(Scene *scene, Base *base) Object *ob= base->object; DispList *dl, *dlob; Material *ma = NULL; - Curve *cu; Render *re; float imat[3][3], mat[4][4], vec[3]; float *fp, *nor, n1[3]; @@ -655,8 +658,7 @@ void shadeDispList(Scene *scene, Base *base) if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { /* now we need the normals */ - cu= ob->data; - dl= cu->disp.first; + dl= ob->disp.first; while(dl) { extern Material defmaterial; /* material.c */ @@ -788,7 +790,7 @@ void reshadeall_displist(Scene *scene) /* ****************** make displists ********************* */ -static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) +static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, int forRender) { Nurb *nu; DispList *dl; @@ -801,7 +803,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) while(nu) { if(nu->hide==0) { - if(G.rendering && cu->resolu_ren!=0) + if(forRender && cu->resolu_ren!=0) resolu= cu->resolu_ren; else resolu= nu->resolu; @@ -928,55 +930,58 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal) { EditVert *eve, *v1, *vlast; EditFace *efa; - DispList *dlnew=0, *dl; + DispList *dlnew=NULL, *dl; float *f1; - int colnr=0, charidx=0, cont=1, tot, a, *index; + int colnr=0, charidx=0, cont=1, tot, a, *index, nextcol= 0; intptr_t totvert; - if(dispbase==0) return; - if(dispbase->first==0) return; + if(dispbase==NULL) return; + if(dispbase->first==NULL) return; while(cont) { cont= 0; - totvert=0; + totvert= 0; + nextcol= 0; dl= dispbase->first; while(dl) { if(dl->type==DL_POLY) { if(charidx<dl->charidx) cont= 1; - else if(charidx==dl->charidx) { - - colnr= dl->col; - charidx= dl->charidx; - - /* make editverts and edges */ - f1= dl->verts; - a= dl->nr; - eve= v1= 0; - - while(a--) { - vlast= eve; - - eve= BLI_addfillvert(f1); - totvert++; + else if(charidx==dl->charidx) { /* character with needed index */ + if(colnr==dl->col) { + /* make editverts and edges */ + f1= dl->verts; + a= dl->nr; + eve= v1= NULL; - if(vlast==0) v1= eve; - else { - BLI_addfilledge(vlast, eve); + while(a--) { + vlast= eve; + + eve= BLI_addfillvert(f1); + totvert++; + + if(vlast==NULL) v1= eve; + else { + BLI_addfilledge(vlast, eve); + } + f1+=3; } - f1+=3; - } - - if(eve!=0 && v1!=0) { - BLI_addfilledge(eve, v1); + + if(eve!=NULL && v1!=NULL) { + BLI_addfilledge(eve, v1); + } + } else if (colnr<dl->col) { + /* got poly with next material at current char */ + cont= 1; + nextcol= 1; } } } dl= dl->next; } - if(totvert && BLI_edgefill(0, 0)) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { + if(totvert && BLI_edgefill(0)) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { /* count faces */ tot= 0; @@ -1032,7 +1037,14 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal) } BLI_end_edgefill(); - charidx++; + if(nextcol) { + /* stay at current char but fill polys with next material */ + colnr++; + } else { + /* switch to next char and start filling from first material */ + charidx++; + colnr= 0; + } } /* do not free polys, needed for wireframe display */ @@ -1046,7 +1058,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) float *fp, *fp1; int a, dpoly; - front.first= front.last= back.first= back.last= 0; + front.first= front.last= back.first= back.last= NULL; dl= dispbase->first; while(dl) { @@ -1107,7 +1119,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) } -static void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase) +static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase) { if(cu->flag & CU_3D) return; @@ -1126,16 +1138,14 @@ static void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase) */ float calc_taper(Scene *scene, Object *taperobj, int cur, int tot) { - Curve *cu; DispList *dl; if(taperobj==NULL || taperobj->type!=OB_CURVE) return 1.0; - cu= taperobj->data; - dl= cu->disp.first; + dl= taperobj->disp.first; if(dl==NULL) { makeDispListCurveTypes(scene, taperobj, 0); - dl= cu->disp.first; + dl= taperobj->disp.first; } if(dl) { float fac= ((float)cur)/(float)(tot-1); @@ -1192,6 +1202,8 @@ void makeDispListMBall(Scene *scene, Object *ob) void makeDispListMBall_forRender(Scene *scene, Object *ob, ListBase *dispbase) { metaball_polygonize(scene, ob, dispbase); + tex_space_mball(ob); + object_deform_mball(ob, dispbase); } @@ -1208,10 +1220,20 @@ static ModifierData *curve_get_tesselate_point(Scene *scene, Object *ob, int for preTesselatePoint = NULL; for (; md; md=md->next) { + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + if (!modifier_isEnabled(scene, md, required_mode)) continue; + if (mti->type == eModifierTypeType_Constructive) return preTesselatePoint; if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { - preTesselatePoint = md; + preTesselatePoint = md; + + /* this modifiers are moving point of tesselation automatically + (some of them even can't be applied on tesselated curve), set flag + for incformation button in modifier's header */ + md->mode |= eModifierMode_ApplyOnSpline; + } else if(md->mode&eModifierMode_ApplyOnSpline) { + preTesselatePoint = md; } } @@ -1603,8 +1625,15 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, for (nu=nubase->first; nu; nu=nu->next) { if(forRender || nu->hide==0) { + int resolu= nu->resolu, resolv= nu->resolv; + + if(forRender){ + if(cu->resolu_ren) resolu= cu->resolu_ren; + if(cu->resolv_ren) resolv= cu->resolv_ren; + } + if(nu->pntsv==1) { - len= SEGMENTSU(nu)*nu->resolu; + len= SEGMENTSU(nu)*resolu; dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); @@ -1623,10 +1652,10 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; - makeNurbcurve(nu, data, NULL, NULL, NULL, nu->resolu, 3*sizeof(float)); + makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float)); } else { - len= (nu->pntsu*nu->resolu) * (nu->pntsv*nu->resolv); + len= (nu->pntsu*resolu) * (nu->pntsv*resolv); dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); @@ -1642,12 +1671,12 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, data= dl->verts; dl->type= DL_SURF; - dl->parts= (nu->pntsu*nu->resolu); /* in reverse, because makeNurbfaces works that way */ - dl->nr= (nu->pntsv*nu->resolv); + dl->parts= (nu->pntsu*resolu); /* in reverse, because makeNurbfaces works that way */ + dl->nr= (nu->pntsv*resolv); if(nu->flagv & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_U; /* reverse too! */ if(nu->flagu & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_V; - makeNurbfaces(nu, data, 0); + makeNurbfaces(nu, data, 0, resolu, resolv); /* gl array drawing: using indices */ displist_surf_indices(dl); @@ -1655,6 +1684,11 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, } } + /* make copy of 'undeformed" displist for texture space calculation + actually, it's not totally undeformed -- pre-tesselation modifiers are + already applied, thats how it worked for years, so keep for compatibility (sergey) */ + copy_displist(&cu->disp, dispbase); + if (!forRender) { tex_space_curve(cu); } @@ -1700,7 +1734,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba /* no bevel or extrude, and no width correction? */ if (!dlbev.first && cu->width==1.0f) { - curve_to_displist(cu, nubase, dispbase); + curve_to_displist(cu, nubase, dispbase, forRender); } else { float widfac= cu->width-1.0; BevList *bl= cu->bev.first; @@ -1770,8 +1804,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba /* CU_2D conflicts with R_NOPUNOFLIP */ dl->rt= nu->flag & ~CU_2D; - dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "col2"); - bevp= (BevPoint *)(bl+1); + dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "bevelSplitFlag"); /* for each point of poly make a bevel piece */ bevp= (BevPoint *)(bl+1); @@ -1828,6 +1861,11 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba if(cu->flag & CU_PATH) calc_curvepath(ob); + /* make copy of 'undeformed" displist for texture space calculation + actually, it's not totally undeformed -- pre-tesselation modifiers are + already applied, thats how it worked for years, so keep for compatibility (sergey) */ + copy_displist(&cu->disp, dispbase); + if (!forRender) { tex_space_curve(cu); } @@ -1842,13 +1880,16 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) { - Curve *cu = ob->data; + Curve *cu= ob->data; ListBase *dispbase; freedisplist(&(ob->disp)); - dispbase= &(cu->disp); + dispbase= &(ob->disp); freedisplist(dispbase); + /* free displist used for textspace */ + freedisplist(&cu->disp); + do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco); if (ob->derivedFinal) { @@ -1895,15 +1936,10 @@ float *makeOrcoDispList(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int return orco; } -void imagestodisplist(void) -{ - /* removed */ -} - /* this is confusing, there's also min_max_object, appplying the obmat... */ static void boundbox_displist(Object *ob) { - BoundBox *bb=0; + BoundBox *bb=NULL; float min[3], max[3]; DispList *dl; float *vert; @@ -1915,10 +1951,10 @@ static void boundbox_displist(Object *ob) Curve *cu= ob->data; int doit= 0; - if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); + if(cu->bb==NULL) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); bb= cu->bb; - dl= cu->disp.first; + dl= ob->disp.first; while (dl) { if(dl->type==DL_INDEX3) tot= dl->nr; diff --git a/source/blender/blenkernel/intern/editderivedbmesh.c b/source/blender/blenkernel/intern/editderivedbmesh.c index 168e0e566de..b38521b0a23 100644 --- a/source/blender/blenkernel/intern/editderivedbmesh.c +++ b/source/blender/blenkernel/intern/editderivedbmesh.c @@ -61,6 +61,7 @@ #include "BLI_scanfill.h" #include "BLI_ghash.h" #include "BLI_array.h" +#include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" @@ -201,7 +202,7 @@ static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm) /*complete the loop*/ BLI_addfilledge(firstv, v); - BLI_edgefill(0, 0); + BLI_edgefill(0); for (efa = fillfacebase.first; efa; efa=efa->next) { BMLoop *l1, *l2, *l3; @@ -534,39 +535,44 @@ static void bmDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(vo static void bmDM_drawUVEdges(DerivedMesh *dm) { -#if 0 EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEditMesh *em = bmdm->tc; BMFace *efa; - MTFace *tf; + BMIter iter; glBegin(GL_LINES); - for(efa= bmdm->tc->bm->faces.first; efa; efa= efa->next) { - tf = CustomData_bm_get(&bmdm->tc->bm->pdata, efa->data, CD_MTFACE); - - if(tf && !(efa->h)) { - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - - if (!efa->v4) { - glVertex2fv(tf->uv[2]); - glVertex2fv(tf->uv[0]); - } else { - glVertex2fv(tf->uv[2]); - glVertex2fv(tf->uv[3]); - glVertex2fv(tf->uv[3]); - glVertex2fv(tf->uv[0]); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + BMIter liter; + BMLoop *l; + MLoopUV *lastluv = NULL, *firstluv = NULL; + + if (BM_TestHFlag(efa, BM_HIDDEN)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (luv) { + if (lastluv) + glVertex2fv(luv->uv); + glVertex2fv(luv->uv); + + lastluv = luv; + if (!firstluv) + firstluv = luv; } } + + if (lastluv) { + glVertex2fv(lastluv->uv); + glVertex2fv(firstluv->uv); + } } glEnd(); -#endif } -static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], - float (*vertexCos)[3]) +static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], + float (*vertexCos)[3]) { BMIter iter; BMLoop *l; @@ -591,7 +597,7 @@ static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], } if (tot==0) return; - VECMUL(cent, 1.0f/(float)tot); + mul_v3_fl(cent, 1.0f/(float)tot); } static void bmDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) @@ -1159,9 +1165,7 @@ static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r) vert_r->no[1] = (short)(ev->no[1] * 32767.0f); vert_r->no[2] = (short)(ev->no[2] * 32767.0f); - /* TODO what to do with vert_r->flag and vert_r->mat_nr? */ vert_r->flag = BMFlags_To_MEFlags(ev); - vert_r->mat_nr = 0; if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f); @@ -1255,8 +1259,6 @@ static void bmDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) vert_r->no[1] = (short) (ev->no[1] * 32767.0); vert_r->no[2] = (short) (ev->no[2] * 32767.0); - /* TODO what to do with vert_r->flag and vert_r->mat_nr? */ - vert_r->mat_nr = 0; vert_r->flag = BMFlags_To_MEFlags(ev); if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index fba96d2fd8f..5d8401d7a43 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -29,6 +29,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <stddef.h> #include "BLI_storage.h" /* _LARGEFILE_SOURCE */ #include <math.h> @@ -58,6 +59,7 @@ #include "BLI_listbase.h" #include "BLI_noise.h" #include "BLI_rand.h" +#include "BLI_utildefines.h" #include "PIL_time.h" @@ -85,8 +87,7 @@ #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_scene.h" -#include "BKE_screen.h" -#include "BKE_utildefines.h" + #include "RE_render_ext.h" #include "RE_shader_ext.h" @@ -165,7 +166,7 @@ PartEff *give_parteff(Object *ob) if(paf->type==EFF_PARTICLE) return paf; paf= paf->next; } - return 0; + return NULL; } void free_effect(Effect *eff) @@ -264,6 +265,9 @@ static void add_object_to_effectors(ListBase **effectors, Scene *scene, Effector eff = new_effector_cache(scene, ob, NULL, ob->pd); + /* make sure imat is up to date */ + invert_m4_m4(ob->imat, ob->obmat); + BLI_addtail(*effectors, eff); } static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src) @@ -410,7 +414,7 @@ void pd_point_from_soft(Scene *scene, float *loc, float *vel, int index, Effecte /************************************************/ // triangle - ray callback function -static void eff_tri_ray_hit(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +static void eff_tri_ray_hit(void *UNUSED(userData), int UNUSED(index), const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit) { // whenever we hit a bounding box, we don't check further hit->dist = -1; @@ -429,7 +433,7 @@ static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, Effect return visibility; if(!colls) - colls = get_collider_cache(eff->scene, NULL, NULL); + colls = get_collider_cache(eff->scene, eff->ob, NULL); if(!colls) return visibility; @@ -515,7 +519,7 @@ static float falloff_func_rad(PartDeflect *pd, float fac) return falloff_func(fac, pd->flag&PFIELD_USEMINR, pd->minrad, pd->flag&PFIELD_USEMAXR, pd->maxrad, pd->f_power_r); } -float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, EffectorWeights *weights) +float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *UNUSED(point), EffectorWeights *weights) { float temp[3]; float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f; @@ -625,7 +629,6 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin } } else if(eff->psys) { - ParticleSimulationData sim = {eff->scene, eff->ob, eff->psys, NULL, NULL}; ParticleData *pa = eff->psys->particles + *efd->index; ParticleKey state; @@ -633,6 +636,11 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin if(eff->psys == point->psys && *efd->index == point->index) ; else { + ParticleSimulationData sim= {NULL}; + sim.scene= eff->scene; + sim.ob= eff->ob; + sim.psys= eff->psys; + /* TODO: time from actual previous calculated frame (step might not be 1) */ state.time = cfra - 1.0; ret = psys_get_particle_state(&sim, *efd->index, &state, 0); @@ -643,11 +651,15 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin // eff->flag |= PE_VELOCITY_TO_IMPULSE; //} - VECCOPY(efd->loc, state.co); - VECCOPY(efd->nor, state.vel); - if(real_velocity) { - VECCOPY(efd->vel, state.vel); - } + copy_v3_v3(efd->loc, state.co); + + /* rather than use the velocity use rotated x-axis (defaults to velocity) */ + efd->nor[0] = 1.f; + efd->nor[1] = efd->nor[2] = 0.f; + mul_qt_v3(state.rot, efd->nor); + + if(real_velocity) + copy_v3_v3(efd->vel, state.vel); efd->size = pa->size; } @@ -667,10 +679,10 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin /* for vortex the shape chooses between old / new force */ if(eff->pd && eff->pd->shape == PFIELD_SHAPE_PLANE) { /* efd->loc is closes point on effector xy-plane */ - float temp[3]; + float temp[3], translate[3]; sub_v3_v3v3(temp, point->loc, ob->obmat[3]); - project_v3_v3v3(efd->loc, temp, efd->nor); - sub_v3_v3v3(efd->loc, point->loc, efd->loc); + project_v3_v3v3(translate, temp, efd->nor); + add_v3_v3v3(efd->loc, ob->obmat[3], translate); } else { VECCOPY(efd->loc, ob->obmat[3]); @@ -712,7 +724,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin return ret; } -static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p) +static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p, int *step) { if(eff->pd->shape == PFIELD_SHAPE_POINTS) { efd->index = p; @@ -745,6 +757,13 @@ static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoin *p= point->index % eff->psys->totpart; *tot= *p + 1; } + + if(eff->psys->part->effector_amount) { + int totpart = eff->psys->totpart; + int amount = eff->psys->part->effector_amount; + + *step = (totpart > amount) ? totpart/amount : 1; + } } else { *p = 0; @@ -762,7 +781,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP if(!eff->pd->tex) return; - result[0].nor = result[1].nor = result[2].nor = result[3].nor = 0; + result[0].nor = result[1].nor = result[2].nor = result[3].nor = NULL; strength= eff->pd->f_strength * efd->falloff; @@ -774,7 +793,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP } if(eff->pd->flag & PFIELD_TEX_OBJECT) { - mul_m4_v3(eff->ob->obmat, tex_co); + mul_m4_v3(eff->ob->imat, tex_co); } hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL,NULL, 0, result); @@ -826,7 +845,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP add_v3_v3(total_force, force); } -void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force) +static void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force) { PartDeflect *pd = eff->pd; RNG *rng = pd->rng; @@ -982,7 +1001,7 @@ void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *we */ EffectorCache *eff; EffectorData efd; - int p=0, tot = 1; + int p=0, tot = 1, step = 1; /* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */ /* Check for min distance here? (yes would be cool to add that, ton) */ @@ -990,9 +1009,9 @@ void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *we if(effectors) for(eff = effectors->first; eff; eff=eff->next) { /* object effectors were fully checked to be OK to evaluate! */ - get_effector_tot(eff, &efd, point, &tot, &p); + get_effector_tot(eff, &efd, point, &tot, &p, &step); - for(; p<tot; p++) { + for(; p<tot; p+=step) { if(get_effector_data(eff, &efd, point, 0)) { efd.falloff= effector_falloff(eff, &efd, point, weights); diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index deae6d2808b..4afce1e56c4 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -1,4 +1,5 @@ -/* exotic.c +/* + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -20,21 +21,24 @@ * All rights reserved. * * - * Contributor(s): + * Contributor(s): * - Martin DeMello * Added dxf_read_arc, dxf_read_ellipse and dxf_read_lwpolyline * Copyright (C) 2004 by Etheract Software Labs * * - Blender Foundation * - * ***** END GPL LICENSE BLOCK *****/ + * ***** END GPL LICENSE BLOCK **** + */ +#include <stddef.h> #include "BLI_storage.h" +#include <stdlib.h> #include <ctype.h> /* isdigit, isspace */ #include <math.h> #include <stdio.h> -#include <stdlib.h> + #include <fcntl.h> #include <string.h> #include <errno.h> @@ -59,9 +63,11 @@ #include "DNA_camera_types.h" #include "DNA_scene_types.h" -#include "BKE_utildefines.h" #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_storage.h" +#include "BLI_utildefines.h" + #include "BKE_blender.h" #include "BKE_global.h" @@ -71,22 +77,22 @@ #include "BKE_object.h" #include "BKE_material.h" #include "BKE_report.h" - +#include "BKE_exotic.h" #include "BKE_displist.h" #include "BKE_DerivedMesh.h" #include "BKE_curve.h" -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON #include "BPY_extern.h" #endif #include "zlib.h" -static int is_dxf(char *str); -static void dxf_read(Scene *scene, char *filename); -static int is_stl(char *str); +static int is_dxf(const char *str); +static void dxf_read(Scene *scene, const char *filename); +static int is_stl(const char *str); -static int is_stl_ascii(char *str) +static int is_stl_ascii(const char *str) { FILE *fpSTL; char buffer[1000]; @@ -111,7 +117,7 @@ static int is_stl_ascii(char *str) return 1; } -static int is_stl(char *str) +static int is_stl(const char *str) { int i; i = strlen(str) - 3; @@ -187,7 +193,7 @@ static void mesh_add_normals_flags(Mesh *me) } } -static void read_stl_mesh_binary(Scene *scene, char *str) +static void read_stl_mesh_binary(Scene *scene, const char *str) { FILE *fpSTL; Object *ob; @@ -311,7 +317,7 @@ static void read_stl_mesh_binary(Scene *scene, char *str) STLBAILOUT("Bad vertex!"); \ ++totvert; \ } -static void read_stl_mesh_ascii(Scene *scene, char *str) +static void read_stl_mesh_ascii(Scene *scene, const char *str) { FILE *fpSTL; char buffer[2048], *cp; @@ -360,10 +366,16 @@ static void read_stl_mesh_ascii(Scene *scene, char *str) * sure we have enough storage for some more faces */ if ( (totface) && ( (totface % 10000) == 0 ) ) { + float *vertdata_old= vertdata; ++numtenthousand; vertdata = realloc(vertdata, numtenthousand*3*30000*sizeof(float)); - if (!vertdata) { STLALLOCERROR; } + if (!vertdata) { + if(vertdata_old) { + free(vertdata_old); + } + STLALLOCERROR; + } } /* Don't read normal, but check line for proper syntax anyway @@ -449,1400 +461,60 @@ static void read_stl_mesh_ascii(Scene *scene, char *str) #undef STLREADLINE #undef STLREADVERT -/* ***************** INVENTOR ******************* */ - - -#define IV_MAXSTACK 3000000 -#define IV_MAXFIELD 10 -#define IV_MAXCOL 16 - -static float *iv_data_stack; -static float ivcolors[IV_MAXCOL][3]; -static Object *ivsurf; -static ListBase ivbase; - -struct IvNode { - struct IvNode *next, *prev; - char *nodename; - char *fieldname[IV_MAXFIELD]; - int datalen[IV_MAXFIELD]; - float *data[IV_MAXFIELD]; -}; - -static int iv_curcol=0; - -static int iv_colornumber(struct IvNode *iv) -{ - float *fp, fr = 0.0, fg = 0.0, fb = 0.0; - int a; - char *cp; - - /* search back to last material */ - while(iv) { - if( strcmp(iv->nodename, "Material")==0) { - fp= iv->data[0]; - if(fp==0) fp= iv->data[1]; - if(fp) { - fr= fp[0]; - fg= fp[1]; - fb= fp[2]; - } - break; - } - else if( strcmp(iv->nodename, "BaseColor")==0) { - fp= iv->data[0]; - fr= fp[0]; - fg= fp[1]; - fb= fp[2]; - break; - } - else if( strcmp(iv->nodename, "PackedColor")==0) { - cp= (char *)iv->data[0]; - fr= cp[3]/255.0f; - fg= cp[2]/255.0f; - fb= cp[1]/255.0f; - break; - } - iv= iv->prev; - - } - if(iv==0) return 0; - if(iv->datalen[0]<3) return 0; - - for(a=0; a<iv_curcol; a++) { - - if(ivcolors[a][0]== fr) - if(ivcolors[a][1]== fg) - if(ivcolors[a][2]== fb) return a+1 - ; - } - - if(a>=IV_MAXCOL) a= IV_MAXCOL-1; - iv_curcol= a+1; - ivcolors[a][0]= fr; - ivcolors[a][1]= fg; - ivcolors[a][2]= fb; - - return iv_curcol; -} - -static int iv_finddata(struct IvNode *iv, char *field, int fieldnr) -{ - /* search for "field", count data size and make datablock. return skipdata */ - float *fp; - int len, stackcount, skipdata=0; - char *cpa, terminator, str[64]; - intptr_t i; - - len= strlen(field); - - cpa= iv->nodename+1; - while( *cpa != '}' ) { - - if( *cpa == *field ) { - if( strncmp(cpa, field, len)==0 ) { - iv->fieldname[fieldnr]= cpa; - - /* read until first character */ - cpa+= len; - skipdata+= len; - *cpa= 0; - cpa++; - skipdata++; - - while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) cpa++; - if( *cpa=='[' ) { - terminator= ']'; - cpa++; - skipdata++; - } - else terminator= 13; - - stackcount= 0; - fp= iv_data_stack; - - while( *cpa!=terminator && *cpa != '}' ) { - - /* in fact, isdigit should include the dot and minus */ - if( (isdigit(*cpa) || *cpa=='.' || *cpa=='-') && (isspace(cpa[-1]) || cpa[-1]==0 || cpa[-1]==',') ) { - if(cpa[1]=='x') { - memcpy(str, cpa, 16); - str[16]= 0; - - sscanf(str, "%x", (int *)fp); - } - else { - /* atof doesn't stop after the first float - * in a long string at Windows... so we copy - * the float to a new string then atof... */ - char *cpa_temp = strpbrk(cpa, ", \n"); - i = cpa_temp - cpa; - - if (i>63) *fp= 0.0; - else { - memcpy(str, cpa, i); - str[i]=0; - - *fp= (float) atof(str); - } - } - - stackcount++; - if(stackcount>=IV_MAXSTACK) { - printf("stackoverflow in IV read\n"); - break; - } - fp++; - } - cpa++; - skipdata++; - } - - iv->datalen[fieldnr]= stackcount; - if(stackcount) { - iv->data[fieldnr]= MEM_mallocN(sizeof(float)*stackcount, "iv_finddata"); - memcpy(iv->data[fieldnr], iv_data_stack, sizeof(float)*stackcount); - } - else iv->data[fieldnr]= 0; - - return skipdata; - } - } - cpa++; - skipdata++; - } - - return skipdata; -} - -static void read_iv_index(float *data, float *baseadr, float *index, int nr, int coordtype) -{ - /* write in data: baseadr with offset index (and number nr) */ - float *fp; - int ofs; - - while(nr--) { - ofs= (int) *index; - fp= baseadr+coordtype*ofs; - VECCOPY(data, fp); - data+= 3; - index++; - } -} - - - -static void read_inventor(Scene *scene, char *str, struct ListBase *listb) -{ - struct IvNode *iv, *ivp, *ivn; - char *maindata, *md, *cpa; - float *index, *data, *fp; - int file, filelen, count, lll, face, nr = 0; - int skipdata, ok, a, b, tot, first, colnr, coordtype, polytype, *idata; - struct DispList *dl; - ReportList *reports= NULL; /* XXX */ - - ivbase.first= ivbase.last= 0; - iv_curcol= 0; - ivsurf= 0; - - file= open(str, O_BINARY|O_RDONLY); - if(file== -1) { - BKE_reportf(reports, RPT_ERROR, "Can't read file: %s.", strerror(errno)); - return; - } - - filelen= BLI_filesize(file); - if(filelen < 1) { - close(file); - return; - } - - maindata= MEM_mallocN(filelen, "leesInventor"); - if(read(file, maindata, filelen) < filelen) { - BKE_reportf(reports, RPT_ERROR, "Failed reading file: premature end of file."); - close(file); - return; - } - close(file); - - iv_data_stack= MEM_mallocN(sizeof(float)*IV_MAXSTACK, "ivstack"); - - /* preprocess: remove comments */ - md= maindata+20; - count= 20; - while(count<filelen) { - if( *md=='#' ) { /* comment */ - while( *md!=13 && *md!=10) { /* enters */ - *md= 32; - md++; - count++; - if(count>=filelen) break; - } - } - md++; - count++; - } - - - /* now time to collect: which are the nodes and fields? */ - md= maindata; - count= 0; - while(count<filelen) { - if( *md=='{' ) { /* read back */ - - cpa= md-1; - while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) { /* remove spaces/enters/tab */ - *cpa= 0; - cpa--; - } - - while( *cpa>32 && *cpa<128) cpa--; - cpa++; - *md= 0; - - ok= 0; - skipdata= 0; - iv= MEM_callocN(sizeof(struct IvNode), "leesInventor"); - iv->nodename= cpa; - - if(strcmp(cpa, "Coordinate3")==0 || strcmp(cpa, "Coordinate4")==0) { - skipdata= iv_finddata(iv, "point", 0); - ok= 1; - } - else if(strcmp(cpa, "VertexProperty")==0) { - skipdata= iv_finddata(iv, "vertex", 0); - ok= 1; - } - else if(strcmp(cpa, "IndexedLineSet")==0) { - skipdata= iv_finddata(iv, "coordIndex", 0); - ok= 1; - } - else if(strcmp(cpa, "IndexedTriangleMesh")==0) { - skipdata= iv_finddata(iv, "coordIndex", 0); - ok= 1; - } - else if(strcmp(cpa, "IndexedFaceSet")==0) { - skipdata= iv_finddata(iv, "coordIndex", 0); - ok= 1; - } - else if(strcmp(cpa, "FaceSet")==0) { - skipdata= iv_finddata(iv, "numVertices", 0); - ok= 1; - } - else if(strcmp(cpa, "Material")==0) { - iv_finddata(iv, "diffuseColor", 0); - iv_finddata(iv, "ambientColor", 1); - ok= 1; - } - else if(strcmp(cpa, "BaseColor")==0) { - iv_finddata(iv, "rgb", 0); - ok= 1; - } - else if(strcmp(cpa, "PackedColor")==0) { - iv_finddata(iv, "rgba", 0); - ok= 1; - } - else if(strcmp(cpa, "QuadMesh")==0) { - iv_finddata(iv, "verticesPerColumn", 0); - iv_finddata(iv, "verticesPerRow", 1); - - ok= 1; - } - else if(strcmp(cpa, "IndexedTriangleStripSet")==0) { - skipdata= iv_finddata(iv, "coordIndex", 0); - ok= 1; - } - else if(strcmp(cpa, "TriangleStripSet")==0) { - skipdata= iv_finddata(iv, "numVertices", 0); - ok= 1; - } - else if(strcmp(cpa, "IndexedNurbsSurface")==0 || strcmp(cpa, "NurbsSurface")==0) { - iv_finddata(iv, "numUControlPoints", 0); - iv_finddata(iv, "numVControlPoints", 1); - iv_finddata(iv, "uKnotVector", 2); - iv_finddata(iv, "vKnotVector", 3); - ok= 1; - } - else { - /* to the end */ - while( *md != '}') { - md++; - count++; - if(count<filelen) break; - } - } - - - if(ok) { - BLI_addtail(&ivbase, iv); - md+= skipdata; - count+= skipdata; - } - else MEM_freeN(iv); - - } - md++; - count++; - } - - /* join nodes */ - iv= ivbase.first; - - while(iv) { - ivn= iv->next; - - if( strncmp(iv->nodename, "Indexed", 7)==0) { - /* seek back: same name? */ - - ivp= iv->prev; - while(ivp) { - if(strcmp(iv->nodename, ivp->nodename)==0) break; - - if(strcmp(ivp->nodename, "Coordinate3")==0 || - strcmp(ivp->nodename, "Coordinate4")==0 || - strcmp(ivp->nodename, "VertexProperty")==0) { - ivp= 0; - break; - } - ivp= ivp->prev; - } - - if(ivp) { - /* add iv to ivp */ - - tot= iv->datalen[0] + ivp->datalen[0]; - if(tot) { - data= MEM_mallocN(tot*sizeof(float), "samenvoeg iv"); - memcpy(data, ivp->data[0], sizeof(float)*ivp->datalen[0]); - memcpy(data+ivp->datalen[0], iv->data[0], sizeof(float)*iv->datalen[0]); - - ivp->datalen[0]+= iv->datalen[0]; - MEM_freeN(ivp->data[0]); - ivp->data[0]= data; - - BLI_remlink(&ivbase, iv); - MEM_freeN(iv->data[0]); - MEM_freeN(iv); - } - } - } - - iv= ivn; - } - - - /* convert Nodes to DispLists */ - iv= ivbase.first; - while(iv) { - - /* printf(" Node: %s\n", iv->nodename); */ - /* if(iv->fieldname[0]) printf(" Field: %s len %d\n", iv->fieldname[0], iv->datalen[0]); */ - coordtype= 3; - - if( strcmp(iv->nodename, "IndexedLineSet")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - if(ivp) { - - /* count the nr of lines */ - tot= 0; - index= iv->data[0]; - lll = iv->datalen[0]-1; - for(a=0; a<lll; a++) { - if(index[0]!= -1 && index[1]!= -1) tot++; - index++; - } - - tot*= 2; /* nr of vertices */ - dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor1"); - BLI_addtail(listb, dl); - dl->type= DL_SEGM; - dl->nr= 2; - dl->parts= tot/2; - dl->col= colnr; - data= (float *)(dl+1); - - index= iv->data[0]; - for(a=0; a<lll; a++) { - if(index[0]!= -1 && index[1]!= -1) { - read_iv_index(data, ivp->data[0], index, 2, coordtype); - data+= 6; - } - index++; - } - } - } - else if( strcmp(iv->nodename, "FaceSet")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - - if(ivp) { - /* count triangles */ - tot= 0; - - index= iv->data[0]; - polytype= (int) index[0]; - - for(a=0; a<iv->datalen[0]; a++) { - if(index[0]== polytype) tot++; /* one kind? */ - index++; - } - - - tot*= polytype; /* nr of vertices */ - dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor4"); - BLI_addtail(listb, dl); - dl->type= DL_POLY; - dl->nr= polytype; - dl->parts= tot/polytype; - dl->col= colnr; - data= (float *)(dl+1); - - index= ivp->data[0]; - first= 1; - for(a=0; a<iv->datalen[0]; a++) { - - VECCOPY(data, index); - data+= 3; - index+= 3; - - VECCOPY(data, index); - data+= 3; - index+= 3; - - VECCOPY(data, index); - data+= 3; - index+= 3; - - if(polytype==4) { - VECCOPY(data, index); - data+= 3; - index+= 3; - } - } - } - } - else if( strcmp(iv->nodename, "TriangleStripSet")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - - if(ivp) { - /* count triangles */ - tot= 0; - face= 0; - - index= iv->data[0]; /* strip size */ - - for(a=0; a<iv->datalen[0]; a++) { - tot+= (int) index[0]; - face+= ((int) index[0]) - 2; - index++; - } - - dl= MEM_callocN(sizeof(struct DispList), "leesInventor4"); - dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts"); - dl->index= MEM_callocN( face*3*sizeof(int), "dl index"); - - dl->type= DL_INDEX3; - dl->nr= tot; - dl->parts= face; - - BLI_addtail(listb, dl); - dl->col= colnr; - - index= iv->data[0]; /* strip size */ - fp= ivp->data[0]; /* vertices */ - data= dl->verts; - idata= dl->index; - first= 0; - - for(a=0; a<iv->datalen[0]; a++) { - - /* vertices */ - for(b=0; b<index[0]; b++) { - VECCOPY(data, fp); - data+= 3; - fp+= coordtype; - } - - /* indices */ - lll = index[0] - 2; - for(b=0; b<lll; b++) { - idata[0]= first; - idata[1]= first+1; - idata[2]= first+2; - first++; - idata+= 3; - } - first+= 2; - - index++; - } - } - } - else if( strcmp(iv->nodename, "IndexedFaceSet")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - if(ivp) { - - /* count triangles */ - face= 0; - index= iv->data[0]; - lll = iv->datalen[0]-2; - for(a=0; a<lll; a++) { - if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++; - index++; - } - - /*number of vertices */ - tot= ivp->datalen[0]/coordtype; - - if(tot) { - dl= MEM_callocN(sizeof(struct DispList), "leesInventor5"); - BLI_addtail(listb, dl); - dl->type= DL_INDEX3; - dl->nr= tot; - dl->parts= face; - dl->col= colnr; - - dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts"); - dl->index= MEM_callocN(sizeof(int)*3*face, "dl index"); - - /* vertices */ - fp= ivp->data[0]; - data= dl->verts; - for(b=tot; b>0; b--) { - VECCOPY(data, fp); - data+= 3; - fp+= coordtype; - } - - /* indices */ - index= iv->data[0]; - idata= dl->index; - first= 1; - lll=iv->datalen[0]-2; - for(a=0; a<lll; a++) { - - if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) { - - /* this trick is to fill poly's with more than 3 vertices correctly */ - if(first) { - nr= (int) index[0]; - first= 0; - } - idata[0]= nr; - idata[1]= (int) index[1]; - idata[2]= (int) index[2]; - idata+= 3; - } - else first= 1; - - index++; - } - } - } - } - else if( strcmp(iv->nodename, "IndexedTriangleMesh")==0 || - strcmp(iv->nodename, "IndexedTriangleStripSet")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - if(ivp) { - - /* count triangles */ - face= 0; - index= iv->data[0]; - lll=iv->datalen[0]-2; - for(a=0; a<lll; a++) { - if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++; - index++; - } - - /* nr of vertices */ - tot= ivp->datalen[0]/coordtype; - - dl= MEM_callocN(sizeof(struct DispList), "leesInventor6"); - BLI_addtail(listb, dl); - dl->type= DL_INDEX3; - dl->nr= tot; - dl->parts= face; - dl->col= colnr; - - dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts"); - dl->index= MEM_callocN(sizeof(int)*3*face, "dl index"); - - /* vertices */ - fp= ivp->data[0]; - data= dl->verts; - for(b=tot; b>0; b--) { - VECCOPY(data, fp); - data+= 3; - fp+= coordtype; - } - - /* indices */ - index= iv->data[0]; - idata= dl->index; - - lll=iv->datalen[0]-2; - for(a=lll; a>0; a--) { - - if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) { - idata[0]= (int) index[0]; - idata[1]= (int) index[1]; - idata[2]= (int) index[2]; - idata+= 3; - } - index++; - } - } - } - else if( strcmp(iv->nodename, "QuadMesh")==0 ) { - - colnr= iv_colornumber(iv); - - /* seek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "VertexProperty")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - - if(ivp) { - tot= (int) (floor(*(iv->data[0])+0.5) * floor(*(iv->data[1])+0.5)); - - if(tot>0) { - dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor8"); - BLI_addtail(listb, dl); - dl->type= DL_SURF; - dl->parts= (int) floor(*(iv->data[0])+0.5); - dl->nr= (int) floor(*(iv->data[1])+0.5); - dl->col= colnr; - data= (float *)(dl+1); - memcpy(data, ivp->data[0], tot*3*sizeof(float)); - } - } - } - else if(strcmp(iv->nodename, "IndexedNurbsSurface")==0 || strcmp(iv->nodename, "NurbsSurface")==0) { - - colnr= iv_colornumber(iv); - - /* sek back to data */ - ivp= iv; - while(ivp->prev) { - ivp= ivp->prev; - if( strcmp(ivp->nodename, "Coordinate3")==0 ) { - coordtype= 3; - break; - } - if( strcmp(ivp->nodename, "Coordinate4")==0 ) { - coordtype= 4; - break; - } - } - if(ivp) { - a= (int) *(iv->data[0]); - b= (int) *(iv->data[1]); - - tot= a*b; - - if( (a>=4 || b>=4) && tot>6) { - Object *ob; - Curve *cu; - Nurb *nu; - BPoint *bp; - - if(ivsurf==0) { - ob= add_object(scene, OB_SURF); - ivsurf= ob; - } - else ob= ivsurf; - cu= ob->data; - nu = (Nurb*) MEM_callocN(sizeof(Nurb),"addNurbprim") ; - BLI_addtail(&cu->nurb, nu); - nu->type= CU_NURBS; - - nu->pntsu= a; - nu->pntsv= b; - nu->resolu= 2*a; - nu->resolv= 2*b; - - nu->flagu= 0; - nu->flagv= 0; - - nu->bp = bp = - (BPoint*)MEM_callocN(tot * sizeof(BPoint), "addNurbprim3"); - a= tot; - data= ivp->data[0]; - while(a--) { - VECCOPY(bp->vec, data); - if(coordtype==4) { - bp->vec[3]= data[3]; - mul_v3_fl(bp->vec, 1.0f/data[3]); - } - else bp->vec[3]= 1.0; - data+= coordtype; - bp++; - } - - /* iv->datalen[2] / [3] is number of knots */ - nu->orderu= iv->datalen[2] - nu->pntsu; - nu->orderv= iv->datalen[3] - nu->pntsv; - - nu->knotsu= MEM_mallocN( sizeof(float)*(iv->datalen[2]), "knots"); - memcpy(nu->knotsu, iv->data[2], sizeof(float)*(iv->datalen[2])); - nu->knotsv= MEM_mallocN( sizeof(float)*(iv->datalen[3]), "knots"); - memcpy(nu->knotsv, iv->data[3], sizeof(float)*(iv->datalen[3])); - - switchdirectionNurb(nu); - - } - else { - dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor3"); - BLI_addtail(listb, dl); - dl->type= DL_SURF; - dl->nr= (int) *(iv->data[0]); - dl->parts= (int) *(iv->data[1]); - dl->col= colnr; - data= (float *)(dl+1); - - a= tot; - fp= ivp->data[0]; - while(a--) { - VECCOPY(data, fp); - fp+= coordtype; - data+= 3; - } - } - } - } - iv= iv->next; - } - - /* free */ - iv= ivbase.first; - while(iv) { - for(a=0; a<IV_MAXFIELD; a++) { - if(iv->data[a]) MEM_freeN(iv->data[a]); - } - iv= iv->next; - } - - BLI_freelistN(&ivbase); - MEM_freeN(maindata); - MEM_freeN(iv_data_stack); - -} - /* ************************************************************ */ -static void displist_to_mesh(Scene *scene, DispList *dlfirst) -{ - Object *ob; - Mesh *me; - Material *ma; - DispList *dl; - MVert *mvert; - MFace *mface; - float *data, vec[3], min[3], max[3]; - int a, b, startve, *idata, totedge=0, tottria=0, totquad=0, totvert=0, totface, totcol=0, colnr; - int p1, p2, p3, p4; - unsigned int maxvertidx; - - /* count first */ - INIT_MINMAX(min, max); - - dl= dlfirst; - while(dl) { - - /* PATCH 1 (polyfill) can't be done, there's no listbase here. do that first! */ - /* PATCH 2 */ - if(dl->type==DL_SEGM && dl->nr>2) { - data= (float *)(dl+1); - if(data[0]==data[3*(dl->nr-1)]) { - if(data[1]==data[3*(dl->nr-1)+1]) { - if(data[2]==data[3*(dl->nr-1)+2]) { - dl->type= DL_POLY; - dl->nr--; - } - } - } - } - - /* colors */ - if(dl->col > totcol) totcol= dl->col; - - /* size and count */ - if(dl->type==DL_SURF) { - a= dl->nr; - b= dl->parts; - if(dl->flag & DL_CYCL_U) a++; - if(dl->flag & DL_CYCL_V) b++; - - totquad+= a*b; - - totvert+= dl->nr*dl->parts; - - data= (float *)(dl+1); - for(a= dl->nr*dl->parts; a>0; a--) { - DO_MINMAX(data, min, max); - data+= 3; - } - } - else if(dl->type==DL_POLY) { - if(dl->nr==3 || dl->nr==4) { - if(dl->nr==3) tottria+= dl->parts; - else totquad+= dl->parts; - - totvert+= dl->nr*dl->parts; - - data= (float *)(dl+1); - for(a= dl->nr*dl->parts; a>0; a--) { - DO_MINMAX(data, min, max); - data+= 3; - } - } - else if(dl->nr>4) { - - tottria+= dl->nr*dl->parts; - totvert+= dl->nr*dl->parts; - - data= (float *)(dl+1); - for(a= dl->nr*dl->parts; a>0; a--) { - DO_MINMAX(data, min, max); - data+= 3; - } - - } - } - else if(dl->type==DL_INDEX3) { - tottria+= dl->parts; - totvert+= dl->nr; - - data= dl->verts; - for(a= dl->nr; a>0; a--) { - DO_MINMAX(data, min, max); - data+= 3; - } - } - else if(dl->type==DL_SEGM) { - - tottria+= (dl->nr-1)*dl->parts; - totvert+= dl->nr*dl->parts; - - data= (float *)(dl+1); - for(a= dl->nr*dl->parts; a>0; a--) { - DO_MINMAX(data, min, max); - data+= 3; - } - } - - dl= dl->next; - } - - if(totvert==0) { - return; - } - - vec[0]= (min[0]+max[0])/2; - vec[1]= (min[1]+max[1])/2; - vec[2]= (min[2]+max[2])/2; - - ob= add_object(scene, OB_MESH); - VECCOPY(ob->loc, vec); - where_is_object(scene, ob); - - me= ob->data; - - /* colors */ - if(totcol) { - ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat"); - ob->matbits= MEM_callocN(sizeof(char)*totcol, "ob->matbits"); - me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat"); - me->totcol= totcol; - ob->totcol= (unsigned char) me->totcol; - ob->actcol= 1; - } - - /* materials */ - for(a=0; a<totcol; a++) { - ma= G.main->mat.first; - while(ma) { - if(ma->mtex[0]==0) { - if(ivcolors[a][0]==ma->r && ivcolors[a][1]==ma->g && ivcolors[a][2]==ma->b) { - me->mat[a]= ma; - ma->id.us++; - break; - } - } - ma= ma->id.next; - } - if(ma==0) { - ma= add_material("ext"); - me->mat[a]= ma; - ma->r= ivcolors[a][0]; - ma->g= ivcolors[a][1]; - ma->b= ivcolors[a][2]; - automatname(ma); - } - } - - totface= totquad+tottria+totedge; - - printf("Import: %d vertices %d faces\n", totvert, totface); - - me->totvert= totvert; - me->totface= totface; - me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, - NULL, me->totvert); - me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, - NULL, me->totface); - maxvertidx= totvert-1; - - mvert= me->mvert; - mface= me->mface; - - startve= 0; - - dl= dlfirst; - while(dl) { - - colnr= dl->col; - if(colnr) colnr--; - - if(dl->type==DL_SURF) { - data= (float *)(dl+1); - - for(a=dl->parts*dl->nr; a>0; a--) { - mvert->co[0]= data[0] -vec[0]; - mvert->co[1]= data[1] -vec[1]; - mvert->co[2]= data[2] -vec[2]; - - data+=3; - mvert++; - } - - for(a=0; a<dl->parts; a++) { - - if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0) - break; - - p1+= startve; - p2+= startve; - p3+= startve; - p4+= startve; - - for(; b<dl->nr; b++) { - - mface->v1= p1; - mface->v2= p2; - mface->v3= p4; - mface->v4= p3; - - mface->mat_nr= colnr; - test_index_face(mface, NULL, 0, 4); - - mface++; - - p4= p3; - p3++; - p2= p1; - p1++; - } - } - - startve += dl->parts*dl->nr; - - } - else if(dl->type==DL_POLY) { - - if(dl->nr==3 || dl->nr==4) { - data= (float *)(dl+1); - - for(a=dl->parts*dl->nr; a>0; a--) { - mvert->co[0]= data[0] -vec[0]; - mvert->co[1]= data[1] -vec[1]; - mvert->co[2]= data[2] -vec[2]; - data+=3; - mvert++; - } - - for(a=0; a<dl->parts; a++) { - if(dl->nr==3) { - mface->v1= startve+a*dl->nr; - mface->v2= startve+a*dl->nr+1; - mface->v3= startve+a*dl->nr+2; - mface->mat_nr= colnr; - test_index_face(mface, NULL, 0, 3); - mface++; - } - else { - mface->v1= startve+a*dl->nr; - mface->v2= startve+a*dl->nr+1; - mface->v3= startve+a*dl->nr+2; - mface->v4= startve+a*dl->nr+3; - mface->mat_nr= colnr; - test_index_face(mface, NULL, 0, 4); - mface++; - } - } - startve += dl->parts*dl->nr; - } - else if(dl->nr>4) { - data= (float *)(dl+1); - - for(a=dl->parts*dl->nr; a>0; a--) { - mvert->co[0]= data[0] -vec[0]; - mvert->co[1]= data[1] -vec[1]; - mvert->co[2]= data[2] -vec[2]; - - data+=3; - mvert++; - } - - for(b=0; b<dl->parts; b++) { - for(a=0; a<dl->nr; a++) { - mface->v1= startve+a; - - if(a==dl->nr-1) mface->v2= startve; - else mface->v2= startve+a+1; - - mface->mat_nr= colnr; - - mface++; - } - startve += dl->nr; - } - } - } - else if(dl->type==DL_INDEX3) { - data= dl->verts; - - for(a=dl->nr; a>0; a--) { - mvert->co[0]= data[0] -vec[0]; - mvert->co[1]= data[1] -vec[1]; - mvert->co[2]= data[2] -vec[2]; - data+=3; - mvert++; - } - - idata= dl->index; - for(b=dl->parts; b>0; b--) { - mface->v1= startve+idata[0]; - mface->v2= startve+idata[1]; - mface->v3= startve+idata[2]; - mface->mat_nr= colnr; - - if (mface->v1>maxvertidx) mface->v1= maxvertidx; - if (mface->v2>maxvertidx) mface->v2= maxvertidx; - if (mface->v3>maxvertidx) mface->v3= maxvertidx; - - test_index_face(mface, NULL, 0, 3); - mface++; - idata+= 3; - } - startve += dl->nr; - } - else if(dl->type==DL_SEGM) { - data= (float *)(dl+1); - - for(a=dl->parts*dl->nr; a>0; a--) { - mvert->co[0]= data[0] -vec[0]; - mvert->co[1]= data[1] -vec[1]; - mvert->co[2]= data[2] -vec[2]; - data+=3; - mvert++; - } - - for(b=0; b<dl->parts; b++) { - for(a=0; a<dl->nr-1; a++) { - mface->v1= startve+a; - mface->v2= startve+a+1; - mface->mat_nr= colnr; - mface++; - } - startve += dl->nr; - } - } - dl= dl->next; - } - - mesh_add_normals_flags(me); - make_edges(me, 0); -} - -static void displist_to_objects(Scene *scene, ListBase *lbase) -{ - DispList *dl, *first, *prev, *next; - ListBase tempbase; - int maxaantal, curcol, totvert=0, vert; - - /* irst this: is still active */ - if(ivsurf) { - where_is_object(scene, ivsurf); -// XXX docenter_new(); - } - - dl= lbase->first; - while(dl) { - next= dl->next; - - /* PATCH 1: polyfill */ - if(dl->type==DL_POLY && dl->nr>4) { - /* solution: put them together in separate listbase */ - ; - } - /* PATCH 2: poly's of 2 points */ - if(dl->type==DL_POLY && dl->nr==2) dl->type= DL_SEGM; - - dl= next; - } - - /* count vertices */ - - dl= lbase->first; - while(dl) { - - if(dl->type==DL_SURF) totvert+= dl->nr*dl->parts; - else if(dl->type==DL_POLY) { - if(dl->nr==3 || dl->nr==4) totvert+= dl->nr*dl->parts; - else if(dl->nr>4) totvert+= dl->nr*dl->parts; - } - else if(dl->type==DL_INDEX3) totvert+= dl->nr; - else if(dl->type==DL_SEGM) totvert+= dl->nr*dl->parts; - - dl= dl->next; - } - - if(totvert==0) { - - if(ivsurf==0) {}; //XXX error("Found no data"); - if(lbase->first) BLI_freelistN(lbase); - - return; - } - - maxaantal= 32000; - - if(totvert>maxaantal) { - - /* try to put colors together */ - curcol= 0; - tempbase.first= tempbase.last= 0; - - while(lbase->first) { - dl= lbase->first; - while(dl) { - next= dl->next; - if(dl->col==curcol) { - BLI_remlink(lbase, dl); - BLI_addtail(&tempbase, dl); - dl->col= 0; - } - - dl= next; - } - - /* in tempbase are all 'curcol' */ - totvert= 0; - dl= first= tempbase.first; - while(dl) { - vert= 0; - - if(dl->type==DL_SURF) vert= dl->nr*dl->parts; - else if(dl->type==DL_POLY) { - if(dl->nr==3 || dl->nr==4) vert= dl->nr*dl->parts; - else if(dl->nr>4) vert= dl->nr*dl->parts; - } - else if(dl->type==DL_INDEX3) totvert+= dl->nr; - else if(dl->type==DL_SEGM) vert= dl->nr*dl->parts; - - totvert+= vert; - if(totvert > maxaantal || dl->next==0) { - if(dl->next==0) { - displist_to_mesh(scene, first); - } - else if(dl->prev) { - prev= dl->prev; - prev->next= 0; - displist_to_mesh(scene, first); - prev->next= dl; - first= dl; - totvert= 0; - } - } - - dl= dl->next; - } - - freedisplist(&tempbase); - - curcol++; - } - } - else displist_to_mesh(scene, lbase->first); - - freedisplist(lbase); - -} - -int BKE_read_exotic(Scene *scene, char *name) +int BKE_read_exotic(Scene *scene, const char *name) { - ListBase lbase={0, 0}; int len; gzFile gzfile; - char str[32]; - int *s0 = (int*) str; - int retval = 0; + char header[7]; + int retval; // make sure we're not trying to read a directory.... len= strlen(name); - if (name[len-1] !='/' && name[len-1] != '\\') { + if (ELEM(name[len-1], '/', '\\')) { + retval= BKE_READ_EXOTIC_FAIL_PATH; + } + else { gzfile = gzopen(name,"rb"); - if (NULL == gzfile ) { - //XXX error("Can't open file: %s", name); - retval= -1; - } else { - gzread(gzfile, str, 31); + if (gzfile == NULL) { + retval= BKE_READ_EXOTIC_FAIL_OPEN; + } + else { + len= gzread(gzfile, header, sizeof(header)); gzclose(gzfile); - - if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0) && !BLI_testextensie(name,".blend.gz")) { - + if (len == sizeof(header) && strncmp(header, "BLENDER", 7) == 0) { + retval= BKE_READ_EXOTIC_OK_BLEND; + } + else { //XXX waitcursor(1); - if(strncmp(str, "#Inventor V1.0", 14)==0) { - if( strncmp(str+15, "ascii", 5)==0) { - read_inventor(scene, name, &lbase); - displist_to_objects(scene, &lbase); - retval = 1; - } else { - //XXX error("Can only read Inventor 1.0 ascii"); - } - } - else if((strncmp(str, "#VRML V1.0 asc", 14)==0)) { - read_inventor(scene, name, &lbase); - displist_to_objects(scene, &lbase); - retval = 1; - } - else if(is_dxf(name)) { + if(is_dxf(name)) { dxf_read(scene, name); - retval = 1; + retval= BKE_READ_EXOTIC_OK_OTHER; } else if(is_stl(name)) { if (is_stl_ascii(name)) read_stl_mesh_ascii(scene, name); else read_stl_mesh_binary(scene, name); - retval = 1; + retval= BKE_READ_EXOTIC_OK_OTHER; } -#ifndef DISABLE_PYTHON - // TODO: this should not be in the kernel... - else { // unknown format, call Python importloader - if (BPY_call_importloader(name)) { - retval = 1; - } else { - //XXX error("Unknown file type or error, check console"); - } - + else { + retval= BKE_READ_EXOTIC_FAIL_FORMAT; } -#endif /* DISABLE_PYTHON */ //XXX waitcursor(0); } } } - return (retval); + return retval; } /* ************************ WRITE ************************** */ - -char temp_dir[160]= {0, 0}; - static void write_vert_stl(Object *ob, MVert *verts, int index, FILE *fpSTL) { float vert[3]; @@ -1887,7 +559,7 @@ static int write_derivedmesh_stl(FILE *fpSTL, Object *ob, DerivedMesh *dm) return numfacets; } -static int write_object_stl(FILE *fpSTL, Scene *scene, Object *ob, Mesh *me) +static int write_object_stl(FILE *fpSTL, Scene *scene, Object *ob) { int numfacets = 0; DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); @@ -1902,20 +574,12 @@ static int write_object_stl(FILE *fpSTL, Scene *scene, Object *ob, Mesh *me) void write_stl(Scene *scene, char *str) { Object *ob; - Mesh *me; Base *base; FILE *fpSTL; int numfacets = 0; ReportList *reports= NULL; /* XXX */ - - if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0; - if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0; - if(BLI_testextensie(str,".stl")==0) strcat(str, ".stl"); - if (BLI_exists(str)) { - ; //XXX if(saveover(str)==0) - //XXX return; - } + /* XXX, operator needs to manage filename extension */ fpSTL= fopen(str, "wb"); @@ -1923,7 +587,6 @@ void write_stl(Scene *scene, char *str) BKE_reportf(reports, RPT_ERROR, "Can't open file: %s.", strerror(errno)); return; } - strcpy(temp_dir, str); //XXX waitcursor(1); @@ -1942,9 +605,8 @@ void write_stl(Scene *scene, char *str) if (base->flag & SELECT) { ob = base->object; if (ob->type == OB_MESH) { - me = ob->data; - if (me) - numfacets += write_object_stl(fpSTL, scene, ob, me); + if(ob->data) + numfacets += write_object_stl(fpSTL, scene, ob); } } base= base->next; @@ -1965,7 +627,6 @@ void write_stl(Scene *scene, char *str) //XXX waitcursor(0); } -/* ******************************* WRITE VRML ***************************** */ static void replace_chars(char *str1, char *str2) { @@ -1978,354 +639,6 @@ static void replace_chars(char *str1, char *str2) } } - -static void write_material_vrml(FILE *fp, Material *ma) -{ - char str[32]; - - replace_chars(str, ma->id.name+2); - - fprintf(fp, "\tDEF %s\n", str); - fprintf(fp, "\tMaterial {\n"); - - fprintf(fp, "\t\tdiffuseColor %f %f %f\n", ma->r, ma->g, ma->b); - fprintf(fp, "\t\tspecularColor %f %f %f\n", ma->specr, ma->specg, ma->specb); - fprintf(fp, "\t\tshininess %f \n", ((float)ma->har)/100.0); - fprintf(fp, "\t\ttransparency %f \n", 1.0-ma->alpha); - - fprintf(fp, "\t}\n"); - -} - -unsigned int *mcol_to_vcol(Mesh *me) -{ - MFace *mface; - unsigned int *mcol, *mcoln, *mcolmain; - int a; - - if(me->totface==0 || me->mcol==0) return 0; - - mcoln= mcolmain= MEM_mallocN(sizeof(int)*me->totvert, "mcoln"); - mcol = (unsigned int *)me->mcol; - mface= me->mface; - - for(a=me->totface; a>0; a--, mface++) { - mcoln[mface->v1]= mcol[0]; - mcoln[mface->v2]= mcol[1]; - mcoln[mface->v3]= mcol[2]; - if(mface->v4) mcoln[mface->v4]= mcol[3]; - - mcol+= 4; - } - - return mcolmain; -} - -void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a) -{ - char *cp; - - cp = (char *)&col; - - *r= cp[3]; - *r /= 255.0; - - *g= cp[2]; - *g /= 255.0; - - *b= cp[1]; - *b /= 255.0; - - *a= cp[0]; - *a /= 255.0; -} - -static void write_mesh_vrml(FILE *fp, Mesh *me) -{ - Material *ma; - MVert *mvert; - MFace *mface; - MTFace *tface; - Image *ima; - int a, b, totcol, texind; - char str[32]; - - replace_chars(str, me->id.name+2); - - fprintf(fp, "\tDEF %s\n", str); - fprintf(fp, "\tSeparator {\n"); - - if(me->mtface) { - ima= ((MTFace *)me->mtface)->tpage; - if(ima) { - fprintf(fp, "\t\tTexture2 {\n"); - fprintf(fp, "\t\t\tfilename %s\n", ima->name); - fprintf(fp, "\t\t\twrapS REPEAT \n"); - fprintf(fp, "\t\t\twrapT REPEAT \n"); - fprintf(fp, "\t\t}\n"); - } - } - - if(me->mcol) { - unsigned int *mcol, *mcolmain; - float r, g, b, cola; - - fprintf(fp, "\t\tMaterial {\n"); - fprintf(fp, "\t\t\tdiffuseColor [\n"); - - a= me->totvert; - mcol= mcolmain= mcol_to_vcol(me); - if(mcol) { - while(a--) { - mcol_to_rgba(*mcol, &r, &g, &b, &cola); - fprintf(fp, "\t\t\t\t %f %f %f,\n", r, g, b); - mcol++; - } - MEM_freeN(mcolmain); - } - fprintf(fp, "\t\t\t]\n"); - fprintf(fp, "\t\t}\n"); - - fprintf(fp, "\t\tMaterialBinding { value PER_VERTEX_INDEXED }\n"); - } - - - fprintf(fp, "\t\tCoordinate3 {\n"); - fprintf(fp, "\t\t\tpoint [\n"); - - a= me->totvert; - mvert= me->mvert; - while(a--) { - fprintf(fp, "\t\t\t\t %f %f %f,\n", mvert->co[0], mvert->co[1], mvert->co[2]); - mvert++; - } - fprintf(fp, "\t\t\t]\n"); - fprintf(fp, "\t\t}\n"); - - - totcol= me->totcol; - if(totcol==0) totcol= 1; - texind= 0; // index for uv coords - - for(b=0; b<totcol; b++) { - - if(me->mcol==0) { - if(me->mat) { - ma= me->mat[b]; - if(ma) { - replace_chars(str, ma->id.name+2); - - fprintf(fp, "\t\tUSE %s\n\n", str); - } - } - } - - if(me->mtface) { - fprintf(fp, "\t\tTextureCoordinate2 {\n"); - fprintf(fp, "\t\t\tpoint [\n"); - - a= me->totface; - mface= me->mface; - tface= me->mtface; - while(a--) { - if(mface->mat_nr==b) { - fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[0][0], tface->uv[0][1]); - fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[1][0], tface->uv[1][1]); - fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[2][0], tface->uv[2][1]); - if(mface->v4) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[3][0], tface->uv[3][1]); - } - mface++; - tface++; - } - fprintf(fp, "\t\t\t]\n"); - fprintf(fp, "\t\t}\n"); - } - - fprintf(fp, "\t\tIndexedFaceSet {\n"); - fprintf(fp, "\t\t\tcoordIndex [\n"); - - a= me->totface; - mface= me->mface; - while(a--) { - if(mface->mat_nr==b) { - if(mface->v4) fprintf(fp, "\t\t\t\t %d, %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3, mface->v4); - else fprintf(fp, "\t\t\t\t %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3); - } - mface++; - } - fprintf(fp, "\t\t\t]\n"); - - if(me->mtface) { - fprintf(fp, "\t\t\ttextureCoordIndex [\n"); - - a= me->totface; - mface= me->mface; - while(a--) { - if(mface->mat_nr==b) { - if(mface->v4) { - fprintf(fp, "\t\t\t\t %d, %d, %d, %d, -1,\n", texind, texind+1, texind+2, texind+3); - texind+= 4; - } - else { - fprintf(fp, "\t\t\t\t %d, %d, %d, -1,\n", texind, texind+1, texind+2); - texind+= 3; - } - } - mface++; - } - fprintf(fp, "\t\t\t]\n"); - } - fprintf(fp, "\t\t}\n"); - } - - fprintf(fp, "\t}\n"); -} - -static void write_camera_vrml(FILE *fp, Object *ob) -{ - Camera *cam; - - if(ob==0) return; - invert_m4_m4(ob->imat, ob->obmat); - - fprintf(fp, "\tMatrixTransform {\n"); - - fprintf(fp, "\tmatrix \n"); - - fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[0][0], ob->imat[0][1], ob->imat[0][2], ob->imat[0][3]); - fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[1][0], ob->imat[1][1], ob->imat[1][2], ob->imat[1][3]); - fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[2][0], ob->imat[2][1], ob->imat[2][2], ob->imat[2][3]); - fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[3][0], ob->imat[3][1], ob->imat[3][2], ob->imat[3][3]); - - fprintf(fp, "\t}\n"); - - cam= ob->data; - - fprintf(fp, "\tPerspectiveCamera {\n"); - fprintf(fp, "\t\tfocalDistance %f\n", cam->lens/10.0); - - fprintf(fp, "\t}\n"); - -} - -static void write_object_vrml(FILE *fp, Object *ob) -{ - ID *id; - char str[32]; - - fprintf(fp, "\tSeparator {\n"); - fprintf(fp, "\t\tMatrixTransform {\n"); - - fprintf(fp, "\t\tmatrix \n"); - - fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[0][0], ob->obmat[0][1], ob->obmat[0][2], ob->obmat[0][3]); - fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[1][0], ob->obmat[1][1], ob->obmat[1][2], ob->obmat[1][3]); - fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[2][0], ob->obmat[2][1], ob->obmat[2][2], ob->obmat[2][3]); - fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2], ob->obmat[3][3]); - - fprintf(fp, "\t\t}\n"); - - id= ob->data; - - replace_chars(str, id->name+2); - - fprintf(fp, "\t\tUSE %s\n", str); - fprintf(fp, "\t}\n"); -} - - -void write_vrml(Scene *scene, char *str) -{ - Mesh *me; - Material *ma; - Base *base; - FILE *fp; - - if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0; - if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0; - if(BLI_testextensie(str,".wrl")==0) strcat(str, ".wrl"); - //XXX saveover() if(saveover(str)==0) return; - - fp= fopen(str, "w"); - - if(fp==NULL) { - //XXX error("Can't write file"); - return; - } - strcpy(temp_dir, str); - - //XXX waitcursor(1); - - /* FIRST: write all the datablocks */ - - fprintf(fp, "#VRML V1.0 ascii\n\n# Blender V%d\n\n# 'Switch' is used as a hack, to ensure it is not part of the drawing\n\n", BLENDER_VERSION); - fprintf(fp, "Separator {\n"); - fprintf(fp, "Switch {\n"); - - ma= G.main->mat.first; - while(ma) { - if(ma->id.us) { - write_material_vrml(fp, ma); - } - ma= ma->id.next; - } - - /* only write meshes we're using in this scene */ - flag_listbase_ids(&G.main->mesh, LIB_DOIT, 0); - - for(base= scene->base.first; base; base= base->next) - if(base->object->type== OB_MESH) - ((ID *)base->object->data)->flag |= LIB_DOIT; - - me= G.main->mesh.first; - while(me) { - if(me->id.flag & LIB_DOIT) { /* is the mesh used in this scene ? */ - write_mesh_vrml(fp, me); - } - me= me->id.next; - } - - /* THEN:Hidden Objects */ - fprintf(fp, "\n\t# Hidden Objects, in invisible layers\n\n"); - base= scene->base.first; - while(base) { - if(base->object->type== OB_MESH) { - if( (base->lay & scene->lay)==0 ) { - write_object_vrml(fp, base->object); - } - } - base= base->next; - } - - fprintf(fp, "}\n"); - fprintf(fp, "\n# Visible Objects\n\n"); - fprintf(fp, "Separator {\n"); - - /* The camera */ - - write_camera_vrml(fp, scene->camera); - - /* THEN:The Objects */ - - base= scene->base.first; - while(base) { - if(base->object->type== OB_MESH) { - if(base->lay & scene->lay) { - write_object_vrml(fp, base->object); - } - } - base= base->next; - } - - fprintf(fp, "}\n"); - fprintf(fp, "}\n"); - - fclose(fp); - - //XXX waitcursor(0); -} - - /* ******************************* WRITE DXF ***************************** */ #define write_group(id,data) fprintf(fp, "%d\n%s\n", id, data) @@ -2551,15 +864,7 @@ void write_dxf(struct Scene *scene, char *str) Base *base; FILE *fp; - if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0; - if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0; - if(BLI_testextensie(str,".dxf")==0) strcat(str, ".dxf"); - - - if (BLI_exists(str)) { - ; //XXX if(saveover(str)==0) - // return; - } + /* XXX, operator needs to handle overwrite & rename */ fp= fopen(str, "w"); @@ -2567,7 +872,6 @@ void write_dxf(struct Scene *scene, char *str) //XXX error("Can't write file"); return; } - strcpy(temp_dir, str); //XXX waitcursor(1); @@ -2672,7 +976,7 @@ static int all_digits(char *str) return 1; } -static int dxf_get_layer_col(char *layer) +static int dxf_get_layer_col(char *UNUSED(layer)) { return 1; } @@ -2710,8 +1014,8 @@ static void myfgets(char *str, int len, FILE *fp) /* three types of enters, \n \r and \r\n */ if(c == '\n') break; if(c=='\r') { - c= getc(dxf_fp); // read the linefeed from stream - if(c != 10) ungetc(c, dxf_fp); // put back, if it's not one... + c= getc(fp); // read the linefeed from stream + if(c != 10) ungetc(c, fp); // put back, if it's not one... break; } } @@ -2764,7 +1068,7 @@ static char val[256]; static short error_exit=0; static short hasbumped=0; -static int is_dxf(char *str) +static int is_dxf(const char *str) { dxf_line=0; @@ -2827,7 +1131,7 @@ static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer) ma= G.main->mat.first; while(ma) { - if(ma->mtex[0]==0) { + if(ma->mtex[0]==NULL) { if(color[0]==ma->r && color[1]==ma->g && color[2]==ma->b) { me->mat[0]= ma; ma->id.us++; @@ -2836,7 +1140,7 @@ static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer) } ma= ma->id.next; } - if(ma==0) { + if(ma==NULL) { ma= add_material("ext"); me->mat[0]= ma; ma->r= color[0]; @@ -2866,10 +1170,10 @@ static void dxf_get_mesh(Scene *scene, Mesh** m, Object** o, int noob) *o = add_object(scene, OB_MESH); ob = *o; - if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname); - else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname); + if (entname[0]) new_id(&G.main->object, (ID *)ob, entname); + else if (layname[0]) new_id(&G.main->object, (ID *)ob, layname); - if (strlen(layname)) ob->lay= dxf_get_layer_num(scene, layname); + if (layname[0]) ob->lay= dxf_get_layer_num(scene, layname); else ob->lay= scene->lay; // not nice i know... but add_object() sets active base, which needs layer setting too (ton) scene->basact->lay= ob->lay; @@ -2888,8 +1192,8 @@ static void dxf_get_mesh(Scene *scene, Mesh** m, Object** o, int noob) ((ID *)me)->us=0; - if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname); - else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname); + if (entname[0]) new_id(&G.main->mesh, (ID *)me, entname); + else if (layname[0]) new_id(&G.main->mesh, (ID *)me, layname); vcenter = zerovec; } @@ -3345,7 +1649,7 @@ static void dxf_read_arc(Scene *scene, int noob) cent[2]= center[2]; dxf_get_mesh(scene, &me, &ob, noob); - strcpy(oldllay, layname); + BLI_strncpy(oldllay, layname, sizeof(oldllay)); if(ob) VECCOPY(ob->loc, cent); dxf_add_mat (ob, me, color, layname); @@ -3902,7 +2206,7 @@ static void dxf_read_3dface(Scene *scene, int noob) hasbumped=1; } -static void dxf_read(Scene *scene, char *filename) +static void dxf_read(Scene *scene, const char *filename) { Mesh *lastMe = G.main->mesh.last; @@ -4071,7 +2375,7 @@ static void dxf_read(Scene *scene, char *filename) ob->dupon= 1; ob->dupoff= 0; ob->dupsta= 1; ob->dupend= 100; - ob->recalc= OB_RECALC_ALL; /* needed because of weird way of adding libdata directly */ + ob->recalc= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; /* needed because of weird way of adding libdata directly */ ob->data= obdata; ((ID*)ob->data)->us++; @@ -4090,7 +2394,7 @@ static void dxf_read(Scene *scene, char *filename) I leave it commented out here as warning (ton) */ //for (i=0; i<ob->totcol; i++) ob->mat[i]= ((Mesh*)ob->data)->mat[i]; - if (strlen(layname)) ob->lay= dxf_get_layer_num(scene, layname); + if (layname[0]) ob->lay= dxf_get_layer_num(scene, layname); else ob->lay= scene->lay; /* link to scene */ diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 43f01199b69..b50943ba9f1 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -41,6 +41,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_utildefines.h" #include "BKE_fcurve.h" #include "BKE_animsys.h" @@ -53,7 +54,7 @@ #include "RNA_access.h" -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON #include "BPY_extern.h" #endif @@ -163,10 +164,10 @@ void copy_fcurves (ListBase *dst, ListBase *src) } } -/* --------------------- Finding -------------------------- */ +/* ----------------- Finding F-Curves -------------------------- */ /* high level function to get an fcurve from C without having the rna */ -FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, char *prop_name, int index) +FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index) { /* anim vars */ AnimData *adt= BKE_animdata_from_id(id); @@ -220,7 +221,7 @@ FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array for (fcu= list->first; fcu; fcu= fcu->next) { /* simple string-compare (this assumes that they have the same root...) */ if (fcu->rna_path && !strcmp(fcu->rna_path, rna_path)) { - /* now check indicies */ + /* now check indices */ if (fcu->array_index == array_index) return fcu; } @@ -298,36 +299,36 @@ int list_find_data_fcurves (ListBase *dst, ListBase *src, const char *dataPrefix return matches; } -FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, int *driven) +FCurve *rna_get_fcurve (PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, int *driven) { FCurve *fcu= NULL; *driven= 0; /* there must be some RNA-pointer + property combon */ - if(prop && ptr->id.data && RNA_property_animateable(ptr, prop)) { + if (prop && ptr->id.data && RNA_property_animateable(ptr, prop)) { AnimData *adt= BKE_animdata_from_id(ptr->id.data); char *path; - if(adt) { - if((adt->action && adt->action->curves.first) || (adt->drivers.first)) { + if (adt) { + if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) { /* XXX this function call can become a performance bottleneck */ path= RNA_path_from_ID_to_property(ptr, prop); - if(path) { + if (path) { /* animation takes priority over drivers */ - if(adt->action && adt->action->curves.first) + if (adt->action && adt->action->curves.first) fcu= list_find_fcurve(&adt->action->curves, path, rnaindex); /* if not animated, check if driven */ - if(!fcu && (adt->drivers.first)) { + if (!fcu && (adt->drivers.first)) { fcu= list_find_fcurve(&adt->drivers, path, rnaindex); - if(fcu) + if (fcu) *driven= 1; } - if(fcu && action) + if (fcu && action) *action= adt->action; MEM_freeN(path); @@ -339,6 +340,8 @@ FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction return fcu; } +/* ----------------- Finding Keyframes/Extents -------------------------- */ + /* threshold for binary-searching keyframes - threshold here should be good enough for now, but should become userpref */ #define BEZT_BINARYSEARCH_THRESH 0.01f /* was 0.00001, but giving errors */ @@ -469,11 +472,7 @@ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, flo foundvert=1; } - /* minimum sizes are 1.0f */ if (foundvert) { - if (xminv == xmaxv) xmaxv += 1.0f; - if (yminv == ymaxv) ymaxv += 1.0f; - if (xmin) *xmin= xminv; if (xmax) *xmax= xmaxv; @@ -481,10 +480,13 @@ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, flo if (ymax) *ymax= ymaxv; } else { + if (G.f & G_DEBUG) + printf("F-Curve calc bounds didn't find anything, so assuming minimum bounds of 1.0\n"); + if (xmin) *xmin= 0.0f; - if (xmax) *xmax= 0.0f; + if (xmax) *xmax= 1.0f; - if (ymin) *ymin= 1.0f; + if (ymin) *ymin= 0.0f; if (ymax) *ymax= 1.0f; } } @@ -520,6 +522,87 @@ void calc_fcurve_range (FCurve *fcu, float *start, float *end) } } +/* ----------------- Status Checks -------------------------- */ + +/* Are keyframes on F-Curve of any use? + * Usability of keyframes refers to whether they should be displayed, + * and also whether they will have any influence on the final result. + */ +short fcurve_are_keyframes_usable (FCurve *fcu) +{ + /* F-Curve must exist */ + if (fcu == NULL) + return 0; + + /* F-Curve must not have samples - samples are mutually exclusive of keyframes */ + if (fcu->fpt) + return 0; + + /* if it has modifiers, none of these should "drastically" alter the curve */ + if (fcu->modifiers.first) { + FModifier *fcm; + + /* check modifiers from last to first, as last will be more influential */ + // TODO: optionally, only check modifier if it is the active one... + for (fcm = fcu->modifiers.last; fcm; fcm = fcm->prev) { + /* ignore if muted/disabled */ + if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) + continue; + + /* type checks */ + switch (fcm->type) { + /* clearly harmless - do nothing */ + case FMODIFIER_TYPE_CYCLES: + case FMODIFIER_TYPE_STEPPED: + case FMODIFIER_TYPE_NOISE: + break; + + /* sometimes harmful - depending on whether they're "additive" or not */ + case FMODIFIER_TYPE_GENERATOR: + { + FMod_Generator *data = (FMod_Generator *)fcm->data; + + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + return 0; + } + break; + case FMODIFIER_TYPE_FN_GENERATOR: + { + FMod_FunctionGenerator *data = (FMod_FunctionGenerator *)fcm->data; + + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + return 0; + } + break; + + /* always harmful - cannot allow */ + default: + return 0; + } + } + } + + /* keyframes are usable */ + return 1; +} + +/* Can keyframes be added to F-Curve? + * Keyframes can only be added if they are already visible + */ +short fcurve_is_keyframable (FCurve *fcu) +{ + /* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */ + if (fcurve_are_keyframes_usable(fcu) == 0) + return 0; + + /* F-Curve must currently be editable too */ + if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) + return 0; + + /* F-Curve is keyframable */ + return 1; +} + /* ***************************** Keyframe Column Tools ********************************* */ /* add a BezTriple to a column */ @@ -556,7 +639,7 @@ void bezt_add_to_cfra_elem (ListBase *lb, BezTriple *bezt) /* Basic sampling callback which acts as a wrapper for evaluate_fcurve() * 'data' arg here is unneeded here... */ -float fcurve_samplingcb_evalcurve (FCurve *fcu, void *data, float evaltime) +float fcurve_samplingcb_evalcurve (FCurve *fcu, void *UNUSED(data), float evaltime) { /* assume any interference from drivers on the curve is intended... */ return evaluate_fcurve(fcu, evaltime); @@ -801,7 +884,7 @@ typedef struct DriverVarTypeInfo { /* allocation of target slots */ int num_targets; /* number of target slots required */ - char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */ + const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */ int target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */ } DriverVarTypeInfo; @@ -851,31 +934,44 @@ static float dtar_get_prop_val (ChannelDriver *driver, DriverTarget *dtar) /* get property to read from, and get value as appropriate */ if (RNA_path_resolve_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - if (RNA_property_array_length(&ptr, prop)) + if(RNA_property_array_check(&ptr, prop)) { + /* array */ + if (index < RNA_property_array_length(&ptr, prop)) { + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: value= (float)RNA_property_boolean_get_index(&ptr, prop, index); - else - value= (float)RNA_property_boolean_get(&ptr, prop); + break; + case PROP_INT: + value= (float)RNA_property_int_get_index(&ptr, prop, index); + break; + case PROP_FLOAT: + value= RNA_property_float_get_index(&ptr, prop, index); + break; + default: + break; + } + } + } + else { + /* not an array */ + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: + value= (float)RNA_property_boolean_get(&ptr, prop); break; case PROP_INT: - if (RNA_property_array_length(&ptr, prop)) - value= (float)RNA_property_int_get_index(&ptr, prop, index); - else - value= (float)RNA_property_int_get(&ptr, prop); + value= (float)RNA_property_int_get(&ptr, prop); break; case PROP_FLOAT: - if (RNA_property_array_length(&ptr, prop)) - value= RNA_property_float_get_index(&ptr, prop, index); - else - value= RNA_property_float_get(&ptr, prop); + value= RNA_property_float_get(&ptr, prop); break; case PROP_ENUM: value= (float)RNA_property_enum_get(&ptr, prop); break; default: break; + } } + } else { if (G.f & G_DEBUG) @@ -1106,7 +1202,7 @@ static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar) /* ......... */ /* Table of Driver Varaiable Type Info Data */ -DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = { +static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = { BEGIN_DVAR_TYPEDEF(DVAR_TYPE_SINGLE_PROP) dvar_eval_singleProp, /* eval callback */ 1, /* number of targets used */ @@ -1137,7 +1233,7 @@ DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = { }; /* Get driver variable typeinfo */ -DriverVarTypeInfo *get_dvar_typeinfo (int type) +static DriverVarTypeInfo *get_dvar_typeinfo (int type) { /* check if valid type */ if ((type >= 0) && (type < MAX_DVAR_TYPES)) @@ -1174,7 +1270,7 @@ void driver_free_variable (ChannelDriver *driver, DriverVar *dvar) else MEM_freeN(dvar); -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON /* since driver variables are cached, the expression needs re-compiling too */ if(driver->type==DRIVER_TYPE_PYTHON) driver->flag |= DRIVER_FLAG_RENAMEVAR; @@ -1231,9 +1327,9 @@ DriverVar *driver_add_new_variable (ChannelDriver *driver) /* set the default type to 'single prop' */ driver_change_variable_type(dvar, DVAR_TYPE_SINGLE_PROP); -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON /* since driver variables are cached, the expression needs re-compiling too */ - if(driver->type==DRIVER_TYPE_PYTHON) + if (driver->type==DRIVER_TYPE_PYTHON) driver->flag |= DRIVER_FLAG_RENAMEVAR; #endif @@ -1258,7 +1354,7 @@ void fcurve_free_driver(FCurve *fcu) driver_free_variable(driver, dvar); } -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON /* free compiled driver expression */ if (driver->expr_comp) BPY_DECREF(driver->expr_comp); @@ -1331,7 +1427,7 @@ float driver_get_variable_value (ChannelDriver *driver, DriverVar *dvar) * - "evaltime" is the frame at which F-Curve is being evaluated * - has to return a float value */ -static float evaluate_driver (ChannelDriver *driver, float evaltime) +static float evaluate_driver (ChannelDriver *driver, float UNUSED(evaltime)) { DriverVar *dvar; @@ -1406,7 +1502,7 @@ static float evaluate_driver (ChannelDriver *driver, float evaltime) case DRIVER_TYPE_PYTHON: /* expression */ { -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON /* check for empty or invalid expression */ if ( (driver->expression[0] == '\0') || (driver->flag & DRIVER_FLAG_INVALID) ) @@ -1418,9 +1514,9 @@ static float evaluate_driver (ChannelDriver *driver, float evaltime) /* this evaluates the expression using Python,and returns its result: * - on errors it reports, then returns 0.0f */ - driver->curval= BPY_eval_driver(driver); + driver->curval= BPY_driver_exec(driver); } -#endif /* DISABLE_PYTHON*/ +#endif /* WITH_PYTHON*/ } break; diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 834fd09aac2..810c56dbe5d 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -1,6 +1,5 @@ -/** - * fluidsim.c - * +/* + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -28,6 +27,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <stddef.h> #include "BLI_storage.h" /* _LARGEFILE_SOURCE */ #include "MEM_guardedalloc.h" @@ -42,6 +42,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" @@ -50,7 +51,7 @@ #include "BKE_global.h" #include "BKE_modifier.h" #include "BKE_mesh.h" -#include "BKE_utildefines.h" + // headers for fluidsim bobj meshes #include <stdlib.h> diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index 1642fadf33d..804c26295bd 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -1,4 +1,4 @@ -/** +/* * $Id: fmodifier.c 21537 2009-07-11 22:22:53Z gsrb3d $ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -38,10 +38,11 @@ #include "BLI_blenlib.h" #include "BLI_math.h" /* windows needs for M_PI */ +#include "BLI_utildefines.h" #include "BKE_fcurve.h" #include "BKE_idprop.h" -#include "BKE_utildefines.h" + #define SMALL -1.0e-10 #define SELECT 1 @@ -146,7 +147,7 @@ static void fcm_generator_verify (FModifier *fcm) nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs"); if (data->coefficients) { - if (data->arraysize > (data->poly_order+1)) + if ((int)data->arraysize > (data->poly_order+1)) memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1)); else memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); @@ -172,7 +173,7 @@ static void fcm_generator_verify (FModifier *fcm) nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs"); if (data->coefficients) { - if (data->arraysize > (data->poly_order * 2)) + if (data->arraysize > (unsigned int)(data->poly_order * 2)) memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2)); else memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); @@ -190,7 +191,7 @@ static void fcm_generator_verify (FModifier *fcm) } } -static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +static void fcm_generator_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime) { FMod_Generator *data= (FMod_Generator *)fcm->data; @@ -240,7 +241,7 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, unsigned int i; /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */ - for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++) + for (cp=data->coefficients, i=0; (cp) && (i < (unsigned int)data->poly_order); cp+=2, i++) value *= (cp[0]*evaltime + cp[1]); /* only if something changed, write *cvalue in one go */ @@ -303,7 +304,7 @@ static double sinc (double x) return sin(M_PI * x) / (M_PI * x); } -static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +static void fcm_fn_generator_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime) { FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; double arg= data->phase_multiplier*evaltime + data->phase_offset; @@ -432,7 +433,7 @@ static void fcm_envelope_verify (FModifier *fcm) } } -static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +static void fcm_envelope_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime) { FMod_Envelope *env= (FMod_Envelope *)fcm->data; FCM_EnvelopeData *fed, *prevfed, *lastfed; @@ -524,12 +525,12 @@ static void fcm_cycles_new_data (void *mdata) data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC; } -static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) +static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float UNUSED(cvalue), float evaltime) { FMod_Cycles *data= (FMod_Cycles *)fcm->data; float prevkey[2], lastkey[2], cycyofs=0.0f; short side=0, mode=0; - int cycles=0; + int cycles=0, ofs=0; /* check if modifier is first in stack, otherwise disable ourself... */ // FIXME... @@ -571,6 +572,7 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e side= -1; mode= data->before_mode; cycles= data->before_cycles; + ofs= prevkey[0]; } } else if (evaltime > lastkey[0]) { @@ -578,6 +580,7 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e side= 1; mode= data->after_mode; cycles= data->after_cycles; + ofs= lastkey[0]; } } if ELEM(0, side, mode) @@ -585,11 +588,8 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e /* find relative place within a cycle */ { - float cycdx=0, cycdy=0, ofs=0; - float cycle= 0; - - /* ofs is start frame of cycle */ - ofs= prevkey[0]; + float cycdx=0, cycdy=0; + float cycle= 0, cyct=0; /* calculate period and amplitude (total height) of a cycle */ cycdx= lastkey[0] - prevkey[0]; @@ -601,6 +601,9 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e /* calculate the 'number' of the cycle */ cycle= ((float)side * (evaltime - ofs) / cycdx); + + /* calculate the time inside the cycle */ + cyct= fmod(evaltime - ofs, cycdx); /* check that cyclic is still enabled for the specified time */ if (cycles == 0) { @@ -608,7 +611,7 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e * as this indicates infinite cycles... */ } - else if (cycle > (cycles+1)) { + else if (cycle > cycles) { /* we are too far away from range to evaluate * TODO: but we should still hold last value... */ @@ -617,26 +620,36 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */ if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { - cycyofs = (float)floor((evaltime - ofs) / cycdx); + if(side < 0) + cycyofs = (float)floor((evaltime - ofs) / cycdx); + else + cycyofs = (float)ceil((evaltime - ofs) / cycdx); cycyofs *= cycdy; } - + + /* special case for cycle start/end */ + if(cyct == 0.0f) { + evaltime = (side == 1 ? lastkey[0] : prevkey[0]); + + if((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)cycle % 2)) + evaltime = (side == 1 ? prevkey[0] : lastkey[0]); + } /* calculate where in the cycle we are (overwrite evaltime to reflect this) */ - if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) { + else if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle+1) % 2)) { /* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse * - for 'before' extrapolation, we need to flip in a different way, otherwise values past * then end of the curve get referenced (result of fmod will be negative, and with different phase) */ if (side < 0) - evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx)); + evaltime= prevkey[0] - cyct; else - evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx)); + evaltime= lastkey[0] - cyct; } else { /* the cycle is played normally... */ - evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs); + evaltime= prevkey[0] + cyct; } - if (evaltime < ofs) evaltime += cycdx; + if (evaltime < prevkey[0]) evaltime += cycdx; } /* store temp data if needed */ @@ -652,7 +665,7 @@ static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float e return evaltime; } -static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +static void fcm_cycles_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float UNUSED(evaltime)) { tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata; @@ -696,7 +709,7 @@ static void fcm_noise_new_data (void *mdata) data->modification = FCM_NOISE_MODIF_REPLACE; } -static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +static void fcm_noise_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime) { FMod_Noise *data= (FMod_Noise *)fcm->data; float noise; @@ -788,15 +801,15 @@ static void fcm_python_copy (FModifier *fcm, FModifier *src) pymod->prop = IDP_CopyProperty(opymod->prop); } -static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +static void fcm_python_evaluate (FCurve *UNUSED(fcu), FModifier *UNUSED(fcm), float *UNUSED(cvalue), float UNUSED(evaltime)) { -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON //FMod_Python *data= (FMod_Python *)fcm->data; /* FIXME... need to implement this modifier... * It will need it execute a script using the custom properties */ -#endif /* DISABLE_PYTHON */ +#endif /* WITH_PYTHON */ } static FModifierTypeInfo FMI_PYTHON = { @@ -817,7 +830,7 @@ static FModifierTypeInfo FMI_PYTHON = { /* Limits F-Curve Modifier --------------------------- */ -static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) +static float fcm_limits_time (FCurve *UNUSED(fcu), FModifier *fcm, float UNUSED(cvalue), float evaltime) { FMod_Limits *data= (FMod_Limits *)fcm->data; @@ -831,7 +844,7 @@ static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float e return evaltime; } -static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +static void fcm_limits_evaluate (FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float UNUSED(evaltime)) { FMod_Limits *data= (FMod_Limits *)fcm->data; @@ -868,7 +881,7 @@ static void fcm_stepped_new_data (void *mdata) data->step_size = 2.0f; } -static float fcm_stepped_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) +static float fcm_stepped_time (FCurve *UNUSED(fcu), FModifier *fcm, float UNUSED(cvalue), float evaltime) { FMod_Stepped *data= (FMod_Stepped *)fcm->data; int snapblock; @@ -920,7 +933,7 @@ static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES]; static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */ /* This function only gets called when FMI_INIT is non-zero */ -static void fmods_init_typeinfo () +static void fmods_init_typeinfo (void) { fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */ fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */ @@ -997,9 +1010,13 @@ FModifier *add_fmodifier (ListBase *modifiers, int type) fcm->flag = FMODIFIER_FLAG_EXPANDED; BLI_addtail(modifiers, fcm); + /* tag modifier as "active" if no other modifiers exist in the stack yet */ + if (modifiers->first == modifiers->last) + fcm->flag |= FMODIFIER_FLAG_ACTIVE; + /* add modifier's data */ fcm->data= MEM_callocN(fmi->size, fmi->structName); - + /* init custom settings if necessary */ if (fmi->new_data) fmi->new_data(fcm->data); diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 501de668000..05988605b4c 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -41,6 +41,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_vfontdata.h" +#include "BLI_utildefines.h" #include "DNA_packedFile_types.h" #include "DNA_curve_types.h" @@ -49,9 +50,7 @@ #include "DNA_object_types.h" #include "BKE_utildefines.h" - #include "BKE_packedFile.h" - #include "BKE_library.h" #include "BKE_font.h" #include "BKE_global.h" @@ -97,13 +96,14 @@ chtoutf8(unsigned long c, char *o) void wcs2utf8s(char *dst, wchar_t *src) { - char ch[5]; + /* NULL terminator not needed */ + char ch[4]; while(*src) { - memset(ch, 0, 5); + memset(ch, 0, sizeof(ch)); chtoutf8(*src++, ch); - strcat(dst, ch); + dst= strncat(dst, ch, sizeof(ch)); } } @@ -124,31 +124,27 @@ wcsleninu8(wchar_t *src) } static int -utf8slen(char *src) +utf8slen(const char *strc) { - int size = 0, index = 0; - unsigned char c; - - c = src[index++]; - while(c) - { - if((c & 0x80) == 0) - { - index += 0; - } - else if((c & 0xe0) == 0xe0) - { - index += 2; - } - else - { - index += 1; + int len=0; + + while(*strc) { + if ((*strc & 0xe0) == 0xc0) { + if((strc[1] & 0x80) && (strc[1] & 0x40) == 0x00) + strc++; + } else if ((*strc & 0xf0) == 0xe0) { + if((strc[1] & strc[2] & 0x80) && ((strc[1] | strc[2]) & 0x40) == 0x00) + strc += 2; + } else if ((*strc & 0xf8) == 0xf0) { + if((strc[1] & strc[2] & strc[3] & 0x80) && ((strc[1] | strc[2] | strc[3]) & 0x40) == 0x00) + strc += 3; } - size += 1; - c = src[index++]; + + strc++; + len++; } - - return size; + + return len; } @@ -212,7 +208,7 @@ int utf8towchar(wchar_t *w, char *c) /* The vfont code */ void free_vfont(struct VFont *vf) { - if (vf == 0) return; + if (vf == NULL) return; if (vf->data) { while(vf->data->characters.first) @@ -305,7 +301,7 @@ static VFontData *vfont_get_data(VFont *vfont) if (!vfont->data) { PackedFile *pf; - if (BLI_streq(vfont->name, "<builtin>")) { + if (strcmp(vfont->name, FO_BUILTIN_NAME)==0) { pf= get_builtin_packedfile(); } else { if (vfont->packedfile) { @@ -342,7 +338,7 @@ static VFontData *vfont_get_data(VFont *vfont) if(!pf) { printf("Font file doesn't exist: %s\n", vfont->name); - strcpy(vfont->name, "<builtin>"); + strcpy(vfont->name, FO_BUILTIN_NAME); pf= get_builtin_packedfile(); } } @@ -358,7 +354,7 @@ static VFontData *vfont_get_data(VFont *vfont) return vfont->data; } -VFont *load_vfont(char *name) +VFont *load_vfont(const char *name) { char filename[FILE_MAXFILE]; VFont *vfont= NULL; @@ -367,15 +363,15 @@ VFont *load_vfont(char *name) int is_builtin; struct TmpFont *tmpfnt; - if (BLI_streq(name, "<builtin>")) { - strcpy(filename, name); + if (strcmp(name, FO_BUILTIN_NAME)==0) { + BLI_strncpy(filename, name, sizeof(filename)); pf= get_builtin_packedfile(); is_builtin= 1; } else { char dir[FILE_MAXDIR]; - strcpy(dir, name); + BLI_strncpy(dir, name, sizeof(dir)); BLI_splitdirstring(dir, filename); pf= newPackedFile(NULL, name); @@ -394,7 +390,7 @@ VFont *load_vfont(char *name) /* if there's a font name, use it for the ID name */ if (strcmp(vfd->name, "")!=0) { - BLI_strncpy(vfont->id.name+2, vfd->name, 21); + BLI_strncpy(vfont->id.name+2, vfd->name, sizeof(vfont->id.name)-2); } BLI_strncpy(vfont->name, name, sizeof(vfont->name)); @@ -403,8 +399,8 @@ VFont *load_vfont(char *name) vfont->packedfile = pf; } - // Do not add <builtin> to temporary listbase - if(strcmp(filename, "<builtin>")) + // Do not add FO_BUILTIN_NAME to temporary listbase + if(strcmp(filename, FO_BUILTIN_NAME)) { tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font"); tmpfnt->pf= tpf; @@ -443,10 +439,10 @@ VFont *get_builtin_font(void) VFont *vf; for (vf= G.main->vfont.first; vf; vf= vf->id.next) - if (BLI_streq(vf->name, "<builtin>")) + if (strcmp(vf->name, FO_BUILTIN_NAME)==0) return vf; - return load_vfont("<builtin>"); + return load_vfont(FO_BUILTIN_NAME); } static VChar *find_vfont_char(VFontData *vfd, intptr_t character) @@ -480,7 +476,7 @@ static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, i nu2->flagu = CU_NURB_CYCLIC; bp = (BPoint*)MEM_callocN(4 * sizeof(BPoint),"underline_bp"); - if (bp == 0){ + if (bp == NULL){ MEM_freeN(nu2); return; } @@ -514,11 +510,12 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float float *fp, fsize, shear, x, si, co; VFontData *vfd = NULL; VChar *che = NULL; - int i, sel=0; + int i; vfd= vfont_get_data(which_vfont(cu, info)); if (!vfd) return; + /* if (cu->selend < cu->selstart) { if ((charidx >= (cu->selend)) && (charidx <= (cu->selstart-2))) sel= 1; @@ -527,6 +524,7 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float if ((charidx >= (cu->selstart-1)) && (charidx <= (cu->selend-1))) sel= 1; } + */ /* make a copy at distance ofsx,ofsy with shear*/ fsize= cu->fsize; @@ -546,10 +544,10 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float bezt1 = nu1->bezt; if (bezt1){ nu2 =(Nurb*) MEM_mallocN(sizeof(Nurb),"duplichar_nurb"); - if (nu2 == 0) break; + if (nu2 == NULL) break; memcpy(nu2, nu1, sizeof(struct Nurb)); nu2->resolu= cu->resolu; - nu2->bp = 0; + nu2->bp = NULL; nu2->knotsu = nu2->knotsv = NULL; nu2->flag= CU_SMOOTH; nu2->charidx = charidx; @@ -564,7 +562,7 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float i = nu2->pntsu; bezt2 = (BezTriple*)MEM_mallocN(i * sizeof(BezTriple),"duplichar_bezt2"); - if (bezt2 == 0){ + if (bezt2 == NULL){ MEM_freeN(nu2); break; } @@ -672,7 +670,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) VFont *vfont, *oldvfont; VFontData *vfd= NULL; Curve *cu; - CharInfo *info, *custrinfo; + CharInfo *info = NULL, *custrinfo; TextBox *tb; VChar *che; struct chartrans *chartransdata=NULL, *ct; @@ -688,18 +686,18 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) /* renark: do calculations including the trailing '\0' of a string because the cursor can be at that location */ - if(ob->type!=OB_FONT) return 0; + if(ob->type!=OB_FONT) return NULL; // Set font data cu= (Curve *) ob->data; vfont= cu->vfont; - if(cu->str == NULL) return 0; - if(vfont == NULL) return 0; + if(cu->str == NULL) return NULL; + if(vfont == NULL) return NULL; // Create unicode string utf8len = utf8slen(cu->str); - tmp = mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem"); + mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem"); utf8towchar(mem, cu->str); @@ -725,7 +723,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) if(!vfd) { if(mem) MEM_freeN(mem); - return 0; + return NULL; } /* calc offset and rotation of each char */ @@ -760,7 +758,6 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) for (i = 0 ; i<=slen ; i++) { makebreak: // Characters in the list - che = vfd->characters.first; info = &(custrinfo[i]); ascii = mem[i]; if(info->flag & CU_CHINFO_SMALLCAPS) { @@ -779,10 +776,10 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) /* * The character wasn't in the current curve base so load it - * But if the font is <builtin> then do not try loading since + * But if the font is FO_BUILTIN_NAME then do not try loading since * whole font is in the memory already */ - if(che == NULL && strcmp(vfont->name, "<builtin>")) { + if(che == NULL && strcmp(vfont->name, FO_BUILTIN_NAME)) { BLI_vfontchar_from_freetypefont(vfont, ascii); } @@ -790,11 +787,11 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) che= find_vfont_char(vfd, ascii); /* No VFont found */ - if (vfont==0) { + if (vfont==NULL) { if(mem) MEM_freeN(mem); MEM_freeN(chartransdata); - return 0; + return NULL; } if (vfont != oldvfont) { @@ -807,7 +804,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) if(mem) MEM_freeN(mem); MEM_freeN(chartransdata); - return 0; + return NULL; } twidth = char_width(cu, che, info); @@ -862,12 +859,15 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) yof= cu->yof + tb->y/cu->fsize; } + /* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */ +#if 0 if(ascii == '\n' || ascii == '\r') xof = cu->xof; else xof= cu->xof + (tb->x/cu->fsize); - +#else xof= cu->xof + (tb->x/cu->fsize); +#endif lnr++; cnr= 0; wsnr= 0; @@ -1042,10 +1042,9 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) che= find_vfont_char(vfd, ascii); twidth = char_width(cu, che, info); - - dtime= distfac*0.35f*twidth; /* why not 0.5? */ - dtime= distfac*0.5f*twidth; /* why not 0.5? */ - + + dtime= distfac*0.5f*twidth; + ctime= timeofs + distfac*( ct->xof - minx); CLAMP(ctime, 0.0, 1.0); @@ -1146,16 +1145,14 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) return NULL; } - if(mode==0) { + if(mode == FO_EDIT) { /* make nurbdata */ - unsigned long cha; - freeNurblist(&cu->nurb); ct= chartransdata; if (cu->sepchar==0) { for (i= 0; i<slen; i++) { - cha = (uintptr_t) mem[i]; + unsigned long cha = (uintptr_t) mem[i]; info = &(custrinfo[i]); if (info->mat_nr > (ob->totcol)) { /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */ @@ -1193,8 +1190,12 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) ascii = mem[i]; info = &(custrinfo[i]); if (cu->sepchar == (i+1)) { - float vecyo[3]= {ct->xof, ct->yof, 0.0f}; - + float vecyo[3]; + + vecyo[0]= ct->xof; + vecyo[1]= ct->yof; + vecyo[2]= 0.0f; + mem[0] = ascii; mem[1] = 0; custrinfo[0]= *info; @@ -1218,7 +1219,5 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) MEM_freeN(mem); MEM_freeN(chartransdata); - return 0; + return NULL; } - - diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 5612d69ed76..abd7c12ff70 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -33,8 +33,8 @@ #include "MEM_guardedalloc.h" - #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "DNA_gpencil_types.h" @@ -42,7 +42,7 @@ #include "BKE_gpencil.h" #include "BKE_library.h" #include "BKE_main.h" -#include "BKE_utildefines.h" + /* ************************************************** */ @@ -190,7 +190,7 @@ bGPDlayer *gpencil_layer_addnew (bGPdata *gpd) } /* add a new gp-datablock */ -bGPdata *gpencil_data_addnew (char name[]) +bGPdata *gpencil_data_addnew (const char name[]) { bGPdata *gpd; diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index bdf203119c3..e48ec8ac288 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -41,6 +41,8 @@ #include "DNA_particle_types.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" + #include "BKE_global.h" #include "BKE_group.h" @@ -127,7 +129,7 @@ void unlink_group(Group *group) group->id.us= 0; } -Group *add_group(char *name) +Group *add_group(const char *name) { Group *group; @@ -327,7 +329,7 @@ static void group_replaces_nla(Object *parent, Object *target, char mode) you can draw everything, leaves tags in objects to signal it needs further updating */ /* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */ -void group_handle_recalc_and_update(Scene *scene, Object *parent, Group *group) +void group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group *group) { GroupObject *go; diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 78306705d6b..8ce3847bf08 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -40,6 +40,7 @@ #include "DNA_world_types.h" #include "DNA_brush_types.h" +#include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BKE_icons.h" @@ -76,7 +77,7 @@ static void icon_free(void *val) /* create an id for a new icon and make sure that ids from deleted icons get reused after the integer number range is used up */ -static int get_next_free_id() +static int get_next_free_id(void) { int startId = gFirstIconId; @@ -105,14 +106,14 @@ void BKE_icons_init(int first_dyn_id) gIcons = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "icons_init gh"); } -void BKE_icons_free() +void BKE_icons_free(void) { if(gIcons) - BLI_ghash_free(gIcons, 0, icon_free); + BLI_ghash_free(gIcons, NULL, icon_free); gIcons = NULL; } -struct PreviewImage* BKE_previewimg_create() +struct PreviewImage* BKE_previewimg_create(void) { PreviewImage* prv_img = NULL; int i; @@ -218,7 +219,7 @@ PreviewImage* BKE_previewimg_get(ID *id) void BKE_icon_changed(int id) { - Icon* icon = 0; + Icon* icon = NULL; if (!id || G.background) return; @@ -241,7 +242,7 @@ void BKE_icon_changed(int id) int BKE_icon_getid(struct ID* id) { - Icon* new_icon = 0; + Icon* new_icon = NULL; if (!id || G.background) return 0; @@ -262,8 +263,8 @@ int BKE_icon_getid(struct ID* id) new_icon->type = GS(id->name); /* next two lines make sure image gets created */ - new_icon->drawinfo = 0; - new_icon->drawinfo_free = 0; + new_icon->drawinfo = NULL; + new_icon->drawinfo_free = NULL; BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon); @@ -272,13 +273,13 @@ int BKE_icon_getid(struct ID* id) Icon* BKE_icon_get(int icon_id) { - Icon* icon = 0; + Icon* icon = NULL; icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id)); if (!icon) { printf("BKE_icon_get: Internal error, no icon for icon ID: %d\n", icon_id); - return 0; + return NULL; } return icon; @@ -286,7 +287,7 @@ Icon* BKE_icon_get(int icon_id) void BKE_icon_set(int icon_id, struct Icon* icon) { - Icon* old_icon = 0; + Icon* old_icon = NULL; old_icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id)); @@ -304,6 +305,6 @@ void BKE_icon_delete(struct ID* id) if (!id->icon_id) return; /* no icon defined for library object */ - BLI_ghash_remove(gIcons, SET_INT_IN_POINTER(id->icon_id), 0, icon_free); + BLI_ghash_remove(gIcons, SET_INT_IN_POINTER(id->icon_id), NULL, icon_free); id->icon_id = 0; } diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index a6c7062e22b..6c8b5329711 100755 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -1,5 +1,5 @@ -/** - * $Id: idcode.c 31437 2010-08-18 07:14:10Z campbellbarton $ +/* + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -33,9 +33,11 @@ #include "DNA_ID.h" +#include "BKE_idcode.h" + typedef struct { unsigned short code; - char *name, *plural; + const char *name, *plural; int flags; #define IDTYPE_FLAGS_ISLINKABLE (1<<0) diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index a0df73d6c42..b3119f317a5 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -266,7 +266,7 @@ void IDP_FreeArray(IDProperty *prop) return newp; } -IDProperty *IDP_CopyArray(IDProperty *prop) +static IDProperty *IDP_CopyArray(IDProperty *prop) { IDProperty *newp = idp_generic_copy(prop); @@ -328,7 +328,7 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) return prop; } -IDProperty *IDP_CopyString(IDProperty *prop) +static IDProperty *IDP_CopyString(IDProperty *prop) { IDProperty *newp = idp_generic_copy(prop); @@ -341,7 +341,7 @@ IDProperty *IDP_CopyString(IDProperty *prop) } -void IDP_AssignString(IDProperty *prop, char *st, int maxlen) +void IDP_AssignString(IDProperty *prop, const char *st, int maxlen) { int stlen; @@ -356,7 +356,7 @@ void IDP_AssignString(IDProperty *prop, char *st, int maxlen) BLI_strncpy(prop->data.pointer, st, stlen); } -void IDP_ConcatStringC(IDProperty *prop, char *st) +void IDP_ConcatStringC(IDProperty *prop, const char *st) { int newlen; @@ -402,7 +402,7 @@ void IDP_UnlinkID(IDProperty *prop) /*-------- Group Functions -------*/ /*checks if a property with the same name as prop exists, and if so replaces it.*/ -IDProperty *IDP_CopyGroup(IDProperty *prop) +static IDProperty *IDP_CopyGroup(IDProperty *prop) { IDProperty *newp = idp_generic_copy(prop), *link; newp->len = prop->len; @@ -421,9 +421,7 @@ void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src) IDProperty *loop, *prop; for (prop=src->data.group.first; prop; prop=prop->next) { for (loop=dest->data.group.first; loop; loop=loop->next) { - if (BSTR_EQ(loop->name, prop->name)) { - int copy_done= 0; - + if (strcmp(loop->name, prop->name)==0) { if(prop->type==loop->type) { switch (prop->type) { @@ -431,11 +429,9 @@ void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src) case IDP_FLOAT: case IDP_DOUBLE: loop->data= prop->data; - copy_done= 1; break; case IDP_GROUP: IDP_SyncGroupValues(loop, prop); - copy_done= 1; break; default: { @@ -444,7 +440,6 @@ void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src) BLI_insertlinkafter(&dest->data.group, loop, copy); BLI_remlink(&dest->data.group, tmp); - loop = copy; IDP_FreeProperty(tmp); MEM_freeN(tmp); @@ -540,6 +535,12 @@ IDProperty *IDP_GetPropertyFromGroup(IDProperty *prop, const char *name) return (IDProperty *)BLI_findstring(&prop->data.group, name, offsetof(IDProperty, name)); } +IDProperty *IDP_GetPropertyTypeFromGroup(IDProperty *prop, const char *name, const char type) +{ + IDProperty *idprop= IDP_GetPropertyFromGroup(prop, name); + return (idprop && idprop->type == type) ? idprop : NULL; +} + typedef struct IDPIter { void *next; IDProperty *parent; @@ -702,7 +703,6 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, const char *name) case IDP_STRING: { char *st = val.str; - int stlen; prop = MEM_callocN(sizeof(IDProperty), "IDProperty string"); if (st == NULL) { @@ -710,10 +710,10 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, const char *name) prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS; prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/ } else { - stlen = strlen(st) + 1; - prop->data.pointer = MEM_callocN(stlen, "id property string 2"); + int stlen = strlen(st) + 1; + prop->data.pointer = MEM_mallocN(stlen, "id property string 2"); prop->len = prop->totallen = stlen; - strcpy(prop->data.pointer, st); + memcpy(prop->data.pointer, st, stlen); } break; } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 0e282aa6449..8a15f63243c 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -54,12 +54,14 @@ #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" +#include "DNA_object_types.h" #include "DNA_camera_types.h" #include "DNA_sequence_types.h" #include "DNA_userdef_types.h" #include "BLI_blenlib.h" #include "BLI_threads.h" +#include "BLI_utildefines.h" #include "BKE_bmfont.h" #include "BKE_global.h" @@ -69,8 +71,9 @@ #include "BKE_main.h" #include "BKE_packedFile.h" #include "BKE_scene.h" - -//XXX #include "BIF_editseq.h" +#include "BKE_node.h" +#include "BKE_sequencer.h" /* seq_foreground_frame_get() */ +#include "BKE_utildefines.h" #include "BLF_api.h" @@ -96,14 +99,14 @@ static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ { struct ImBuf * tbuf1, * tbuf2; - if (ibuf == 0) return; + if (ibuf == NULL) return; if (ibuf->flags & IB_fields) return; ibuf->flags |= IB_fields; if (ibuf->rect) { /* make copies */ - tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); - tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); + tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect); + tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect); ibuf->x *= 2; @@ -124,14 +127,14 @@ static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ { struct ImBuf * tbuf1, * tbuf2; - if (ibuf == 0) return; + if (ibuf == NULL) return; if (ibuf->flags & IB_fields) return; ibuf->flags |= IB_fields; if (ibuf->rect) { /* make copies */ - tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); - tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); + tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect); + tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect); ibuf->x *= 2; @@ -329,7 +332,7 @@ void BKE_image_merge(Image *dest, Image *source) /* otherwise creates new. */ /* does not load ibuf itself */ /* pass on optional frame for #name images */ -Image *BKE_add_image_file(const char *name, int frame) +Image *BKE_add_image_file(const char *name) { Image *ima; int file, len; @@ -337,7 +340,7 @@ Image *BKE_add_image_file(const char *name, int frame) char str[FILE_MAX], strtest[FILE_MAX]; BLI_strncpy(str, name, sizeof(str)); - BLI_path_abs(str, G.sce); + BLI_path_abs(str, G.main->name); /* exists? */ file= open(str, O_BINARY|O_RDONLY); @@ -348,7 +351,7 @@ Image *BKE_add_image_file(const char *name, int frame) for(ima= G.main->image.first; ima; ima= ima->id.next) { if(ima->source!=IMA_SRC_VIEWER && ima->source!=IMA_SRC_GENERATED) { BLI_strncpy(strtest, ima->name, sizeof(ima->name)); - BLI_path_abs(strtest, G.sce); + BLI_path_abs(strtest, G.main->name); if( strcmp(strtest, str)==0 ) { if(ima->anim==NULL || ima->id.us==0) { @@ -381,22 +384,22 @@ Image *BKE_add_image_file(const char *name, int frame) return ima; } -static ImBuf *add_ibuf_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) +static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) { ImBuf *ibuf; unsigned char *rect= NULL; float *rect_float= NULL; if (floatbuf) { - ibuf= IMB_allocImBuf(width, height, depth, IB_rectfloat, 0); + ibuf= IMB_allocImBuf(width, height, depth, IB_rectfloat); rect_float= (float*)ibuf->rect_float; } else { - ibuf= IMB_allocImBuf(width, height, depth, IB_rect, 0); + ibuf= IMB_allocImBuf(width, height, depth, IB_rect); rect= (unsigned char*)ibuf->rect; } - strcpy(ibuf->name, "//Untitled"); + BLI_strncpy(ibuf->name, name, sizeof(ibuf->name)); ibuf->userflags |= IB_BITMAPDIRTY; switch(uvtestgrid) { @@ -414,7 +417,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, int depth, int fl } /* adds new image block, creates ImBuf and initializes color */ -Image *BKE_add_image_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) +Image *BKE_add_image_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) { /* on save, type is changed to FILE in editsima.c */ Image *ima= image_alloc(name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST); @@ -510,7 +513,7 @@ static void tag_all_images_time() } #endif -void free_old_images() +void free_old_images(void) { Image *ima; static int lasttime = 0; @@ -523,6 +526,10 @@ void free_old_images() if (U.textimeout == 0 || ctime % U.texcollectrate || ctime == lasttime) return; + /* of course not! */ + if (G.rendering) + return; + lasttime = ctime; ima= G.main->image.first; @@ -595,7 +602,7 @@ void BKE_image_free_all_textures(void) { Tex *tex; Image *ima; - unsigned int totsize= 0; + /* unsigned int totsize= 0; */ for(ima= G.main->image.first; ima; ima= ima->id.next) ima->id.flag &= ~LIB_DOIT; @@ -607,13 +614,20 @@ void BKE_image_free_all_textures(void) for(ima= G.main->image.first; ima; ima= ima->id.next) { if(ima->ibufs.first && (ima->id.flag & LIB_DOIT)) { ImBuf *ibuf; + for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) { - if(ibuf->mipmap[0]) + /* escape when image is painted on */ + if(ibuf->userflags & IB_BITMAPDIRTY) + break; + + /* if(ibuf->mipmap[0]) totsize+= 1.33*ibuf->x*ibuf->y*4; else - totsize+= ibuf->x*ibuf->y*4; + totsize+= ibuf->x*ibuf->y*4;*/ + } - image_free_buffers(ima); + if(ibuf==NULL) + image_free_buffers(ima); } } /* printf("freed total %d MB\n", totsize/(1024*1024)); */ @@ -756,9 +770,9 @@ int BKE_imtype_is_movie(int imtype) return 0; } -void BKE_add_image_extension(char *string, int imtype) +int BKE_add_image_extension(char *string, int imtype) { - char *extension=""; + const char *extension= NULL; if(imtype== R_IRIS) { if(!BLI_testextensie(string, ".rgb")) @@ -829,7 +843,15 @@ void BKE_add_image_extension(char *string, int imtype) extension= ".jpg"; } - strcat(string, extension); + if(extension) { + /* prefer this in many cases to avoid .png.tga, but in certain cases it breaks */ + /* return BLI_replace_extension(string, FILE_MAX, extension); */ + strcat(string, extension); + return TRUE; + } + else { + return FALSE; + } } /* could allow access externally - 512 is for long names, 64 is for id names */ @@ -841,6 +863,7 @@ typedef struct StampData { char time[512]; char frame[512]; char camera[64]; + char cameralens[64]; char scene[64]; char strip[64]; char rendertime[64]; @@ -853,32 +876,23 @@ static void stampdata(Scene *scene, StampData *stamp_data, int do_prefix) time_t t; if (scene->r.stamp & R_STAMP_FILENAME) { - if (G.relbase_valid) { - if (do_prefix) sprintf(stamp_data->file, "File %s", G.sce); - else sprintf(stamp_data->file, "%s", G.sce); - } else { - if (do_prefix) strcpy(stamp_data->file, "File <untitled>"); - else strcpy(stamp_data->file, "<untitled>"); - } + BLI_snprintf(stamp_data->file, sizeof(stamp_data->file), do_prefix ? "File %s":"%s", G.relbase_valid ? G.main->name:"<untitled>"); } else { stamp_data->file[0] = '\0'; } if (scene->r.stamp & R_STAMP_NOTE) { /* Never do prefix for Note */ - sprintf(stamp_data->note, "%s", scene->r.stamp_udata); + BLI_snprintf(stamp_data->note, sizeof(stamp_data->note), "%s", scene->r.stamp_udata); } else { stamp_data->note[0] = '\0'; } if (scene->r.stamp & R_STAMP_DATE) { - - t = time (NULL); - tl = localtime (&t); - sprintf (text, "%04d/%02d/%02d %02d:%02d:%02d", tl->tm_year+1900, tl->tm_mon+1, tl->tm_mday, tl->tm_hour, tl->tm_min, tl->tm_sec); - - if (do_prefix) sprintf(stamp_data->date, "Date %s", text); - else sprintf(stamp_data->date, "%s", text); + t = time(NULL); + tl = localtime(&t); + BLI_snprintf(text, sizeof(text), "%04d/%02d/%02d %02d:%02d:%02d", tl->tm_year+1900, tl->tm_mon+1, tl->tm_mday, tl->tm_hour, tl->tm_min, tl->tm_sec); + BLI_snprintf(stamp_data->date, sizeof(stamp_data->date), do_prefix ? "Date %s":"%s", text); } else { stamp_data->date[0] = '\0'; } @@ -888,18 +902,17 @@ static void stampdata(Scene *scene, StampData *stamp_data, int do_prefix) if (name) strcpy(text, name); else strcpy(text, "<none>"); - - if (do_prefix) sprintf(stamp_data->marker, "Marker %s", text); - else sprintf(stamp_data->marker, "%s", text); + + BLI_snprintf(stamp_data->marker, sizeof(stamp_data->marker), do_prefix ? "Marker %s":"%s", text); } else { stamp_data->marker[0] = '\0'; } if (scene->r.stamp & R_STAMP_TIME) { - int h, m, s, f; - h= m= s= f= 0; - f = (int)(scene->r.cfra % scene->r.frs_sec); - s = (int)(scene->r.cfra / scene->r.frs_sec); + int f = (int)(scene->r.cfra % scene->r.frs_sec); + int s = (int)(scene->r.cfra / scene->r.frs_sec); + int h= 0; + int m= 0; if (s) { m = (int)(s / 60); @@ -912,50 +925,58 @@ static void stampdata(Scene *scene, StampData *stamp_data, int do_prefix) } if (scene->r.frs_sec < 100) - sprintf (text, "%02d:%02d:%02d.%02d", h, m, s, f); + BLI_snprintf(text, sizeof(text), "%02d:%02d:%02d.%02d", h, m, s, f); else - sprintf (text, "%02d:%02d:%02d.%03d", h, m, s, f); - - if (do_prefix) sprintf(stamp_data->time, "Time %s", text); - else sprintf(stamp_data->time, "%s", text); + BLI_snprintf(text, sizeof(text), "%02d:%02d:%02d.%03d", h, m, s, f); + + BLI_snprintf(stamp_data->time, sizeof(stamp_data->time), do_prefix ? "Time %s":"%s", text); } else { stamp_data->time[0] = '\0'; } if (scene->r.stamp & R_STAMP_FRAME) { char format[32]; - if (do_prefix) sprintf(format, "Frame %%0%di", 1 + (int) log10(scene->r.efra)); - else sprintf(format, "%%0%di", 1 + (int) log10(scene->r.efra)); - sprintf (stamp_data->frame, format, scene->r.cfra); + int digits= 1; + + if(scene->r.efra>9) + digits= 1 + (int) log10(scene->r.efra); + + BLI_snprintf(format, sizeof(format), do_prefix ? "Frame %%0%di":"%%0%di", digits); + BLI_snprintf (stamp_data->frame, sizeof(stamp_data->frame), format, scene->r.cfra); } else { stamp_data->frame[0] = '\0'; } if (scene->r.stamp & R_STAMP_CAMERA) { - if (scene->camera) strcpy(text, ((Camera *) scene->camera)->id.name+2); - else strcpy(text, "<none>"); - - if (do_prefix) sprintf(stamp_data->camera, "Camera %s", text); - else sprintf(stamp_data->camera, "%s", text); + BLI_snprintf(stamp_data->camera, sizeof(stamp_data->camera), do_prefix ? "Camera %s":"%s", scene->camera ? scene->camera->id.name+2 : "<none>"); } else { stamp_data->camera[0] = '\0'; } + if (scene->r.stamp & R_STAMP_CAMERALENS) { + if (scene->camera && scene->camera->type == OB_CAMERA) { + BLI_snprintf(text, sizeof(text), "%.2f", ((Camera *)scene->camera->data)->lens); + } + else strcpy(text, "<none>"); + + BLI_snprintf(stamp_data->cameralens, sizeof(stamp_data->cameralens), do_prefix ? "Lens %s":"%s", text); + } else { + stamp_data->cameralens[0] = '\0'; + } + if (scene->r.stamp & R_STAMP_SCENE) { - if (do_prefix) sprintf(stamp_data->scene, "Scene %s", scene->id.name+2); - else sprintf(stamp_data->scene, "%s", scene->id.name+2); + BLI_snprintf(stamp_data->scene, sizeof(stamp_data->scene), do_prefix ? "Scene %s":"%s", scene->id.name+2); } else { stamp_data->scene[0] = '\0'; } if (scene->r.stamp & R_STAMP_SEQSTRIP) { - Sequence *seq= NULL; //XXX = get_foreground_frame_seq(scene->r.cfra); + Sequence *seq= seq_foreground_frame_get(scene, scene->r.cfra); if (seq) strcpy(text, seq->name+2); else strcpy(text, "<none>"); - - if (do_prefix) sprintf(stamp_data->strip, "Strip %s", text); - else sprintf(stamp_data->strip, "%s", text); + + BLI_snprintf(stamp_data->strip, sizeof(stamp_data->strip), do_prefix ? "Strip %s":"%s", text); } else { stamp_data->strip[0] = '\0'; } @@ -967,37 +988,20 @@ static void stampdata(Scene *scene, StampData *stamp_data, int do_prefix) if (stats && (scene->r.stamp & R_STAMP_RENDERTIME)) { BLI_timestr(stats->lastframetime, text); - if (do_prefix) sprintf(stamp_data->rendertime, "RenderTime %s", text); - else sprintf(stamp_data->rendertime, "%s", text); + BLI_snprintf(stamp_data->rendertime, sizeof(stamp_data->rendertime), do_prefix ? "RenderTime %s":"%s", text); } else { stamp_data->rendertime[0] = '\0'; } } } -// XXX - Bad level call. -extern int datatoc_bmonofont_ttf_size; -extern char datatoc_bmonofont_ttf[]; - -// XXX - copied from text_font_begin ! Change all the BLF_* here -static int mono= -1; - -int stamp_font_begin(int size) -{ - if (mono == -1) - mono= BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); - - BLF_aspect(mono, 1.0); - BLF_size(mono, size, 72); - return(mono); // XXX This is for image_gen.c!! -} - void BKE_stamp_buf(Scene *scene, unsigned char *rect, float *rectf, int width, int height, int channels) { struct StampData stamp_data; float w, h, pad; int x, y; float h_fixed; + const int mono= blf_mono_font_render; // XXX if (!rect && !rectf) return; @@ -1008,8 +1012,9 @@ void BKE_stamp_buf(Scene *scene, unsigned char *rect, float *rectf, int width, i if(scene->r.stamp_font_id < 8) scene->r.stamp_font_id= 12; - stamp_font_begin(scene->r.stamp_font_id); - + /* set before return */ + BLF_size(mono, scene->r.stamp_font_id, 72); + BLF_buffer(mono, rectf, rect, width, height, channels); BLF_buffer_col(mono, scene->r.fg_stamp[0], scene->r.fg_stamp[1], scene->r.fg_stamp[2], 1.0); pad= BLF_width(mono, "--"); @@ -1137,6 +1142,18 @@ void BKE_stamp_buf(Scene *scene, unsigned char *rect, float *rectf, int width, i buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y, x+w+2, y+h+2); BLF_position(mono, x, y+3, 0.0); BLF_draw_buffer(mono, stamp_data.camera); + + /* space width. */ + x += w + pad; + } + + if (stamp_data.cameralens[0]) { + BLF_width_and_height(mono, stamp_data.cameralens, &w, &h); h= h_fixed; + + /* extra space for background. */ + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x, y, x+w+2, y+h+2); + BLF_position(mono, x, y+3, 0.0); + BLF_draw_buffer(mono, stamp_data.cameralens); } if (stamp_data.scene[0]) { @@ -1154,7 +1171,7 @@ void BKE_stamp_buf(Scene *scene, unsigned char *rect, float *rectf, int width, i } if (stamp_data.strip[0]) { - BLF_width_and_height(mono, stamp_data.scene, &w, &h); h= h_fixed; + BLF_width_and_height(mono, stamp_data.strip, &w, &h); h= h_fixed; /* Top right corner, with an extra space because blenfont is too strict! */ x= width - w - pad; @@ -1187,15 +1204,40 @@ void BKE_stamp_info(Scene *scene, struct ImBuf *ibuf) if (stamp_data.time[0]) IMB_metadata_change_field (ibuf, "Time", stamp_data.time); if (stamp_data.frame[0]) IMB_metadata_change_field (ibuf, "Frame", stamp_data.frame); if (stamp_data.camera[0]) IMB_metadata_change_field (ibuf, "Camera", stamp_data.camera); + if (stamp_data.cameralens[0]) IMB_metadata_change_field (ibuf, "Lens", stamp_data.cameralens); if (stamp_data.scene[0]) IMB_metadata_change_field (ibuf, "Scene", stamp_data.scene); if (stamp_data.strip[0]) IMB_metadata_change_field (ibuf, "Strip", stamp_data.strip); if (stamp_data.rendertime[0]) IMB_metadata_change_field (ibuf, "RenderTime", stamp_data.rendertime); } -int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimtype, int quality) +int BKE_alphatest_ibuf(ImBuf *ibuf) +{ + int tot; + if(ibuf->rect_float) { + float *buf= ibuf->rect_float; + for(tot= ibuf->x * ibuf->y; tot--; buf+=4) { + if(buf[3] < 1.0f) { + return TRUE; + } + } + } + else if (ibuf->rect) { + unsigned char *buf= (unsigned char *)ibuf->rect; + for(tot= ibuf->x * ibuf->y; tot--; buf+=4) { + if(buf[3] != 255) { + return TRUE; + } + } + } + + return FALSE; +} + +int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, const char *name, int imtype, int subimtype, int quality) { int ok; - + (void)subimtype; /* quies unused warnings */ + if(imtype==0) { /* pass */ } @@ -1203,7 +1245,7 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt ibuf->ftype= IMAGIC; } #ifdef WITH_HDR - else if ((imtype==R_RADHDR)) { + else if (imtype==R_RADHDR) { ibuf->ftype= RADHDR; } #endif @@ -1215,11 +1257,11 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt } #ifdef WITH_DDS - else if ((imtype==R_DDS)) { + else if (imtype==R_DDS) { ibuf->ftype= DDS; } #endif - else if ((imtype==R_BMP)) { + else if (imtype==R_BMP) { ibuf->ftype= BMP; } #ifdef WITH_TIFF @@ -1299,12 +1341,14 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt } -void BKE_makepicstring(char *string, char *base, int frame, int imtype, int use_ext) +void BKE_makepicstring(char *string, const char *base, int frame, int imtype, const short use_ext, const short use_frames) { if (string==NULL) return; BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */ - BLI_path_abs(string, G.sce); - BLI_path_frame(string, frame, 4); + BLI_path_abs(string, G.main->name); + + if(use_frames) + BLI_path_frame(string, frame, 4); if(use_ext) BKE_add_image_extension(string, imtype); @@ -1318,7 +1362,7 @@ struct anim *openanim(char *name, int flags) struct ImBuf *ibuf; anim = IMB_open_anim(name, flags); - if (anim == NULL) return(0); + if (anim == NULL) return NULL; ibuf = IMB_anim_absolute(anim, 0); if (ibuf == NULL) { @@ -1327,7 +1371,7 @@ struct anim *openanim(char *name, int flags) else printf("anim file doesn't exist: %s\n", name); IMB_free_anim(anim); - return(0); + return NULL; } IMB_freeImBuf(ibuf); @@ -1408,7 +1452,9 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) } } - image_free_buffers(ima); + /* force reload on first use, but not for multilayer, that makes nodes and buttons in ui drawing fail */ + if(ima->type!=IMA_TYPE_MULTILAYER) + image_free_buffers(ima); ima->ok= 1; if(iuser) @@ -1447,6 +1493,17 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) } break; } + + /* dont use notifiers because they are not 100% sure to succseed + * this also makes sure all scenes are accounted for. */ + { + Scene *scene; + for(scene= G.main->scene.first; scene; scene= scene->id.next) { + if(scene->nodetree) { + NodeTagIDChanged(scene->nodetree, &ima->id); + } + } + } } /* if layer or pass changes, we need an index for the imbufs list */ @@ -1549,15 +1606,10 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) /* common stuff to do with images after loading */ static void image_initialize_after_load(Image *ima, ImBuf *ibuf) { - - /* preview is NULL when it has never been used as an icon before */ if(G.background==0 && ima->preview==NULL) BKE_icon_changed(BKE_icon_getid(&ima->id)); - - /* stringcodes also in ibuf, ibuf->name is used to retrieve original (buttons) */ - BLI_strncpy(ibuf->name, ima->name, FILE_MAX); - + /* fields */ if (ima->flag & IMA_FIELDS) { if(ima->flag & IMA_STD_FIELD) de_interlace_st(ibuf); @@ -1582,15 +1634,14 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) ima->tpageflag |= IMA_TPAGE_REFRESH; ima->lastframe= frame; - - BLI_stringdec(ima->name, head, tail, &numlen); - BLI_stringenc(ima->name, head, tail, numlen, frame); BLI_strncpy(name, ima->name, sizeof(name)); - + BLI_stringdec(name, head, tail, &numlen); + BLI_stringenc(name, head, tail, numlen, frame); + if(ima->id.lib) BLI_path_abs(name, ima->id.lib->filepath); else - BLI_path_abs(name, G.sce); + BLI_path_abs(name, G.main->name); flag= IB_rect|IB_multilayer; if(ima->flag & IMA_DO_PREMUL) @@ -1662,11 +1713,12 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f if(rpass) { // printf("load from pass %s\n", rpass->name); /* since we free render results, we copy the rect */ - ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0, 0); + ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0); ibuf->rect_float= MEM_dupallocN(rpass->rect); ibuf->flags |= IB_rectfloat; ibuf->mall= IB_rectfloat; ibuf->channels= rpass->channels; + ibuf->profile = IB_PROFILE_LINEAR_RGB; image_initialize_after_load(ima, ibuf); image_assign_ibuf(ima, ibuf, iuser?iuser->multi_index:0, frame); @@ -1697,7 +1749,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) if(ima->id.lib) BLI_path_abs(str, ima->id.lib->filepath); else - BLI_path_abs(str, G.sce); + BLI_path_abs(str, G.main->name); ima->anim = openanim(str, IB_rect); @@ -1730,8 +1782,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) return ibuf; } -/* cfra used for # code, Image can only have this # for all its users - * warning, 'iuser' can be NULL */ +/* warning, 'iuser' can be NULL */ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) { struct ImBuf *ibuf; @@ -1758,9 +1809,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) if(ima->id.lib) BLI_path_abs(str, ima->id.lib->filepath); else - BLI_path_abs(str, G.sce); - - BLI_path_frame(str, cfra, 0); + BLI_path_abs(str, G.main->name); /* read ibuf */ ibuf = IMB_loadiffname(str, flag); @@ -1813,7 +1862,7 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) RenderPass *rpass= BKE_image_multilayer_index(ima->rr, iuser); if(rpass) { - ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0, 0); + ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0); image_initialize_after_load(ima, ibuf); @@ -1920,7 +1969,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ /* make ibuf if needed, and initialize it */ if(ibuf==NULL) { - ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, 0, 0); + ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, 0); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); } @@ -1952,6 +2001,9 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ ibuf->flags &= ~IB_zbuffloat; } + /* since its possible to access the buffer from the image directly, set the profile [#25073] */ + ibuf->profile= (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE; + ibuf->dither= dither; ima->ok= IMA_OK_LOADED; @@ -1981,11 +2033,6 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame /* XXX temp stuff? */ if(ima->lastframe != frame) { ima->tpageflag |= IMA_TPAGE_REFRESH; - if(ibuf) { - /* without this the image name only updates - * on first load which is quite confusing */ - BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name)); - } } ima->lastframe = frame; } @@ -2005,14 +2052,9 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); } else if(ima->source == IMA_SRC_VIEWER) { - if(ima->type==IMA_TYPE_R_RESULT) { - /* always verify entirely, not that this shouldn't happen - * during render anyway */ - } - else if(ima->type==IMA_TYPE_COMPOSITE) { - frame= iuser?iuser->framenr:0; - ibuf= image_get_ibuf(ima, 0, frame); - } + /* always verify entirely, not that this shouldn't happen + * as part of texture sampling in rendering anyway, so not + * a big bottleneck */ } *frame_r = frame; @@ -2093,9 +2135,6 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ ibuf= image_load_sequence_multilayer(ima, iuser, frame); } - - if(ibuf) - BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name)); } else if(ima->source==IMA_SRC_FILE) { @@ -2129,10 +2168,16 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) BLI_lock_thread(LOCK_VIEWER); *lock_r= ima; - /* Composite Viewer, all handled in compositor */ - /* fake ibuf, will be filled in compositor */ - ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0); - image_assign_ibuf(ima, ibuf, 0, frame); + /* XXX anim play for viewer nodes not yet supported */ + frame= 0; // XXX iuser?iuser->framenr:0; + ibuf= image_get_ibuf(ima, 0, frame); + + if(!ibuf) { + /* Composite Viewer, all handled in compositor */ + /* fake ibuf, will be filled in compositor */ + ibuf= IMB_allocImBuf(256, 256, 32, IB_rect); + image_assign_ibuf(ima, ibuf, 0, frame); + } } } } @@ -2141,10 +2186,7 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) BLI_unlock_thread(LOCK_IMAGE); } - /* we assuming that if it is not rendering, it's also not multithreaded - * (a somewhat weak assumption) */ - if(G.rendering==0) - tag_image_time(ima); + tag_image_time(ima); return ibuf; } @@ -2161,6 +2203,7 @@ void BKE_image_release_ibuf(Image *ima, void *lock) } } +/* warning, this can allocate generated images */ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) { return BKE_image_acquire_ibuf(ima, iuser, NULL); @@ -2168,7 +2211,7 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr) { - int imanr, len; + int len; /* here (+fie_ima/2-1) makes sure that division happens correctly */ len= (iuser->fie_ima*iuser->frames)/2; @@ -2177,8 +2220,9 @@ void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr) iuser->framenr= 0; } else { + int imanr; cfra= cfra - iuser->sfra+1; - + /* cyclic */ if(iuser->cycl) { cfra= ( (cfra) % len ); @@ -2186,7 +2230,7 @@ void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr) if(cfra==0) cfra= len; } - if(cfra<1) cfra= 1; + if(cfra<0) cfra= 0; else if(cfra>len) cfra= len; /* convert current frame to current field */ diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c index 9248ce69280..c21e347d6d8 100644 --- a/source/blender/blenkernel/intern/image_gen.c +++ b/source/blender/blenkernel/intern/image_gen.c @@ -25,6 +25,8 @@ #include <math.h> #include <stdlib.h> + +#include "BKE_image.h" #include "BLI_math_color.h" #include "BLF_api.h" @@ -298,16 +300,16 @@ static void checker_board_grid_fill(unsigned char *rect, float *rect_float, int } /* defined in image.c */ -extern int stamp_font_begin(int size); static void checker_board_text(unsigned char *rect, float *rect_float, int width, int height, int step, int outline) { - int x, y, mono; + int x, y; int pen_x, pen_y; char text[3]= {'A', '1', '\0'}; + const int mono= blf_mono_font; + + BLF_size(mono, 54, 72); /* hard coded size! */ - /* hard coded size! */ - mono= stamp_font_begin(54); BLF_buffer(mono, rect_float, rect, width, height, 4); for(y= 0; y < height; y+=step) diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 158f964a846..207c667f335 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1,31 +1,31 @@ -/* implicit.c -* -* -* ***** 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) Blender Foundation -* All rights reserved. -* -* The Original Code is: all of this file. -* -* Contributor(s): none yet. -* -* ***** END GPL LICENSE BLOCK ***** -*/ +/* + * $Id$ + * + * ***** 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) Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ #include "MEM_guardedalloc.h" @@ -37,12 +37,13 @@ #include "BLI_threads.h" #include "BLI_math.h" #include "BLI_linklist.h" +#include "BLI_utildefines.h" #include "BKE_cloth.h" #include "BKE_collision.h" #include "BKE_effect.h" #include "BKE_global.h" -#include "BKE_utildefines.h" + #define CLOTH_OPENMP_LIMIT 25 @@ -63,7 +64,7 @@ static void itend(void) { QueryPerformanceCounter(&_itend); } -double itval() +double itval(void) { return ((double)_itend.QuadPart - (double)_itstart.QuadPart)/((double)ifreq.QuadPart); @@ -85,7 +86,7 @@ static void itend(void) { gettimeofday(&_itend,&itz); } -double itval() +double itval(void) { double t1, t2; t1 = (double)_itstart.tv_sec + (double)_itstart.tv_usec/(1000*1000); @@ -726,7 +727,7 @@ typedef struct Implicit_Data fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI, *M; } Implicit_Data; -int implicit_init (Object *ob, ClothModifierData *clmd) +int implicit_init (Object *UNUSED(ob), ClothModifierData *clmd) { unsigned int i = 0; unsigned int pinned = 0; @@ -1218,7 +1219,7 @@ DO_INLINE void dfdx_damp(float to[3][3], float dir[3],float length,const float } -DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float time) +DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *UNUSED(lF), lfVector *X, lfVector *V, fmatrix3x3 *UNUSED(dFdV), fmatrix3x3 *UNUSED(dFdX), float time) { Cloth *cloth = clmd->clothObject; ClothVertex *verts = cloth->verts; @@ -1228,7 +1229,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float vel[3]; float k = 0.0f; float L = s->restlen; - float cb = clmd->sim_parms->structural; + float cb; /* = clmd->sim_parms->structural; */ /*UNUSED*/ float nullf[3] = {0,0,0}; float stretch_force[3] = {0,0,0}; @@ -1316,8 +1317,9 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, VECSUB(extent, X[s->ij], tvect); - dot = INPR(extent, extent); - length = sqrt(dot); + // SEE MSG BELOW (these are UNUSED) + // dot = INPR(extent, extent); + // length = sqrt(dot); k = clmd->sim_parms->goalspring; @@ -1353,7 +1355,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, } } -DO_INLINE void cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) +DO_INLINE void cloth_apply_spring_force(ClothModifierData *UNUSED(clmd), ClothSpring *s, lfVector *lF, lfVector *UNUSED(X), lfVector *UNUSED(V), fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) { if(s->flags & CLOTH_SPRING_FLAG_NEEDED) { @@ -1425,7 +1427,7 @@ typedef struct HairGridVert { by Lena Petrovic, Mark Henne and John Anderson * Pixar Technical Memo #06-08, Pixar Animation Studios */ -static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, int numverts) +static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, unsigned int numverts) { /* TODO: This is an initial implementation and should be made much better in due time. * What should at least be implemented is a grid size parameter and a smoothing kernel @@ -1441,10 +1443,10 @@ static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVec /* 2.0f is an experimental value that seems to give good results */ float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth; float collfac = 2.0f * clmd->sim_parms->collider_friction; - int v = 0; - int i = 0; - int j = 0; - int k = 0; + unsigned int v = 0; + unsigned int i = 0; + int j = 0; + int k = 0; INIT_MINMAX(gmin, gmax); @@ -1555,20 +1557,22 @@ static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVec free_collider_cache(&colliders); } -static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M) +static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M) { /* Collect forces and derivatives: F,dFdX,dFdV */ Cloth *cloth = clmd->clothObject; - int i = 0; + unsigned int i = 0; float spring_air = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */ float gravity[3] = {0.0f, 0.0f, 0.0f}; - float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}}; + float tm2[3][3] = {{0}}; MFace *mfaces = cloth->mfaces; unsigned int numverts = cloth->numverts; - LinkNode *search = cloth->springs; + LinkNode *search; lfVector *winvec; EffectedPoint epoint; + tm2[0][0]= tm2[1][1]= tm2[2][2]= -spring_air; + /* global acceleration (gravitation) */ if(clmd->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { VECCOPY(gravity, clmd->scene->physics_settings.gravity); @@ -1708,7 +1712,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, // printf("\n"); } -static void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *M, fmatrix3x3 *bigI) +static void simulate_implicit_euler(lfVector *Vnew, lfVector *UNUSED(lX), lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *UNUSED(P), fmatrix3x3 *UNUSED(Pinv), fmatrix3x3 *M, fmatrix3x3 *UNUSED(bigI)) { unsigned int numverts = dFdV[0].vcount; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index a24f37bf73a..329058b3115 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -59,9 +59,10 @@ #include "BLI_math.h" /* windows needs for M_PI */ #include "BLI_blenlib.h" #include "BLI_dynstr.h" +#include "BLI_utildefines.h" -#include "BKE_utildefines.h" +#include "BKE_ipo.h" #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_fcurve.h" @@ -102,7 +103,7 @@ void free_ipo (Ipo *ipo) /* Mapping Table for bitflag <-> RNA path */ typedef struct AdrBit2Path { int bit; - char *path; + const char *path; int array_index; } AdrBit2Path; @@ -111,27 +112,26 @@ typedef struct AdrBit2Path { /* Object layers */ static AdrBit2Path ob_layer_bits[]= { - {(1<<0), "layer", 0}, - {(1<<1), "layer", 1}, - {(1<<2), "layer", 2}, - {(1<<3), "layer", 3}, - {(1<<4), "layer", 4}, - {(1<<5), "layer", 5}, - {(1<<6), "layer", 6}, - {(1<<7), "layer", 7}, - {(1<<8), "layer", 8}, - {(1<<9), "layer", 9}, - {(1<<10), "layer", 10}, - {(1<<11), "layer", 11}, - {(1<<12), "layer", 12}, - {(1<<13), "layer", 13}, - {(1<<14), "layer", 14}, - {(1<<15), "layer", 15}, - {(1<<16), "layer", 16}, - {(1<<17), "layer", 17}, - {(1<<18), "layer", 18}, - {(1<<19), "layer", 19}, - {(1<<20), "layer", 20} + {(1<<0), "layers", 0}, + {(1<<1), "layers", 1}, + {(1<<2), "layers", 2}, + {(1<<3), "layers", 3}, + {(1<<4), "layers", 4}, + {(1<<5), "layers", 5}, + {(1<<6), "layers", 6}, + {(1<<7), "layers", 7}, + {(1<<8), "layers", 8}, + {(1<<9), "layers", 9}, + {(1<<10), "layers", 10}, + {(1<<11), "layers", 11}, + {(1<<12), "layers", 12}, + {(1<<13), "layers", 13}, + {(1<<14), "layers", 14}, + {(1<<15), "layers", 15}, + {(1<<16), "layers", 16}, + {(1<<17), "layers", 17}, + {(1<<18), "layers", 18}, + {(1<<19), "layers", 19} }; /* Material mode */ @@ -172,7 +172,7 @@ static AdrBit2Path *adrcode_bitmaps_to_paths (int blocktype, int adrcode, int *t /* ADRCODE to RNA-Path Conversion Code - Standard */ /* Object types */ -static char *ob_adrcodes_to_paths (int adrcode, int *array_index) +static const char *ob_adrcodes_to_paths (int adrcode, int *array_index) { /* set array index like this in-case nothing sets it correctly */ *array_index= 0; @@ -253,7 +253,7 @@ static char *ob_adrcodes_to_paths (int adrcode, int *array_index) /* PoseChannel types * NOTE: pchan name comes from 'actname' added earlier... */ -static char *pchan_adrcodes_to_paths (int adrcode, int *array_index) +static const char *pchan_adrcodes_to_paths (int adrcode, int *array_index) { /* set array index like this in-case nothing sets it correctly */ *array_index= 0; @@ -297,7 +297,7 @@ static char *pchan_adrcodes_to_paths (int adrcode, int *array_index) } /* Constraint types */ -static char *constraint_adrcodes_to_paths (int adrcode, int *array_index) +static const char *constraint_adrcodes_to_paths (int adrcode, int *array_index) { /* set array index like this in-case nothing sets it correctly */ *array_index= 0; @@ -315,9 +315,9 @@ static char *constraint_adrcodes_to_paths (int adrcode, int *array_index) /* ShapeKey types * NOTE: as we don't have access to the keyblock where the data comes from (for now), - * we'll just use numerical indicies for now... + * we'll just use numerical indices for now... */ -static char *shapekey_adrcodes_to_paths (int adrcode, int *array_index) +static char *shapekey_adrcodes_to_paths (int adrcode, int *UNUSED(array_index)) { static char buf[128]; @@ -331,9 +331,9 @@ static char *shapekey_adrcodes_to_paths (int adrcode, int *array_index) } /* MTex (Texture Slot) types */ -static char *mtex_adrcodes_to_paths (int adrcode, int *array_index) +static const char *mtex_adrcodes_to_paths (int adrcode, int *UNUSED(array_index)) { - char *base=NULL, *prop=NULL; + const char *base=NULL, *prop=NULL; static char buf[128]; /* base part of path */ @@ -401,7 +401,7 @@ static char *mtex_adrcodes_to_paths (int adrcode, int *array_index) } /* Texture types */ -static char *texture_adrcodes_to_paths (int adrcode, int *array_index) +static const char *texture_adrcodes_to_paths (int adrcode, int *array_index) { /* set array index like this in-case nothing sets it correctly */ *array_index= 0; @@ -481,7 +481,7 @@ static char *texture_adrcodes_to_paths (int adrcode, int *array_index) } /* Material Types */ -static char *material_adrcodes_to_paths (int adrcode, int *array_index) +static const char *material_adrcodes_to_paths (int adrcode, int *array_index) { /* set array index like this in-case nothing sets it correctly */ *array_index= 0; @@ -565,7 +565,7 @@ static char *material_adrcodes_to_paths (int adrcode, int *array_index) } /* Camera Types */ -static char *camera_adrcodes_to_paths (int adrcode, int *array_index) +static const char *camera_adrcodes_to_paths (int adrcode, int *array_index) { /* set array index like this in-case nothing sets it correctly */ *array_index= 0; @@ -605,7 +605,7 @@ static char *camera_adrcodes_to_paths (int adrcode, int *array_index) } /* Lamp Types */ -static char *lamp_adrcodes_to_paths (int adrcode, int *array_index) +static const char *lamp_adrcodes_to_paths (int adrcode, int *array_index) { /* set array index like this in-case nothing sets it correctly */ *array_index= 0; @@ -647,7 +647,7 @@ static char *lamp_adrcodes_to_paths (int adrcode, int *array_index) } /* Sound Types */ -static char *sound_adrcodes_to_paths (int adrcode, int *array_index) +static const char *sound_adrcodes_to_paths (int adrcode, int *array_index) { /* set array index like this in-case nothing sets it correctly */ *array_index= 0; @@ -670,7 +670,7 @@ static char *sound_adrcodes_to_paths (int adrcode, int *array_index) } /* World Types */ -static char *world_adrcodes_to_paths (int adrcode, int *array_index) +static const char *world_adrcodes_to_paths (int adrcode, int *array_index) { /* set array index like this in-case nothing sets it correctly */ *array_index= 0; @@ -709,6 +709,11 @@ static char *world_adrcodes_to_paths (int adrcode, int *array_index) *array_index= 1; return "stars.color"; case WO_STAR_B: *array_index= 2; return "stars.color"; */ + case WO_STAR_R: + case WO_STAR_G: + case WO_STAR_B: + printf("WARNING: WO_STAR_R/G/B deprecated\n"); + return NULL; case WO_STARDIST: return "stars.min_distance"; @@ -723,7 +728,7 @@ static char *world_adrcodes_to_paths (int adrcode, int *array_index) } /* Particle Types */ -static char *particle_adrcodes_to_paths (int adrcode, int *array_index) +static const char *particle_adrcodes_to_paths (int adrcode, int *array_index) { /* set array index like this in-case nothing sets it correctly */ *array_index= 0; @@ -798,10 +803,11 @@ static char *particle_adrcodes_to_paths (int adrcode, int *array_index) * - array_index - index in property's array (if applicable) to use * - return - the allocated path... */ -static char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], Sequence * seq, int *array_index) +static char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], Sequence *seq, int *array_index) { DynStr *path= BLI_dynstr_new(); - char *propname=NULL, *rpath=NULL; + const char *propname=NULL; + char *rpath=NULL; char buf[512]; int dummy_index= 0; @@ -913,8 +919,17 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co sprintf(buf, "pose.bones[\"%s\"].constraints[\"%s\"]", actname, constname); } else if (actname && actname[0]) { - /* Pose-Channel */ - sprintf(buf, "pose.bones[\"%s\"]", actname); + if ((blocktype == ID_OB) && strcmp(actname, "Object")==0) { + /* Actionified "Object" IPO's... no extra path stuff needed */ + } + else if ((blocktype == ID_KE) && strcmp(actname, "Shape")==0) { + /* Actionified "Shape" IPO's - these are forced onto object level via the action container there... */ + strcpy(buf, "data.shape_keys"); + } + else { + /* Pose-Channel */ + sprintf(buf, "pose.bones[\"%s\"]", actname); + } } else if (constname && constname[0]) { /* Constraint in Object */ @@ -922,8 +937,7 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co } else if (seq) { /* Sequence names in Scene */ - sprintf(buf, "sequence_editor.sequences_all[\"%s\"]", - seq->name+2); + sprintf(buf, "sequence_editor.sequences_all[\"%s\"]", seq->name+2); } else strcpy(buf, ""); /* empty string */ @@ -1017,13 +1031,13 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver) dtar= &dvar->targets[0]; dtar->id= (ID *)idriver->ob; if (idriver->name[0]) - BLI_strncpy(dtar->pchan_name, idriver->name, 32); + BLI_strncpy(dtar->pchan_name, idriver->name, sizeof(dtar->pchan_name)); /* second bone target (name was stored in same var as the first one) */ dtar= &dvar->targets[1]; dtar->id= (ID *)idriver->ob; if (idriver->name[0]) // xxx... for safety - BLI_strncpy(dtar->pchan_name, idriver->name+DRIVER_NAME_OFFS, 32); + BLI_strncpy(dtar->pchan_name, idriver->name+DRIVER_NAME_OFFS, sizeof(dtar->pchan_name)); } else { /* only a single variable, of type 'transform channel' */ @@ -1034,7 +1048,7 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver) dtar= &dvar->targets[0]; dtar->id= (ID *)idriver->ob; if (idriver->name[0]) - BLI_strncpy(dtar->pchan_name, idriver->name, 32); + BLI_strncpy(dtar->pchan_name, idriver->name, sizeof(dtar->pchan_name)); dtar->transChan= adrcode_to_dtar_transchan(idriver->adrcode); dtar->flag |= DTAR_FLAG_LOCALSPACE; /* old drivers took local space */ } @@ -1123,7 +1137,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve * { AdrBit2Path *abp; FCurve *fcu; - int i=0, totbits; + int totbits; /* allocate memory for a new F-Curve */ fcu= MEM_callocN(sizeof(FCurve), "FCurve"); @@ -1188,6 +1202,8 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve * * 3) filter the keyframes for the flag of interest */ for (b=0; b < totbits; b++, abp++) { + unsigned int i=0; + /* make a copy of existing base-data if not the last curve */ if (b < (totbits-1)) fcurve= copy_fcurve(fcu); @@ -1195,7 +1211,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve * fcurve= fcu; /* set path */ - fcurve->rna_path= BLI_strdupn(abp->path, strlen(abp->path)); + fcurve->rna_path= BLI_strdup(abp->path); fcurve->array_index= abp->array_index; /* convert keyframes @@ -1211,7 +1227,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve * fcurve->bezt= MEM_callocN(sizeof(BezTriple)*fcurve->totvert, "BezTriples"); /* loop through copying all BezTriples individually, as we need to modify a few things */ - for (dst=fcurve->bezt, src=icu->bezt; i < fcurve->totvert; i++, dst++, src++) { + for (dst=fcurve->bezt, src=icu->bezt, i=0; i < fcurve->totvert; i++, dst++, src++) { /* firstly, copy BezTriple data */ *dst= *src; @@ -1239,6 +1255,8 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve * } } else { + unsigned int i=0; + /* get rna-path * - we will need to set the 'disabled' flag if no path is able to be made (for now) */ @@ -1259,7 +1277,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve * fcu->bezt= MEM_callocN(sizeof(BezTriple)*fcu->totvert, "BezTriples"); /* loop through copying all BezTriples individually, as we need to modify a few things */ - for (dst=fcu->bezt, src=icu->bezt; i < fcu->totvert; i++, dst++, src++) { + for (dst=fcu->bezt, src=icu->bezt, i=0; i < fcu->totvert; i++, dst++, src++) { /* firstly, copy BezTriple data */ *dst= *src; @@ -1301,13 +1319,14 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve * /* correct times for rotation drivers * - need to go from degrees to radians... * - there's only really 1 target to worry about + * - were also degrees/10 */ if (fcu->driver && fcu->driver->variables.first) { DriverVar *dvar= fcu->driver->variables.first; DriverTarget *dtar= &dvar->targets[0]; if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) { - const float fac= (float)M_PI / 180.0f; + const float fac= (float)M_PI / 18.0f; dst->vec[0][0] *= fac; dst->vec[1][0] *= fac; @@ -1315,20 +1334,17 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve * } } - /* correct values for sequencer curves, - that were not locked to frame */ - - if (seq && - (seq->flag & SEQ_IPO_FRAME_LOCKED) == 0) { + /* correct values for sequencer curves, that were not locked to frame */ + if (seq && (seq->flag & SEQ_IPO_FRAME_LOCKED) == 0) { double mul= (seq->enddisp-seq->startdisp)/100.0f; double offset= seq->startdisp; dst->vec[0][0] *= mul; dst->vec[0][0] += offset; - + dst->vec[1][0] *= mul; dst->vec[1][0] += offset; - + dst->vec[2][0] *= mul; dst->vec[2][0] += offset; } @@ -1475,7 +1491,7 @@ static void action_to_animato (ID *id, bAction *act, ListBase *groups, ListBase * This assumes that AnimData has been added already. Separation of drivers * from animation data is accomplished here too... */ -static void ipo_to_animdata (ID *id, Ipo *ipo, char actname[], char constname[], Sequence * seq) +static void ipo_to_animdata (ID *id, Ipo *ipo, char actname[], char constname[], Sequence *seq) { AnimData *adt= BKE_animdata_from_id(id); ListBase anim = {NULL, NULL}; @@ -1506,19 +1522,23 @@ static void ipo_to_animdata (ID *id, Ipo *ipo, char actname[], char constname[], if (G.f & G_DEBUG) printf("\thas anim \n"); /* try to get action */ if (adt->action == NULL) { - adt->action= add_empty_action("ConvData_Action"); // XXX we need a better name for this - if (G.f & G_DEBUG) printf("\t\tadded new action \n"); + char nameBuf[MAX_ID_NAME]; + + BLI_snprintf(nameBuf, sizeof(nameBuf), "CDA:%s", ipo->id.name+2); + + adt->action= add_empty_action(nameBuf); + if (G.f & G_DEBUG) printf("\t\tadded new action - '%s' \n", nameBuf); } /* add F-Curves to action */ - addlisttolist(&adt->action->curves, &anim); + BLI_movelisttolist(&adt->action->curves, &anim); } /* deal with drivers */ if (drivers.first) { if (G.f & G_DEBUG) printf("\thas drivers \n"); /* add drivers to end of driver stack */ - addlisttolist(&adt->drivers, &drivers); + BLI_movelisttolist(&adt->drivers, &drivers); } } @@ -1863,7 +1883,7 @@ void do_versions_ipos_to_animato(Main *main) to different DNA variables later (semi-hack (tm) ) */ - switch(seq->type) { + switch (seq->type) { case SEQ_IMAGE: case SEQ_META: case SEQ_SCENE: diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index f6f4226bf57..5c10c14c4e2 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -39,6 +39,7 @@ #include "BLI_blenlib.h" #include "BLI_editVert.h" #include "BLI_math_vector.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_key_types.h" @@ -58,14 +59,14 @@ #include "BKE_tessmesh.h" #include "BKE_main.h" #include "BKE_object.h" -#include "BKE_utildefines.h" + #include "RNA_access.h" #include "BLI_cellalloc.h" - -#define KEY_BPOINT 1 -#define KEY_BEZTRIPLE 2 +#define KEY_MODE_DUMMY 0 /* use where mode isn't checked for */ +#define KEY_MODE_BPOINT 1 +#define KEY_MODE_BEZTRIPLE 2 // old defines from DNA_ipo_types.h for data-type #define IPO_FLOAT 4 @@ -167,14 +168,10 @@ Key *copy_key(Key *key) Key *keyn; KeyBlock *kbn, *kb; - if(key==0) return 0; + if(key==NULL) return NULL; keyn= copy_libblock(key); -#if 0 // XXX old animation system - keyn->ipo= copy_ipo(key->ipo); -#endif // XXX old animation system - BLI_duplicatelist(&keyn->block, &key->block); kb= key->block.first; @@ -224,14 +221,10 @@ void make_local_key(Key *key) * - only local users: set flag * - mixed: make copy */ - if(key==0) return; + if(key==NULL) return; - key->id.lib= 0; - new_id(0, (ID *)key, 0); - -#if 0 // XXX old animation system - make_local_ipo(key->ipo); -#endif // XXX old animation system + key->id.lib= NULL; + new_id(NULL, (ID *)key, NULL); } /* Sort shape keys and Ipo curves after a change. This assumes that at most @@ -416,14 +409,14 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl) /* if(fac<0.0 || fac>1.0) return 1; */ - if(k1->next==0) return 1; + if(k1->next==NULL) return 1; if(cycl) { /* pre-sort */ k[2]= k1->next; k[3]= k[2]->next; - if(k[3]==0) k[3]=k1; + if(k[3]==NULL) k[3]=k1; while(k1) { - if(k1->next==0) k[0]=k1; + if(k1->next==NULL) k[0]=k1; k1=k1->next; } k1= k[1]; @@ -444,13 +437,13 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl) k[2]= k1->next; t[2]= k[2]->pos; k[3]= k[2]->next; - if(k[3]==0) k[3]= k[2]; + if(k[3]==NULL) k[3]= k[2]; t[3]= k[3]->pos; k1= k[3]; } while( t[2]<fac ) { /* find correct location */ - if(k1->next==0) { + if(k1->next==NULL) { if(cycl) { k1= firstkey; ofs+= dpos; @@ -570,36 +563,53 @@ static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char ** return kb->data; } -static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, int mode) + +/* currently only the first value of 'ofs' may be set. */ +static short key_pointer_size(const Key *key, const int mode, int *poinsize, int *ofs) +{ + if(key->from==NULL) { + return FALSE; + } + + switch(GS(key->from->name)) { + case ID_ME: + *ofs= sizeof(float)*3; + *poinsize= *ofs; + break; + case ID_LT: + *ofs= sizeof(float)*3; + *poinsize= *ofs; + break; + case ID_CU: + if(mode == KEY_MODE_BPOINT) { + *ofs= sizeof(float)*4; + *poinsize= *ofs; + } else { + ofs[0]= sizeof(float)*12; + *poinsize= (*ofs) / 3; + } + + break; + default: + BLI_assert(!"invalid 'key->from' ID type"); + return FALSE; + } + + return TRUE; +} + +static void cp_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, const int mode) { float ktot = 0.0, kd = 0.0; int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo=0; char *k1, *kref, *freek1, *freekref; char *cp, elemstr[8]; - if(key->from==NULL) return; - - if( GS(key->from->name)==ID_ME ) { - ofs[0]= sizeof(float)*3; - ofs[1]= 0; - poinsize= ofs[0]; - } - else if( GS(key->from->name)==ID_LT ) { - ofs[0]= sizeof(float)*3; - ofs[1]= 0; - poinsize= ofs[0]; - } - else if( GS(key->from->name)==ID_CU ) { - if(mode==KEY_BPOINT) { - ofs[0]= sizeof(float)*4; - poinsize= ofs[0]; - }else { - ofs[0]= sizeof(float)*12; - poinsize= ofs[0]/3; - } + /* currently always 0, in future key_pointer_size may assign */ + ofs[1]= 0; - ofs[1]= 0; - } + if(!key_pointer_size(key, mode, &poinsize, &ofs[0])) + return; if(end>tot) end= tot; @@ -631,7 +641,7 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * else k1+= start*key->elemsize; } - if(mode==KEY_BEZTRIPLE) { + if(mode == KEY_MODE_BEZTRIPLE) { elemstr[0]= 1; elemstr[1]= IPO_BEZTRIPLE; elemstr[2]= 0; @@ -639,11 +649,11 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * /* just do it here, not above! */ elemsize= key->elemsize; - if(mode==KEY_BEZTRIPLE) elemsize*= 3; + if(mode == KEY_MODE_BEZTRIPLE) elemsize*= 3; for(a=start; a<end; a++) { cp= key->elemstr; - if(mode==KEY_BEZTRIPLE) cp= elemstr; + if(mode == KEY_MODE_BEZTRIPLE) cp= elemstr; ofsp= ofs; @@ -666,8 +676,14 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * case IPO_BEZTRIPLE: memcpy(poin, k1, sizeof(float)*12); break; + default: + /* should never happen */ + if(freek1) MEM_freeN(freek1); + if(freekref) MEM_freeN(freekref); + BLI_assert(!"invalid 'cp[1]'"); + return; } - + poin+= ofsp[0]; cp+= 2; ofsp++; } @@ -686,14 +702,14 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * kref+= elemsize; } - if(mode==KEY_BEZTRIPLE) a+=2; + if(mode == KEY_MODE_BEZTRIPLE) a+=2; } if(freek1) MEM_freeN(freek1); if(freekref) MEM_freeN(freekref); } -static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int start, int end, char *out, int tot) +static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const int start, int end, char *out, const int tot) { Nurb *nu; int a, step, a1, a2; @@ -705,7 +721,7 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int st a1= MAX2(a, start); a2= MIN2(a+step, end); - if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_BPOINT); + if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BPOINT); } else if(nu->bezt) { step= 3*nu->pntsu; @@ -714,45 +730,26 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int st a1= MAX2(a, start); a2= MIN2(a+step, end); - if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_BEZTRIPLE); + if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BEZTRIPLE); } else step= 0; } } - -void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock *actkb, int mode) +void do_rel_key(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode) { KeyBlock *kb; int *ofsp, ofs[3], elemsize, b; char *cp, *poin, *reffrom, *from, elemstr[8]; char *freefrom, *freereffrom; - int poinsize= 0; - - if(key->from==NULL) return; + int poinsize; - if( GS(key->from->name)==ID_ME ) { - ofs[0]= sizeof(float)*3; - ofs[1]= 0; - poinsize= ofs[0]; - } - else if( GS(key->from->name)==ID_LT ) { - ofs[0]= sizeof(float)*3; - ofs[1]= 0; - poinsize= ofs[0]; - } - else if( GS(key->from->name)==ID_CU ) { - if(mode==KEY_BPOINT) { - ofs[0]= sizeof(float)*4; - poinsize= ofs[0]; - } else { - ofs[0]= sizeof(float)*12; - poinsize= ofs[0] / 3; - } + /* currently always 0, in future key_pointer_size may assign */ + ofs[1]= 0; - ofs[1]= 0; - } + if(!key_pointer_size(key, mode, &poinsize, &ofs[0])) + return; if(end>tot) end= tot; @@ -763,7 +760,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock /* just here, not above! */ elemsize= key->elemsize; - if(mode==KEY_BEZTRIPLE) elemsize*= 3; + if(mode == KEY_MODE_BEZTRIPLE) elemsize*= 3; /* step 1 init */ cp_key(start, end, tot, basispoin, key, actkb, key->refkey, NULL, mode); @@ -799,7 +796,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock weight= icuval; cp= key->elemstr; - if(mode==KEY_BEZTRIPLE) cp= elemstr; + if(mode == KEY_MODE_BEZTRIPLE) cp= elemstr; ofsp= ofs; @@ -815,8 +812,14 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock case IPO_BEZTRIPLE: rel_flerp(12, (float *)poin, (float *)reffrom, (float *)from, weight); break; + default: + /* should never happen */ + if(freefrom) MEM_freeN(freefrom); + if(freereffrom) MEM_freeN(freereffrom); + BLI_assert(!"invalid 'cp[1]'"); + return; } - + poin+= ofsp[0]; cp+= 2; @@ -826,7 +829,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock reffrom+= elemsize; from+= elemsize; - if(mode==KEY_BEZTRIPLE) b+= 2; + if(mode == KEY_MODE_BEZTRIPLE) b+= 2; if(weights) weights++; } @@ -838,7 +841,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock } -static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, int mode) +static void do_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, const int mode) { float k1tot = 0.0, k2tot = 0.0, k3tot = 0.0, k4tot = 0.0; float k1d = 0.0, k2d = 0.0, k3d = 0.0, k4d = 0.0; @@ -847,29 +850,11 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * char *k1, *k2, *k3, *k4, *freek1, *freek2, *freek3, *freek4; char *cp, elemstr[8];; - if(key->from==0) return; + /* currently always 0, in future key_pointer_size may assign */ + ofs[1]= 0; - if( GS(key->from->name)==ID_ME ) { - ofs[0]= sizeof(float)*3; - ofs[1]= 0; - poinsize= ofs[0]; - } - else if( GS(key->from->name)==ID_LT ) { - ofs[0]= sizeof(float)*3; - ofs[1]= 0; - poinsize= ofs[0]; - } - else if( GS(key->from->name)==ID_CU ) { - if(mode==KEY_BPOINT) { - ofs[0]= sizeof(float)*4; - poinsize= ofs[0]; - } else { - ofs[0]= sizeof(float)*12; - poinsize= ofs[0] / 3; - } - - ofs[1]= 0; - } + if(!key_pointer_size(key, mode, &poinsize, &ofs[0])) + return; if(end>tot) end= tot; @@ -971,12 +956,12 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * /* only here, not above! */ elemsize= key->elemsize; - if(mode==KEY_BEZTRIPLE) elemsize*= 3; + if(mode == KEY_MODE_BEZTRIPLE) elemsize*= 3; for(a=start; a<end; a++) { cp= key->elemstr; - if(mode==KEY_BEZTRIPLE) cp= elemstr; + if(mode == KEY_MODE_BEZTRIPLE) cp= elemstr; ofsp= ofs; @@ -992,6 +977,14 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * case IPO_BEZTRIPLE: flerp(12, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t); break; + default: + /* should never happen */ + if(freek1) MEM_freeN(freek1); + if(freek2) MEM_freeN(freek2); + if(freek3) MEM_freeN(freek3); + if(freek4) MEM_freeN(freek4); + BLI_assert(!"invalid 'cp[1]'"); + return; } poin+= ofsp[0]; @@ -1040,7 +1033,7 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * else k4+= elemsize; } - if(mode==KEY_BEZTRIPLE) a+= 2; + if(mode == KEY_MODE_BEZTRIPLE) a+= 2; } if(freek1) MEM_freeN(freek1); @@ -1116,7 +1109,7 @@ static float *get_weights_array(Object *ob, char *vgroup) return NULL; } -static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot) +static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot) { KeyBlock *k[4], *actkb= ob_get_keyblock(ob); float cfra, ctime, t[4], delta; @@ -1137,7 +1130,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot) for(a=0; a<tot; a+=step, cfra+= delta) { - ctime= bsystem_time(scene, 0, cfra, 0.0); // xxx ugly cruft! + ctime= bsystem_time(scene, NULL, cfra, 0.0); // xxx ugly cruft! #if 0 // XXX old animation system if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) { ctime /= 100.0; @@ -1151,9 +1144,9 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot) flag= setkeys(ctime, &key->block, k, t, 0); if(flag==0) - do_key(a, a+step, tot, (char *)out, key, actkb, k, t, 0); + do_key(a, a+step, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY); else - cp_key(a, a+step, tot, (char *)out, key, actkb, k[2], NULL, 0); + cp_key(a, a+step, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY); } } else { @@ -1163,7 +1156,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot) for(kb= key->block.first; kb; kb= kb->next) kb->weights= get_weights_array(ob, kb->vgroup); - do_rel_key(0, tot, tot, (char *)out, key, actkb, 0); + do_rel_key(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY); for(kb= key->block.first; kb; kb= kb->next) { if(kb->weights) MEM_freeN(kb->weights); @@ -1186,14 +1179,14 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot) flag= setkeys(ctime, &key->block, k, t, 0); if(flag==0) - do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0); + do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY); else - cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0); + cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY); } } } -static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, int tot) +static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, const int tot) { Nurb *nu; int a, step; @@ -1201,18 +1194,18 @@ static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) { if(nu->bp) { step= nu->pntsu*nu->pntsv; - do_key(a, a+step, tot, out, key, actkb, k, t, KEY_BPOINT); + do_key(a, a+step, tot, out, key, actkb, k, t, KEY_MODE_BPOINT); } else if(nu->bezt) { step= 3*nu->pntsu; - do_key(a, a+step, tot, out, key, actkb, k, t, KEY_BEZTRIPLE); + do_key(a, a+step, tot, out, key, actkb, k, t, KEY_MODE_BEZTRIPLE); } else step= 0; } } -static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float ctime, char *out, int tot) +static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float UNUSED(ctime), char *out, const int tot) { Nurb *nu; int a, step; @@ -1220,18 +1213,18 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float ctime, cha for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) { if(nu->bp) { step= nu->pntsu*nu->pntsv; - do_rel_key(a, a+step, tot, out, key, actkb, KEY_BPOINT); + do_rel_key(a, a+step, tot, out, key, actkb, KEY_MODE_BPOINT); } else if(nu->bezt) { step= 3*nu->pntsu; - do_rel_key(a, a+step, tot, out, key, actkb, KEY_BEZTRIPLE); + do_rel_key(a, a+step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE); } else step= 0; } } -static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot) +static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const int tot) { Curve *cu= ob->data; KeyBlock *k[4], *actkb= ob_get_keyblock(ob); @@ -1240,7 +1233,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot) if(key->slurph && key->type!=KEY_RELATIVE) { Nurb *nu; - int mode, i= 0, remain= 0, estep, count; + int mode=0, i= 0, remain= 0, estep=0, count=0; delta= (float)key->slurph / tot; @@ -1255,11 +1248,11 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot) for(nu=cu->nurb.first; nu; nu=nu->next) { if(nu->bp) { - mode= KEY_BPOINT; + mode= KEY_MODE_BPOINT; estep= nu->pntsu*nu->pntsv; } else if(nu->bezt) { - mode= KEY_BEZTRIPLE; + mode= KEY_MODE_BEZTRIPLE; estep= 3*nu->pntsu; } else @@ -1269,7 +1262,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot) while (a < estep) { if (remain <= 0) { cfra+= delta; - ctime= bsystem_time(scene, 0, cfra, 0.0f); // XXX old cruft + ctime= bsystem_time(scene, NULL, cfra, 0.0f); // XXX old cruft ctime /= 100.0f; CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing @@ -1279,7 +1272,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot) } count= MIN2(remain, estep); - if (mode == KEY_BEZTRIPLE) { + if (mode == KEY_MODE_BEZTRIPLE) { count += 3 - count % 3; } @@ -1317,7 +1310,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot) } } -static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot) +static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int tot) { Lattice *lt= ob->data; KeyBlock *k[4], *actkb= ob_get_keyblock(ob); @@ -1332,7 +1325,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot) for(a=0; a<tot; a++, cfra+= delta) { - ctime= bsystem_time(scene, 0, cfra, 0.0); // XXX old cruft + ctime= bsystem_time(scene, NULL, cfra, 0.0); // XXX old cruft #if 0 // XXX old animation system if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) { ctime /= 100.0; @@ -1343,9 +1336,9 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot) flag= setkeys(ctime, &key->block, k, t, 0); if(flag==0) - do_key(a, a+1, tot, (char *)out, key, actkb, k, t, 0); + do_key(a, a+1, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY); else - cp_key(a, a+1, tot, (char *)out, key, actkb, k[2], NULL, 0); + cp_key(a, a+1, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY); } } else { @@ -1355,7 +1348,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot) for(kb= key->block.first; kb; kb= kb->next) kb->weights= get_weights_array(ob, kb->vgroup); - do_rel_key(0, tot, tot, (char *)out, key, actkb, 0); + do_rel_key(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY); for(kb= key->block.first; kb; kb= kb->next) { if(kb->weights) MEM_freeN(kb->weights); @@ -1375,9 +1368,9 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot) flag= setkeys(ctime, &key->block, k, t, 0); if(flag==0) - do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0); + do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY); else - cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0); + cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY); } } @@ -1490,7 +1483,7 @@ Key *ob_get_key(Object *ob) return NULL; } -KeyBlock *add_keyblock(Key *key, char *name) +KeyBlock *add_keyblock(Key *key, const char *name) { KeyBlock *kb; float curpos= -0.1; @@ -1707,7 +1700,7 @@ void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb) } } -void key_to_curve(KeyBlock *kb, Curve *cu, ListBase *nurb) +void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) { Nurb *nu; BezTriple *bezt; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 725f9a34b25..70eba3903d0 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -1,4 +1,4 @@ -/** +/* * lattice.c * * @@ -41,6 +41,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_cellalloc.h" +#include "BLI_utildefines.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -50,6 +51,7 @@ #include "DNA_curve_types.h" #include "DNA_key_types.h" +#include "BKE_animsys.h" #include "BKE_anim.h" #include "BKE_cdderivedmesh.h" #include "BKE_displist.h" @@ -60,7 +62,7 @@ #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_modifier.h" -#include "BKE_utildefines.h" + #include "BKE_deform.h" //XXX #include "BIF_editdeform.h" @@ -182,7 +184,7 @@ void resizelattice(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) MEM_freeN(vertexCos); } -Lattice *add_lattice(char *name) +Lattice *add_lattice(const char *name) { Lattice *lt; @@ -204,10 +206,6 @@ Lattice *copy_lattice(Lattice *lt) ltn= copy_libblock(lt); ltn->def= MEM_dupallocN(lt->def); - -#if 0 // XXX old animation system - id_us_plus((ID *)ltn->ipo); -#endif // XXX old animation system ltn->key= copy_key(ltn->key); if(ltn->key) ltn->key->from= (ID *)ltn; @@ -234,6 +232,12 @@ void free_lattice(Lattice *lt) MEM_freeN(editlt); MEM_freeN(lt->editlatt); } + + /* free animation data */ + if (lt->adt) { + BKE_free_animdata(<->id); + lt->adt= NULL; + } } @@ -248,11 +252,11 @@ void make_local_lattice(Lattice *lt) * - mixed: make copy */ - if(lt->id.lib==0) return; + if(lt->id.lib==NULL) return; if(lt->id.us==1) { - lt->id.lib= 0; + lt->id.lib= NULL; lt->id.flag= LIB_LOCAL; - new_id(0, (ID *)lt, 0); + new_id(NULL, (ID *)lt, NULL); return; } @@ -266,9 +270,9 @@ void make_local_lattice(Lattice *lt) } if(local && lib==0) { - lt->id.lib= 0; + lt->id.lib= NULL; lt->id.flag= LIB_LOCAL; - new_id(0, (ID *)lt, 0); + new_id(NULL, (ID *)lt, NULL); } else if(local && lib) { ltn= copy_lattice(lt); @@ -278,7 +282,7 @@ void make_local_lattice(Lattice *lt) while(ob) { if(ob->data==lt) { - if(ob->id.lib==0) { + if(ob->id.lib==NULL) { ob->data= ltn; ltn->id.us++; lt->id.us--; @@ -600,16 +604,6 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C } #endif - - static float q_x90d[4] = {0.70710676908493, 0.70710676908493, 0.0, 0.0}; // float rot_axis[3]= {1,0,0}; axis_angle_to_quat(q, rot_axis, 90 * (M_PI / 180)); - static float q_y90d[4] = {0.70710676908493, 0.0, 0.70710676908493, 0.0}; // float rot_axis[3]= {0,1,0}; axis_angle_to_quat(q, rot_axis, 90 * (M_PI / 180)); - static float q_z90d[4] = {0.70710676908493, 0.0, 0.0, 0.70710676908493}; // float rot_axis[3]= {0,0,2}; axis_angle_to_quat(q, rot_axis, 90 * (M_PI / 180)); - - static float q_nx90d[4] = {0.70710676908493, -0.70710676908493, 0.0, 0.0}; // float rot_axis[3]= {1,0,0}; axis_angle_to_quat(q, rot_axis, -90 * (M_PI / 180)); - static float q_ny90d[4] = {0.70710676908493, 0.0, -0.70710676908493, 0.0}; // float rot_axis[3]= {0,1,0}; axis_angle_to_quat(q, rot_axis, -90 * (M_PI / 180)); - static float q_nz90d[4] = {0.70710676908493, 0.0, 0.0, -0.70710676908493}; // float rot_axis[3]= {0,0,2}; axis_angle_to_quat(q, rot_axis, -90 * (M_PI / 180)); - - if(cd->no_rot_axis) { /* set by caller */ /* this is not exactly the same as 2.4x, since the axis is having rotation removed rather then @@ -636,53 +630,18 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C * Notice X,Y,Z Up all have light colors and each ordered CCW. * * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell + * + * note: moved functions into quat_apply_track/vec_apply_track * */ + copy_qt_qt(quat, new_quat); + copy_v3_v3(cent, co); + + /* zero the axis which is not used, + * the big block of text above now applies to these 3 lines */ + quat_apply_track(quat, axis-1, (axis==1 || axis==3) ? 1:0); /* up flag is a dummy, set so no rotation is done */ + vec_apply_track(cent, axis-1); + cent[axis < 4 ? axis-1 : axis-4]= 0.0f; - switch(axis) { - case MOD_CURVE_POSX: - mul_qt_qtqt(quat, new_quat, q_y90d); - - cent[0]= 0.0; - cent[1]= co[2]; - cent[2]= co[1]; - break; - case MOD_CURVE_NEGX: - mul_qt_qtqt(quat, new_quat, q_ny90d); - - cent[0]= 0.0; - cent[1]= -co[1]; - cent[2]= co[2]; - - break; - case MOD_CURVE_POSY: - mul_qt_qtqt(quat, new_quat, q_x90d); - - cent[0]= co[2]; - cent[1]= 0.0; - cent[2]= -co[0]; - break; - case MOD_CURVE_NEGY: - mul_qt_qtqt(quat, new_quat, q_nx90d); - - cent[0]= -co[0]; - cent[1]= 0.0; - cent[2]= -co[2]; - break; - case MOD_CURVE_POSZ: - mul_qt_qtqt(quat, new_quat, q_z90d); - - cent[0]= co[1]; - cent[1]= -co[0]; - cent[2]= 0.0; - break; - case MOD_CURVE_NEGZ: - mul_qt_qtqt(quat, new_quat, q_nz90d); - - cent[0]= co[0]; - cent[1]= -co[1]; - cent[2]= 0.0; - break; - } /* scale if enabled */ if(cu->flag & CU_PATH_RADIUS) diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 687b212ec2e..cb96f549829 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -39,6 +39,7 @@ #include <string.h> #include <stdlib.h> #include <stddef.h> +#include <assert.h> #include "MEM_guardedalloc.h" @@ -66,9 +67,10 @@ #include "DNA_world_types.h" #include "DNA_gpencil_types.h" - #include "BLI_blenlib.h" #include "BLI_dynstr.h" +#include "BLI_utildefines.h" + #include "BKE_animsys.h" #include "BKE_context.h" @@ -136,8 +138,14 @@ void id_us_plus(ID *id) void id_us_min(ID *id) { - if(id) - id->us--; + if(id) { + if(id->us<2 && (id->flag & LIB_FAKEUSER)) + id->us= 1; + else if(id->us<=0) + printf("ID user decrement error: %s \n", id->name); + else + id->us--; + } } int id_make_local(ID *id, int test) @@ -302,7 +310,7 @@ int id_copy(ID *id, ID **newid, int test) if(!test) *newid= (ID*)copy_action((bAction*)id); return 1; case ID_NT: - if(!test) *newid= (ID*)ntreeCopyTree((bNodeTree*)id, 0); + if(!test) *newid= (ID*)ntreeCopyTree((bNodeTree*)id); return 1; case ID_BR: if(!test) *newid= (ID*)copy_brush((Brush*)id); @@ -335,7 +343,7 @@ int id_unlink(ID *id, int test) break; case ID_OB: if(test) return 1; - unlink_object(NULL, (Object*)id); + unlink_object((Object*)id); break; } @@ -411,7 +419,7 @@ ListBase *which_libbase(Main *mainlib, short type) case ID_GD: return &(mainlib->gpencil); } - return 0; + return NULL; } /* Flag all ids in listbase */ @@ -442,7 +450,7 @@ void recalc_all_library_objects(Main *main) /* flag for full recalc */ for(ob=main->object.first; ob; ob=ob->id.next) if(ob->id.lib) - ob->recalc |= OB_RECALC_ALL; + ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; } /* note: MAX_LIBARRAY define should match this code */ @@ -450,11 +458,13 @@ int set_listbasepointers(Main *main, ListBase **lb) { int a = 0; - /* BACKWARDS! also watch order of free-ing! (mesh<->mat) */ - + /* BACKWARDS! also watch order of free-ing! (mesh<->mat), first items freed last. + * This is important because freeing data decreases usercounts of other datablocks, + * if this data is its self freed it can crash. */ lb[a++]= &(main->ipo); lb[a++]= &(main->action); // xxx moved here to avoid problems when freeing with animato (aligorith) lb[a++]= &(main->key); + lb[a++]= &(main->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */ lb[a++]= &(main->nodetree); lb[a++]= &(main->image); lb[a++]= &(main->tex); @@ -481,14 +491,13 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a++]= &(main->brush); lb[a++]= &(main->script); lb[a++]= &(main->particle); - + lb[a++]= &(main->world); lb[a++]= &(main->screen); lb[a++]= &(main->object); lb[a++]= &(main->scene); lb[a++]= &(main->library); lb[a++]= &(main->wm); - lb[a++]= &(main->gpencil); lb[a]= NULL; @@ -617,24 +626,24 @@ void *alloc_libblock(ListBase *lb, short type, const char *name) /* by spec, animdata is first item after ID */ /* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */ -static void id_copy_animdata(ID *id) +static void id_copy_animdata(ID *id, const short do_action) { AnimData *adt= BKE_animdata_from_id(id); if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id; - iat->adt= BKE_copy_animdata(iat->adt); + iat->adt= BKE_copy_animdata(iat->adt, do_action); /* could be set to FALSE, need to investigate */ } } /* material nodes use this since they are not treated as libdata */ -void copy_libblock_data(ID *id, const ID *id_from) +void copy_libblock_data(ID *id, const ID *id_from, const short do_action) { if (id_from->properties) id->properties = IDP_CopyProperty(id_from->properties); /* the duplicate should get a copy of the animdata */ - id_copy_animdata(id); + id_copy_animdata(id, do_action); } /* used everywhere in blenkernel */ @@ -649,11 +658,9 @@ void *copy_libblock(void *rt) lb= which_libbase(G.main, GS(id->name)); idn= alloc_libblock(lb, GS(id->name), id->name+2); - - if(idn==NULL) { - printf("ERROR: Illegal ID name for %s (Crashing now)\n", id->name); - } - + + assert(idn != NULL); + idn_len= MEM_allocN_len(idn); if(idn_len - sizeof(ID) > 0) { cp= (char *)id; @@ -664,12 +671,12 @@ void *copy_libblock(void *rt) id->newid= idn; idn->flag |= LIB_NEW; - copy_libblock_data(idn, id); + copy_libblock_data(idn, id, FALSE); return idn; } -static void free_library(Library *lib) +static void free_library(Library *UNUSED(lib)) { /* no freeing needed for libraries yet */ } @@ -681,7 +688,7 @@ void set_free_windowmanager_cb(void (*func)(bContext *C, wmWindowManager *) ) free_windowmanager_cb= func; } -void animdata_dtar_clear_cb(ID *id, AnimData *adt, void *userdata) +static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata) { ChannelDriver *driver; FCurve *fcu; @@ -822,7 +829,7 @@ void free_libblock_us(ListBase *lb, void *idv) /* test users */ else printf("ERROR block %s users %d\n", id->name, id->us); } if(id->us==0) { - if( GS(id->name)==ID_OB ) unlink_object(NULL, (Object *)id); + if( GS(id->name)==ID_OB ) unlink_object((Object *)id); free_libblock(lb, id); } @@ -851,7 +858,7 @@ void free_main(Main *mainvar) /* ***************** ID ************************ */ -ID *find_id(char *type, char *name) /* type: "OB" or "MA" etc */ +ID *find_id(const char *type, const char *name) /* type: "OB" or "MA" etc */ { ListBase *lb= which_libbase(G.main, GS(type)); return BLI_findstring(lb, name, offsetof(ID, name) + 2); @@ -913,7 +920,7 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor BLI_dynstr_append(pupds, buf); BLI_dynstr_append(pupds, id->name+2); - sprintf(buf, "%%x%d", i+1); + BLI_snprintf(buf, sizeof(buf), "%%x%d", i+1); BLI_dynstr_append(pupds, buf); /* icon */ @@ -924,7 +931,7 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor case ID_IM: /* fall through */ case ID_WO: /* fall through */ case ID_LA: /* fall through */ - sprintf(buf, "%%i%d", BKE_icon_getid(id) ); + BLI_snprintf(buf, sizeof(buf), "%%i%d", BKE_icon_getid(id) ); BLI_dynstr_append(pupds, buf); break; default: @@ -940,7 +947,7 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor /* used by headerbuttons.c buttons.c editobject.c editseq.c */ /* if nr==NULL no MAX_IDPUP, this for non-header browsing */ -void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr) +void IDnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr) { DynStr *pupds= BLI_dynstr_new(); @@ -962,7 +969,7 @@ void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, } /* skips viewer images */ -void IMAnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr) +void IMAnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr) { DynStr *pupds= BLI_dynstr_new(); @@ -983,35 +990,6 @@ void IMAnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb BLI_dynstr_free(pupds); } - -/* used by buttons.c library.c mball.c */ -int splitIDname(char *name, char *left, int *nr) -{ - int a; - - *nr= 0; - strncpy(left, name, 21); - - a= strlen(name); - if(a>1 && name[a-1]=='.') return a; - - while(a--) { - if( name[a]=='.' ) { - left[a]= 0; - *nr= atol(name+a+1); - return a; - } - if( isdigit(name[a])==0 ) break; - - left[a]= 0; - } - - for(a= 0; name[a]; a++) - left[a]= name[a]; - - return a; -} - static void sort_alpha_id(ListBase *lb, ID *id) { ID *idtest; @@ -1029,7 +1007,7 @@ static void sort_alpha_id(ListBase *lb, ID *id) idtest= idtest->next; } /* as last */ - if(idtest==0) { + if(idtest==NULL) { BLI_addtail(lb, id); } } @@ -1040,7 +1018,7 @@ static void sort_alpha_id(ListBase *lb, ID *id) * Check to see if there is an ID with the same name as 'name'. * Returns the ID if so, if not, returns NULL */ -static ID *is_dupid(ListBase *lb, ID *id, char *name) +static ID *is_dupid(ListBase *lb, ID *id, const char *name) { ID *idtest=NULL; @@ -1091,7 +1069,7 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name) memset(in_use, 0, sizeof(in_use)); /* get name portion, number portion ("name.number") */ - left_len= splitIDname(name, left, &nr); + left_len= BLI_split_name_num(left, &nr, name, '.'); /* if new name will be too long, truncate it */ if(nr > 999 && left_len > 16) { @@ -1108,7 +1086,7 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name) (idtest->lib == NULL) && (*name == *(idtest->name+2)) && (strncmp(name, idtest->name+2, left_len)==0) && - (splitIDname(idtest->name+2, leftest, &nrtest) == left_len) + (BLI_split_name_num(leftest, &nrtest, idtest->name+2, '.') == left_len) ) { if(nrtest < sizeof(in_use)) in_use[nrtest]= 1; /* mark as used */ @@ -1146,11 +1124,11 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name) /* this would overflow name buffer */ left[16] = 0; /* left_len = 16; */ /* for now this isnt used again */ - memcpy(name, left, sizeof(char) * 16); + memcpy(name, left, sizeof(char) * 17); continue; } /* this format specifier is from hell... */ - sprintf(name, "%s.%.3d", left, nr); + BLI_snprintf(name, sizeof(id->name) - 2,"%s.%.3d", left, nr); return 1; } @@ -1211,7 +1189,7 @@ int new_id(ListBase *lb, ID *id, const char *tname) } /* next to indirect usage in read/writefile also in editobject.c scene.c */ -void clear_id_newpoins() +void clear_id_newpoins(void) { ListBase *lbarray[MAX_LIBARRAY]; ID *id; @@ -1221,7 +1199,7 @@ void clear_id_newpoins() while(a--) { id= lbarray[a]->first; while(id) { - id->newid= 0; + id->newid= NULL; id->flag &= ~LIB_NEW; id= id->next; } @@ -1234,7 +1212,7 @@ static void image_fix_relative_path(Image *ima) if(ima->id.lib==NULL) return; if(strncmp(ima->name, "//", 2)==0) { BLI_path_abs(ima->name, ima->id.lib->filepath); - BLI_path_rel(ima->name, G.sce); + BLI_path_rel(ima->name, G.main->name); } } @@ -1279,25 +1257,43 @@ static void lib_indirect_test_id(ID *id, Library *lib) } } -void tag_main(struct Main *mainvar, int tag) +void tag_main_lb(ListBase *lb, const short tag) { - ListBase *lbarray[MAX_LIBARRAY]; ID *id; + if(tag) { + for(id= lb->first; id; id= id->next) { + id->flag |= LIB_DOIT; + } + } + else { + for(id= lb->first; id; id= id->next) { + id->flag &= ~LIB_DOIT; + } + } +} + +void tag_main_idcode(struct Main *mainvar, const short type, const short tag) +{ + ListBase *lb= which_libbase(mainvar, type); + + tag_main_lb(lb, tag); +} + +void tag_main(struct Main *mainvar, const short tag) +{ + ListBase *lbarray[MAX_LIBARRAY]; int a; a= set_listbasepointers(mainvar, lbarray); while(a--) { - for(id= lbarray[a]->first; id; id= id->next) { - if(tag) id->flag |= LIB_DOIT; - else id->flag &= ~LIB_DOIT; - } + tag_main_lb(lbarray[a], tag); } } /* if lib!=NULL, only all from lib local */ void all_local(Library *lib, int untagged_only) { - ListBase *lbarray[MAX_LIBARRAY], tempbase={0, 0}; + ListBase *lbarray[MAX_LIBARRAY], tempbase={NULL, NULL}; ID *id, *idn; int a; @@ -1326,7 +1322,7 @@ void all_local(Library *lib, int untagged_only) image_fix_relative_path((Image *)id); id->lib= NULL; - new_id(lbarray[a], id, 0); /* new_id only does it with double names */ + new_id(lbarray[a], id, NULL); /* new_id only does it with double names */ sort_alpha_id(lbarray[a], id); } } @@ -1338,7 +1334,7 @@ void all_local(Library *lib, int untagged_only) while( (id=tempbase.first) ) { BLI_remlink(&tempbase, id); BLI_addtail(lbarray[a], id); - new_id(lbarray[a], id, 0); + new_id(lbarray[a], id, NULL); } } @@ -1359,7 +1355,7 @@ void test_idbutton(char *name) lb= which_libbase(G.main, GS(name-2) ); - if(lb==0) return; + if(lb==NULL) return; /* search for id */ idtest= BLI_findstring(lb, name, offsetof(ID, name) + 2); @@ -1386,14 +1382,14 @@ void text_idbutton(struct ID *id, char *text) } else { text[0]= '\0'; -} + } } -void rename_id(ID *id, char *name) +void rename_id(ID *id, const char *name) { ListBase *lb; - strncpy(id->name+2, name, 21); + BLI_strncpy(id->name+2, name, sizeof(id->name)-2); lb= which_libbase(G.main, GS(id->name) ); new_id(lb, id, name); @@ -1402,7 +1398,7 @@ void rename_id(ID *id, char *name) void name_uiprefix_id(char *name, ID *id) { name[0] = id->lib ? 'L':' '; - name[1] = id->flag & LIB_FAKEUSER ? 'F':' '; + name[1] = id->flag & LIB_FAKEUSER ? 'F': (id->us==0)?'0':' '; name[2] = ' '; strcpy(name+3, id->name+2); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 7e52f746ebc..0b1cbd60432 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -44,6 +44,8 @@ #include "DNA_scene_types.h" #include "BLI_math.h" +#include "BLI_listbase.h" +#include "BLI_utildefines.h" #include "BKE_animsys.h" #include "BKE_displist.h" @@ -54,7 +56,7 @@ #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_node.h" -#include "BKE_utildefines.h" + #include "GPU_material.h" @@ -84,7 +86,8 @@ void free_material(Material *ma) BKE_free_animdata((ID *)ma); - BKE_previewimg_free(&ma->preview); + if(ma->preview) + BKE_previewimg_free(&ma->preview); BKE_icon_delete((struct ID*)ma); ma->id.icon_id = 0; @@ -185,7 +188,7 @@ void init_material(Material *ma) ma->preview = NULL; } -Material *add_material(char *name) +Material *add_material(const char *name) { Material *ma; @@ -196,6 +199,7 @@ Material *add_material(char *name) return ma; } +/* XXX keep synced with next function */ Material *copy_material(Material *ma) { Material *man; @@ -203,9 +207,6 @@ Material *copy_material(Material *ma) man= copy_libblock(ma); -#if 0 // XXX old animation system - id_us_plus((ID *)man->ipo); -#endif // XXX old animation system id_lib_extern((ID *)man->group); for(a=0; a<MAX_MTEX; a++) { @@ -222,7 +223,7 @@ Material *copy_material(Material *ma) if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview); if(ma->nodetree) { - man->nodetree= ntreeCopyTree(ma->nodetree, 0); /* 0 == full new tree */ + man->nodetree= ntreeCopyTree(ma->nodetree); /* 0 == full new tree */ } man->gpumaterial.first= man->gpumaterial.last= NULL; @@ -230,6 +231,38 @@ Material *copy_material(Material *ma) return man; } +/* XXX (see above) material copy without adding to main dbase */ +Material *localize_material(Material *ma) +{ + Material *man; + int a; + + man= copy_libblock(ma); + BLI_remlink(&G.main->mat, man); + + for(a=0; a<MAX_MTEX; a++) { + if(ma->mtex[a]) { + man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial"); + memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex)); + /* free_material decrements! */ + id_us_plus((ID *)man->mtex[a]->tex); + } + } + + if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col); + if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec); + + man->preview = NULL; + + if(ma->nodetree) { + man->nodetree= ntreeLocalize(ma->nodetree); + } + + man->gpumaterial.first= man->gpumaterial.last= NULL; + + return man; +} + void make_local_material(Material *ma) { Main *bmain= G.main; @@ -245,11 +278,11 @@ void make_local_material(Material *ma) * - mixed: make copy */ - if(ma->id.lib==0) return; + if(ma->id.lib==NULL) return; if(ma->id.us==1) { - ma->id.lib= 0; + ma->id.lib= NULL; ma->id.flag= LIB_LOCAL; - new_id(0, (ID *)ma, 0); + new_id(NULL, (ID *)ma, NULL); for(a=0; a<MAX_MTEX; a++) { if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex); } @@ -311,14 +344,14 @@ void make_local_material(Material *ma) } if(local && lib==0) { - ma->id.lib= 0; + ma->id.lib= NULL; ma->id.flag= LIB_LOCAL; for(a=0; a<MAX_MTEX; a++) { if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex); } - new_id(0, (ID *)ma, 0); + new_id(NULL, (ID *)ma, NULL); } else if(local && lib) { @@ -331,7 +364,7 @@ void make_local_material(Material *ma) if(ob->mat) { for(a=0; a<ob->totcol; a++) { if(ob->mat[a]==ma) { - if(ob->id.lib==0) { + if(ob->id.lib==NULL) { ob->mat[a]= man; man->id.us++; ma->id.us--; @@ -347,7 +380,7 @@ void make_local_material(Material *ma) if(me->mat) { for(a=0; a<me->totcol; a++) { if(me->mat[a]==ma) { - if(me->id.lib==0) { + if(me->id.lib==NULL) { me->mat[a]= man; man->id.us++; ma->id.us--; @@ -363,7 +396,7 @@ void make_local_material(Material *ma) if(cu->mat) { for(a=0; a<cu->totcol; a++) { if(cu->mat[a]==ma) { - if(cu->id.lib==0) { + if(cu->id.lib==NULL) { cu->mat[a]= man; man->id.us++; ma->id.us--; @@ -379,7 +412,7 @@ void make_local_material(Material *ma) if(mb->mat) { for(a=0; a<mb->totcol; a++) { if(mb->mat[a]==ma) { - if(mb->id.lib==0) { + if(mb->id.lib==NULL) { mb->mat[a]= man; man->id.us++; ma->id.us--; @@ -445,7 +478,7 @@ Material ***give_matarar_id(ID *id) return &(((Curve *)id)->mat); break; case ID_MB: - return &(((Curve *)id)->mat); + return &(((MetaBall *)id)->mat); break; } return NULL; @@ -461,7 +494,7 @@ short *give_totcolp_id(ID *id) return &(((Curve *)id)->totcol); break; case ID_MB: - return &(((Curve *)id)->totcol); + return &(((MetaBall *)id)->totcol); break; } return NULL; @@ -492,6 +525,7 @@ Material *material_pop_id(ID *id, int index) short *totcol= give_totcolp_id(id); if(index >= 0 && index < (*totcol)) { ret= (*matar)[index]; + id_us_min((ID *)ret); if(*totcol <= 1) { *totcol= 0; MEM_freeN(*matar); @@ -529,6 +563,10 @@ Material *give_current_material(Object *ob, int act) totcolp= give_totcolp(ob); if(totcolp==NULL || ob->totcol==0) return NULL; + if(act<0) { + printf("no!\n"); + } + if(act>ob->totcol) act= ob->totcol; else if(act<=0) act= 1; @@ -545,7 +583,7 @@ Material *give_current_material(Object *ob, int act) matarar= give_matarar(ob); if(matarar && *matarar) ma= (*matarar)[act-1]; - else ma= 0; + else ma= NULL; } @@ -555,7 +593,7 @@ Material *give_current_material(Object *ob, int act) ID *material_from(Object *ob, int act) { - if(ob==0) return 0; + if(ob==NULL) return NULL; if(ob->totcol==0) return ob->data; if(act==0) act= 1; @@ -589,67 +627,53 @@ Material *give_node_material(Material *ma) /* from misc_util: flip the bytes from x */ /* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ -void test_object_materials(ID *id) +void resize_object_material(Object *ob, const short totcol) { - /* make the ob mat-array same size as 'ob->data' mat-array */ - Object *ob; - Mesh *me; - Curve *cu; - MetaBall *mb; Material **newmatar; char *newmatbits; - int totcol=0; - - if(id==0) return; - if( GS(id->name)==ID_ME ) { - me= (Mesh *)id; - totcol= me->totcol; + if(totcol==0) { + if(ob->totcol) { + MEM_freeN(ob->mat); + MEM_freeN(ob->matbits); + ob->mat= NULL; + ob->matbits= NULL; + } } - else if( GS(id->name)==ID_CU ) { - cu= (Curve *)id; - totcol= cu->totcol; + else if(ob->totcol<totcol) { + newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar"); + newmatbits= MEM_callocN(sizeof(char)*totcol, "newmatbits"); + if(ob->totcol) { + memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol); + memcpy(newmatbits, ob->matbits, sizeof(char)*ob->totcol); + MEM_freeN(ob->mat); + MEM_freeN(ob->matbits); + } + ob->mat= newmatar; + ob->matbits= newmatbits; } - else if( GS(id->name)==ID_MB ) { - mb= (MetaBall *)id; - totcol= mb->totcol; + ob->totcol= totcol; + if(ob->totcol && ob->actcol==0) ob->actcol= 1; + if(ob->actcol>ob->totcol) ob->actcol= ob->totcol; +} + +void test_object_materials(ID *id) +{ + /* make the ob mat-array same size as 'ob->data' mat-array */ + Object *ob; + short *totcol; + + if(id==NULL || (totcol=give_totcolp_id(id))==NULL) { + return; } - else return; - ob= G.main->object.first; - while(ob) { - + for(ob= G.main->object.first; ob; ob= ob->id.next) { if(ob->data==id) { - - if(totcol==0) { - if(ob->totcol) { - MEM_freeN(ob->mat); - MEM_freeN(ob->matbits); - ob->mat= NULL; - ob->matbits= NULL; - } - } - else if(ob->totcol<totcol) { - newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar"); - newmatbits= MEM_callocN(sizeof(char)*totcol, "newmatbits"); - if(ob->totcol) { - memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol); - memcpy(newmatbits, ob->matbits, sizeof(char)*ob->totcol); - MEM_freeN(ob->mat); - MEM_freeN(ob->matbits); - } - ob->mat= newmatar; - ob->matbits= newmatbits; - } - ob->totcol= totcol; - if(ob->totcol && ob->actcol==0) ob->actcol= 1; - if(ob->actcol>ob->totcol) ob->actcol= ob->totcol; + resize_object_material(ob, *totcol); } - ob= ob->id.next; } } - void assign_material(Object *ob, Material *ma, int act) { Material *mao, **matar, ***matarar; @@ -664,7 +688,7 @@ void assign_material(Object *ob, Material *ma, int act) totcolp= give_totcolp(ob); matarar= give_matarar(ob); - if(totcolp==0 || matarar==0) return; + if(totcolp==NULL || matarar==NULL) return; if(act > *totcolp) { matar= MEM_callocN(sizeof(void *)*act, "matarray1"); @@ -758,11 +782,18 @@ int object_add_material_slot(Object *ob) { Material *ma; - if(ob==0) return FALSE; + if(ob==NULL) return FALSE; if(ob->totcol>=MAXMAT) return FALSE; ma= give_current_material(ob, ob->actcol); + if(ma == NULL) + ma= add_material("Material"); + else + ma= copy_material(ma); + + id_us_min(&ma->id); + assign_material(ob, ma, ob->totcol+1); ob->actcol= ob->totcol; return TRUE; @@ -786,10 +817,10 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) ma->texco |= mtex->texco; ma->mapto |= mtex->mapto; - if(r_mode & R_OSA) { - if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA; - else if(mtex->texflag & MTEX_NEW_BUMP) ma->texco |= TEXCO_OSA; // NEWBUMP: need texture derivatives for procedurals as well - } + + /* always get derivatives for these textures */ + if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA; + else if(mtex->texflag & (MTEX_COMPAT_BUMP|MTEX_3TAP_BUMP|MTEX_5TAP_BUMP)) ma->texco |= TEXCO_OSA; if(ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1; else if(ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT|TEXCO_SPEED)) needuv= 1; @@ -841,7 +872,7 @@ static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode if(ma!=basemat) { do_init_render_material(ma, r_mode, amb); basemat->texco |= ma->texco; - basemat->mode_l |= ma->mode_l; + basemat->mode_l |= ma->mode_l & ~(MA_TRANSP|MA_ZTRANSP|MA_RAYTRANSP); } } else if(node->type==NODE_GROUP) @@ -933,7 +964,7 @@ int material_in_material(Material *parmat, Material *mat) /* ****************** */ -char colname_array[125][20]= { +static char colname_array[125][20]= { "Black","DarkRed","HalfRed","Red","Red", "DarkGreen","DarkOlive","Brown","Chocolate","OrangeRed", "HalfGreen","GreenOlive","DryOlive","Goldenrod","DarkOrange", @@ -966,7 +997,7 @@ void automatname(Material *ma) int nr, r, g, b; float ref; - if(ma==0) return; + if(ma==NULL) return; if(ma->mode & MA_SHLESS) ref= 1.0; else ref= ma->ref; @@ -1014,7 +1045,7 @@ int object_remove_material_slot(Object *ob) if(*totcolp==0) { MEM_freeN(*matarar); - *matarar= 0; + *matarar= NULL; } actcol= ob->actcol; @@ -1037,7 +1068,7 @@ int object_remove_material_slot(Object *ob) if(obt->totcol==0) { MEM_freeN(obt->mat); MEM_freeN(obt->matbits); - obt->mat= 0; + obt->mat= NULL; obt->matbits= NULL; } } @@ -1318,8 +1349,7 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col) /* copy/paste buffer, if we had a propper py api that would be better */ Material matcopybuf; -// MTex mtexcopybuf; -static short matcopied=0; +static short matcopied= 0; void clear_matcopybuf(void) { @@ -1329,7 +1359,6 @@ void clear_matcopybuf(void) void free_matcopybuf(void) { -// extern MTex mtexcopybuf; /* buttons.c */ int a; for(a=0; a<MAX_MTEX; a++) { @@ -1350,7 +1379,6 @@ void free_matcopybuf(void) MEM_freeN(matcopybuf.nodetree); matcopybuf.nodetree= NULL; } -// default_mtex(&mtexcopybuf); matcopied= 0; } @@ -1373,7 +1401,7 @@ void copy_matcopybuf(Material *ma) matcopybuf.mtex[a]= MEM_dupallocN(mtex); } } - matcopybuf.nodetree= ntreeCopyTree(ma->nodetree, 0); + matcopybuf.nodetree= ntreeCopyTree(ma->nodetree); matcopybuf.preview= NULL; matcopybuf.gpumaterial.first= matcopybuf.gpumaterial.last= NULL; matcopied= 1; @@ -1401,7 +1429,7 @@ void paste_matcopybuf(Material *ma) MEM_freeN(ma->nodetree); } - GPU_materials_free(ma); + GPU_material_free(ma); id= (ma->id); memcpy(ma, &matcopybuf, sizeof(Material)); @@ -1418,11 +1446,5 @@ void paste_matcopybuf(Material *ma) } } - ma->nodetree= ntreeCopyTree(matcopybuf.nodetree, 0); - - /* - BIF_preview_changed(ID_MA); - BIF_undo_push("Paste material settings"); - scrarea_queue_winredraw(curarea); - */ + ma->nodetree= ntreeCopyTree(matcopybuf.nodetree); } diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index e6f38e04d76..4f44875b7ea 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -1,4 +1,4 @@ -/** mball.c +/* mball.c * * MetaBalls are created from a single Object (with a name without number in it), * here the DispList and BoundBox also is located. @@ -48,8 +48,9 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_utildefines.h" + -#include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_main.h" @@ -76,7 +77,7 @@ void unlink_mball(MetaBall *mb) for(a=0; a<mb->totcol; a++) { if(mb->mat[a]) mb->mat[a]->id.us--; - mb->mat[a]= 0; + mb->mat[a]= NULL; } } @@ -86,14 +87,17 @@ void free_mball(MetaBall *mb) { unlink_mball(mb); - if(mb->adt) BKE_free_animdata((ID *)mb); + if(mb->adt) { + BKE_free_animdata((ID *)mb); + mb->adt = NULL; + } if(mb->mat) MEM_freeN(mb->mat); if(mb->bb) MEM_freeN(mb->bb); BLI_freelistN(&mb->elems); if(mb->disp.first) freedisplist(&mb->disp); } -MetaBall *add_mball(char *name) +MetaBall *add_mball(const char *name) { MetaBall *mb; @@ -138,9 +142,9 @@ void make_local_mball(MetaBall *mb) * - mixed: make copy */ - if(mb->id.lib==0) return; + if(mb->id.lib==NULL) return; if(mb->id.us==1) { - mb->id.lib= 0; + mb->id.lib= NULL; mb->id.flag= LIB_LOCAL; return; } @@ -155,7 +159,7 @@ void make_local_mball(MetaBall *mb) } if(local && lib==0) { - mb->id.lib= 0; + mb->id.lib= NULL; mb->id.flag= LIB_LOCAL; } else if(local && lib) { @@ -166,7 +170,7 @@ void make_local_mball(MetaBall *mb) while(ob) { if(ob->data==mb) { - if(ob->id.lib==0) { + if(ob->id.lib==NULL) { ob->data= mbn; mbn->id.us++; mb->id.us--; @@ -238,7 +242,7 @@ void tex_space_mball(Object *ob) float *data, min[3], max[3], loc[3], size[3]; int tot, doit=0; - if(ob->bb==0) ob->bb= MEM_callocN(sizeof(BoundBox), "mb boundbox"); + if(ob->bb==NULL) ob->bb= MEM_callocN(sizeof(BoundBox), "mb boundbox"); bb= ob->bb; /* Weird one, this. */ @@ -309,6 +313,19 @@ float *make_orco_mball(Object *ob, ListBase *dispbase) return orcodata; } + +/* Note on mball basis stuff 2.5x (this is a can of worms) + * This really needs a rewrite/refactorm its totally broken in anything other then basic cases + * Multiple Scenes + Set Scenes & mixing mball basis SHOULD work but fails to update the depsgraph on rename + * and linking into scenes or removal of basis mball. so take care when changing this code. + * + * Main idiot thing here is that the system returns find_basis_mball() objects which fail a is_basis_mball() test. + * + * Not only that but the depsgraph and ther areas depend on this behavior!, so making small fixes here isnt worth it. + * - campbell + */ + + /** \brief Test, if Object *ob is basic MetaBall. * * It test last character of Object ID name. If last character @@ -330,8 +347,8 @@ int is_mball_basis_for(Object *ob1, Object *ob2) int basis1nr, basis2nr; char basis1name[32], basis2name[32]; - splitIDname(ob1->id.name+2, basis1name, &basis1nr); - splitIDname(ob2->id.name+2, basis2name, &basis2nr); + BLI_split_name_num(basis1name, &basis1nr, ob1->id.name+2, '.'); + BLI_split_name_num(basis2name, &basis2nr, ob2->id.name+2, '.'); if(!strcmp(basis1name, basis2name)) return is_basis_mball(ob1); else return 0; @@ -352,16 +369,16 @@ void copy_mball_properties(Scene *scene, Object *active_object) int basisnr, obnr; char basisname[32], obname[32]; - splitIDname(active_object->id.name+2, basisname, &basisnr); + BLI_split_name_num(basisname, &basisnr, active_object->id.name+2, '.'); /* XXX recursion check, see scene.c, just too simple code this next_object() */ - if(F_ERROR==next_object(&sce_iter, 0, 0, 0)) + if(F_ERROR==next_object(&sce_iter, 0, NULL, NULL)) return; while(next_object(&sce_iter, 1, &base, &ob)) { if (ob->type==OB_MBALL) { if(ob!=active_object){ - splitIDname(ob->id.name+2, obname, &obnr); + BLI_split_name_num(obname, &obnr, ob->id.name+2, '.'); /* Object ob has to be in same "group" ... it means, that it has to have * same base of its name */ @@ -385,6 +402,8 @@ void copy_mball_properties(Scene *scene, Object *active_object) * its name. All MetaBalls with same base of name can be * blended. MetaBalls with different basic name can't be * blended. + * + * warning!, is_basis_mball() can fail on returned object, see long note above. */ Object *find_basis_mball(Scene *scene, Object *basis) { @@ -394,12 +413,12 @@ Object *find_basis_mball(Scene *scene, Object *basis) MetaElem *ml=NULL; int basisnr, obnr; char basisname[32], obname[32]; - - splitIDname(basis->id.name+2, basisname, &basisnr); + + BLI_split_name_num(basisname, &basisnr, basis->id.name+2, '.'); totelem= 0; /* XXX recursion check, see scene.c, just too simple code this next_object() */ - if(F_ERROR==next_object(&sce_iter, 0, 0, 0)) + if(F_ERROR==next_object(&sce_iter, 0, NULL, NULL)) return NULL; while(next_object(&sce_iter, 1, &base, &ob)) { @@ -415,7 +434,7 @@ Object *find_basis_mball(Scene *scene, Object *basis) else ml= mb->elems.first; } else{ - splitIDname(ob->id.name+2, obname, &obnr); + BLI_split_name_num(obname, &obnr, ob->id.name+2, '.'); /* object ob has to be in same "group" ... it means, that it has to have * same base of its name */ @@ -679,8 +698,8 @@ float metaball(float x, float y, float z) /* ******************************************** */ -int *indices=NULL; -int totindex, curindex; +static int *indices=NULL; +static int totindex, curindex; void accum_mballfaces(int i1, int i2, int i3, int i4) @@ -719,12 +738,12 @@ void accum_mballfaces(int i1, int i2, int i3, int i4) void *new_pgn_element(int size) { /* during polygonize 1000s of elements are allocated - * and never freed inbetween. Freeing only done at the end. + * and never freed in between. Freeing only done at the end. */ int blocksize= 16384; static int offs= 0; /* the current free address */ - static struct pgn_elements *cur= 0; - static ListBase lb= {0, 0}; + static struct pgn_elements *cur= NULL; + static ListBase lb= {NULL, NULL}; void *adr; if(size>10000 || size==0) { @@ -906,14 +925,14 @@ void testface(int i, int j, int k, CUBE* old, int bit, int c1, int c2, int c3, i newc.corners[FLIP(c3, bit)] = corn3; newc.corners[FLIP(c4, bit)] = corn4; - if(newc.corners[0]==0) newc.corners[0] = setcorner(p, i, j, k); - if(newc.corners[1]==0) newc.corners[1] = setcorner(p, i, j, k+1); - if(newc.corners[2]==0) newc.corners[2] = setcorner(p, i, j+1, k); - if(newc.corners[3]==0) newc.corners[3] = setcorner(p, i, j+1, k+1); - if(newc.corners[4]==0) newc.corners[4] = setcorner(p, i+1, j, k); - if(newc.corners[5]==0) newc.corners[5] = setcorner(p, i+1, j, k+1); - if(newc.corners[6]==0) newc.corners[6] = setcorner(p, i+1, j+1, k); - if(newc.corners[7]==0) newc.corners[7] = setcorner(p, i+1, j+1, k+1); + if(newc.corners[0]==NULL) newc.corners[0] = setcorner(p, i, j, k); + if(newc.corners[1]==NULL) newc.corners[1] = setcorner(p, i, j, k+1); + if(newc.corners[2]==NULL) newc.corners[2] = setcorner(p, i, j+1, k); + if(newc.corners[3]==NULL) newc.corners[3] = setcorner(p, i, j+1, k+1); + if(newc.corners[4]==NULL) newc.corners[4] = setcorner(p, i+1, j, k); + if(newc.corners[5]==NULL) newc.corners[5] = setcorner(p, i+1, j, k+1); + if(newc.corners[6]==NULL) newc.corners[6] = setcorner(p, i+1, j+1, k); + if(newc.corners[7]==NULL) newc.corners[7] = setcorner(p, i+1, j+1, k+1); p->cubes->cube= newc; } @@ -1012,7 +1031,7 @@ void makecubetable (void) for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c); for (e = 0; e < 12; e++) if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) { - INTLIST *ints = 0; + INTLIST *ints = NULL; INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist"); int start = e, edge = e; @@ -1061,7 +1080,7 @@ void BKE_freecubetable(void) MEM_freeN(lists); lists= nlists; } - cubetable[i]= 0; + cubetable[i]= NULL; } } @@ -1403,7 +1422,7 @@ void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) int i, j, k, c_i, c_j, c_k; int index[3]={1,0,-1}; float f =0.0f; - float in_v, out_v; + float in_v /*, out_v*/; MB_POINT workp; float tmp_v, workp_v, max_len, len, dx, dy, dz, nx, ny, nz, MAXN; @@ -1464,7 +1483,7 @@ void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) calc_mballco(ml, (float *)&out); - out_v = mbproc->function(out.x, out.y, out.z); + /*out_v = mbproc->function(out.x, out.y, out.z);*/ /*UNUSED*/ /* find "first points" on Implicit Surface of MetaElemnt ml */ workp.x = in.x; @@ -1563,8 +1582,8 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */ Object *bob; MetaBall *mb; MetaElem *ml; - float size, totsize, (*mat)[4] = NULL, (*imat)[4] = NULL, obinv[4][4], obmat[4][4], vec[3]; - float temp1[4][4], temp2[4][4], temp3[4][4]; //max=0.0; + float size, totsize, obinv[4][4], obmat[4][4], vec[3]; + //float max=0.0; int a, obnr, zero_size=0; char obname[32]; @@ -1572,10 +1591,10 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */ invert_m4_m4(obinv, ob->obmat); a= 0; - splitIDname(ob->id.name+2, obname, &obnr); + BLI_split_name_num(obname, &obnr, ob->id.name+2, '.'); /* make main array */ - next_object(&sce_iter, 0, 0, 0); + next_object(&sce_iter, 0, NULL, NULL); while(next_object(&sce_iter, 1, &base, &bob)) { if(bob->type==OB_MBALL) { @@ -1583,7 +1602,6 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */ ml= NULL; if(bob==ob && (base->flag & OB_FROMDUPLI)==0) { - mat= imat= 0; mb= ob->data; if(mb->editelems) ml= mb->editelems->first; @@ -1593,7 +1611,7 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */ char name[32]; int nr; - splitIDname(bob->id.name+2, name, &nr); + BLI_split_name_num(name, &nr, bob->id.name+2, '.'); if( strcmp(obname, name)==0 ) { mb= bob->data; @@ -1630,6 +1648,8 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */ while(ml) { if(!(ml->flag & MB_HIDE)) { int i; + float temp1[4][4], temp2[4][4], temp3[4][4]; + float (*mat)[4] = NULL, (*imat)[4] = NULL; float max_x, max_y, max_z, min_x, min_y, min_z; max_x = max_y = max_z = -3.4e38; @@ -2154,7 +2174,7 @@ void metaball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) if(G.moving && mb->flag==MB_UPDATE_FAST) return; curindex= totindex= 0; - indices= 0; + indices= NULL; thresh= mb->thresh; /* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */ @@ -2209,7 +2229,7 @@ void metaball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) mbproc.function = metaball; mbproc.size = width; mbproc.bounds = nr_cubes; - mbproc.cubes= 0; + mbproc.cubes= NULL; mbproc.delta = width/(float)(RES*RES); polygonize(&mbproc, mb); @@ -2231,7 +2251,7 @@ void metaball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) dl->parts= curindex; dl->index= indices; - indices= 0; + indices= NULL; a= mbproc.vertices.count; dl->verts= ve= MEM_mallocN(sizeof(float)*3*a, "mballverts"); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index f205d8f9e9a..f6679315606 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -44,6 +44,13 @@ #include "DNA_ipo_types.h" #include "DNA_customdata_types.h" +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_math.h" +#include "BLI_edgehash.h" +#include "BLI_utildefines.h" +#include "BLI_scanfill.h" + #include "BKE_animsys.h" #include "BKE_main.h" #include "BKE_customdata.h" @@ -53,12 +60,13 @@ #include "BKE_displist.h" #include "BKE_library.h" #include "BKE_material.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" #include "BKE_key.h" /* these 2 are only used by conversion functions */ #include "BKE_curve.h" /* -- */ #include "BKE_object.h" -#include "BKE_utildefines.h" #include "BKE_tessmesh.h" #include "BLI_edgehash.h" @@ -396,11 +404,11 @@ void unlink_mesh(Mesh *me) { int a; - if(me==0) return; + if(me==NULL) return; for(a=0; a<me->totcol; a++) { if(me->mat[a]) me->mat[a]->id.us--; - me->mat[a]= 0; + me->mat[a]= NULL; } if(me->key) { @@ -408,9 +416,9 @@ void unlink_mesh(Mesh *me) if (me->key->id.us == 0 && me->key->ipo ) me->key->ipo->id.us--; } - me->key= 0; + me->key= NULL; - if(me->texcomesh) me->texcomesh= 0; + if(me->texcomesh) me->texcomesh= NULL; } @@ -485,7 +493,7 @@ void free_dverts(MDeformVert *dvert, int totvert) MEM_freeN (dvert); } -Mesh *add_mesh(char *name) +Mesh *add_mesh(const char *name) { Mesh *me; @@ -600,9 +608,9 @@ void make_local_tface(Mesh *me) if(tface->tpage) { ima= tface->tpage; if(ima->id.lib) { - ima->id.lib= 0; + ima->id.lib= NULL; ima->id.flag= LIB_LOCAL; - new_id(0, (ID *)ima, 0); + new_id(NULL, (ID *)ima, NULL); } } } @@ -623,11 +631,11 @@ void make_local_mesh(Mesh *me) * - mixed: make copy */ - if(me->id.lib==0) return; + if(me->id.lib==NULL) return; if(me->id.us==1) { - me->id.lib= 0; + me->id.lib= NULL; me->id.flag= LIB_LOCAL; - new_id(0, (ID *)me, 0); + new_id(NULL, (ID *)me, NULL); if(me->mtface) make_local_tface(me); @@ -644,9 +652,9 @@ void make_local_mesh(Mesh *me) } if(local && lib==0) { - me->id.lib= 0; + me->id.lib= NULL; me->id.flag= LIB_LOCAL; - new_id(0, (ID *)me, 0); + new_id(NULL, (ID *)me, NULL); if(me->mtface) make_local_tface(me); @@ -658,7 +666,7 @@ void make_local_mesh(Mesh *me) ob= bmain->object.first; while(ob) { if( me==get_mesh(ob) ) { - if(ob->id.lib==0) { + if(ob->id.lib==NULL) { set_mesh(ob, men); } } @@ -673,7 +681,7 @@ void boundbox_mesh(Mesh *me, float *loc, float *size) float min[3], max[3]; float mloc[3], msize[3]; - if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); + if(me->bb==NULL) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); bb= me->bb; if (!loc) loc= mloc; @@ -786,11 +794,11 @@ void transform_mesh_orco_verts(Mesh *me, float (*orco)[3], int totvert, int inve int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr) { /* first test if the face is legal */ - if(mface->v3 && mface->v3==mface->v4) { + if((mface->v3 || nr==4) && mface->v3==mface->v4) { mface->v4= 0; nr--; } - if(mface->v2 && mface->v2==mface->v3) { + if((mface->v2 || mface->v4) && mface->v2==mface->v3) { mface->v3= mface->v4; mface->v4= 0; nr--; @@ -802,6 +810,32 @@ int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr) nr--; } + /* check corrupt cases, bowtie geometry, cant handle these because edge data wont exist so just return 0 */ + if(nr==3) { + if( + /* real edges */ + mface->v1==mface->v2 || + mface->v2==mface->v3 || + mface->v3==mface->v1 + ) { + return 0; + } + } + else if(nr==4) { + if( + /* real edges */ + mface->v1==mface->v2 || + mface->v2==mface->v3 || + mface->v3==mface->v4 || + mface->v4==mface->v1 || + /* across the face */ + mface->v1==mface->v3 || + mface->v2==mface->v4 + ) { + return 0; + } + } + /* prevent a zero at wrong index location */ if(nr==3) { if(mface->v3==0) { @@ -832,16 +866,18 @@ int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr) Mesh *get_mesh(Object *ob) { - if(ob==0) return 0; + if(ob==NULL) return NULL; if(ob->type==OB_MESH) return ob->data; - else return 0; + else return NULL; } void set_mesh(Object *ob, Mesh *me) { - Mesh *old=0; + Mesh *old=NULL; + + multires_force_update(ob); - if(ob==0) return; + if(ob==NULL) return; if(ob->type==OB_MESH) { old= ob->data; @@ -852,6 +888,8 @@ void set_mesh(Object *ob, Mesh *me) } test_object_materials((ID *)me); + + test_object_modifiers(ob); } /* ************** make edges in a Mesh, for outside of editmode */ @@ -903,7 +941,7 @@ static void mfaces_strip_loose(MFace *mface, int *totface) } /* Create edges based on known verts and faces */ -static void make_edges_mdata(MVert *allvert, MFace *allface, int totvert, int totface, +static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, int UNUSED(totvert), int totface, int old, MEdge **alledge, int *_totedge) { MFace *mface; @@ -1020,6 +1058,23 @@ void mesh_strip_loose_faces(Mesh *me) me->totface = b; } +void mesh_strip_loose_edges(Mesh *me) +{ + int a,b; + + for (a=b=0; a<me->totedge; a++) { + if (me->medge[a].v1!=me->medge[a].v2) { + if (a!=b) { + memcpy(&me->medge[b],&me->medge[a],sizeof(me->medge[b])); + CustomData_copy_data(&me->edata, &me->edata, a, b, 1); + CustomData_free_elem(&me->edata, a, 1); + } + b++; + } + } + me->totedge = b; +} + void mball_to_mesh(ListBase *lb, Mesh *me) { DispList *dl; @@ -1029,7 +1084,7 @@ void mball_to_mesh(ListBase *lb, Mesh *me) int a, *index; dl= lb->first; - if(dl==0) return; + if(dl==NULL) return; if(dl->type==DL_INDEX4) { me->totvert= dl->nr; @@ -1077,7 +1132,7 @@ void mball_to_mesh(ListBase *lb, Mesh *me) int nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert, MEdge **alledge, int *totedge, MFace **allface, int *totface) { - return nurbs_to_mdata_customdb(ob, &((Curve *)ob->data)->disp, + return nurbs_to_mdata_customdb(ob, &ob->disp, allvert, totvert, alledge, totedge, allface, totface); } @@ -1093,9 +1148,13 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int float *data; int a, b, ofs, vertcount, startvert, totvert=0, totvlak=0; int p1, p2, p3, p4, *index; + int conv_polys= 0; cu= ob->data; + conv_polys|= cu->flag & CU_3D; /* 2d polys are filled with DL_INDEX3 displists */ + conv_polys|= ob->type == OB_SURF; /* surf polys are never filled */ + /* count */ dl= dispbase->first; while(dl) { @@ -1104,8 +1163,10 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int totvlak+= dl->parts*(dl->nr-1); } else if(dl->type==DL_POLY) { - totvert+= dl->parts*dl->nr; - totvlak+= dl->parts*dl->nr; + if(conv_polys) { + totvert+= dl->parts*dl->nr; + totvlak+= dl->parts*dl->nr; + } } else if(dl->type==DL_SURF) { totvert+= dl->parts*dl->nr; @@ -1125,7 +1186,7 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int } *allvert= mvert= MEM_callocN(sizeof (MVert) * totvert, "nurbs_init mvert"); - *allface= mface= MEM_callocN(sizeof (MVert) * totvert, "nurbs_init mface"); + *allface= mface= MEM_callocN(sizeof (MVert) * totvlak, "nurbs_init mface"); /* verts and faces */ vertcount= 0; @@ -1157,24 +1218,26 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int } else if(dl->type==DL_POLY) { - startvert= vertcount; - a= dl->parts*dl->nr; - data= dl->verts; - while(a--) { - VECCOPY(mvert->co, data); - data+=3; - vertcount++; - mvert++; - } + if(conv_polys) { + startvert= vertcount; + a= dl->parts*dl->nr; + data= dl->verts; + while(a--) { + VECCOPY(mvert->co, data); + data+=3; + vertcount++; + mvert++; + } - for(a=0; a<dl->parts; a++) { - ofs= a*dl->nr; - for(b=0; b<dl->nr; b++) { - mface->v1= startvert+ofs+b; - if(b==dl->nr-1) mface->v2= startvert+ofs; - else mface->v2= startvert+ofs+b+1; - if(smooth) mface->flag |= ME_SMOOTH; - mface++; + for(a=0; a<dl->parts; a++) { + ofs= a*dl->nr; + for(b=0; b<dl->nr; b++) { + mface->v1= startvert+ofs+b; + if(b==dl->nr-1) mface->v2= startvert+ofs; + else mface->v2= startvert+ofs+b+1; + if(smooth) mface->flag |= ME_SMOOTH; + mface++; + } } } } @@ -1196,6 +1259,7 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int mface->v2= startvert+index[2]; mface->v3= startvert+index[1]; mface->v4= 0; + mface->mat_nr= (unsigned char)dl->col; test_index_face(mface, NULL, 0, 3); if(smooth) mface->flag |= ME_SMOOTH; @@ -1313,7 +1377,7 @@ void nurbs_to_mesh(Object *ob) tex_space_mesh(me); - cu->mat= 0; + cu->mat= NULL; cu->totcol= 0; if(ob->data) { @@ -1555,14 +1619,12 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth) mf->flag &= ~ME_SMOOTH; } } - -// XXX do this in caller DAG_id_flush_update(&me->id, OB_RECALC_DATA); } void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float **faceNors_r) { float (*tnorms)[3]= MEM_callocN(numVerts*sizeof(*tnorms), "tnorms"); - float *fnors= MEM_mallocN(sizeof(*fnors)*3*numFaces, "meshnormals"); + float *fnors= MEM_callocN(sizeof(*fnors)*3*numFaces, "meshnormals"); int i; for (i=0; i<numFaces; i++) { @@ -1782,7 +1844,7 @@ void mesh_pmv_free(PartialVisibility *pv) MEM_freeN(pv); } -void mesh_pmv_revert(Object *ob, Mesh *me) +void mesh_pmv_revert(Mesh *me) { if(me->pv) { unsigned i; @@ -1816,15 +1878,13 @@ void mesh_pmv_revert(Object *ob, Mesh *me) me->pv->edge_map= NULL; MEM_freeN(me->pv->vert_map); me->pv->vert_map= NULL; - -// XXX do this in caller DAG_id_flush_update(&me->id, OB_RECALC_DATA); } } -void mesh_pmv_off(Object *ob, Mesh *me) +void mesh_pmv_off(Mesh *me) { - if(ob && me->pv) { - mesh_pmv_revert(ob, me); + if(me->pv) { + mesh_pmv_revert(me); MEM_freeN(me->pv); me->pv= NULL; } @@ -1946,7 +2006,7 @@ int mesh_recalcTesselation(CustomData *fdata, } BLI_addfilledge(lastv, firstv); - BLI_edgefill(0, 0); + BLI_edgefill(0); for (f=fillfacebase.first; f; f=f->next) { BLI_array_growone(mf); BLI_array_growone(origIndex); @@ -2129,7 +2189,10 @@ int mesh_center_median(Mesh *me, float cent[3]) for(mvert= me->mvert; i--; mvert++) { add_v3_v3(cent, mvert->co); } - mul_v3_fl(cent, 1.0f/(float)me->totvert); + /* otherwise we get NAN for 0 verts */ + if(me->totvert) { + mul_v3_fl(cent, 1.0f/(float)me->totvert); + } return (me->totvert != 0); } diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c new file mode 100644 index 00000000000..0821b4188fe --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -0,0 +1,379 @@ +/* + * $Id$ + * + * ***** 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) 2011 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BLO_sys_types.h" + +#include "BLI_utildefines.h" +#include "BLI_edgehash.h" + +#include "BKE_DerivedMesh.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_mesh.h" + +#define SELECT 1 + +typedef union { + uint32_t verts[2]; + int64_t edval; +} EdgeUUID; + +typedef struct SortFace { +// unsigned int v[4]; + EdgeUUID es[4]; + unsigned int index; +} SortFace; + +static void edge_store_assign(uint32_t verts[2], const uint32_t v1, const uint32_t v2) +{ + if(v1 < v2) { + verts[0]= v1; + verts[1]= v2; + } + else { + verts[0]= v2; + verts[1]= v1; + } +} + +static void edge_store_from_mface_quad(EdgeUUID es[4], MFace *mf) +{ + edge_store_assign(es[0].verts, mf->v1, mf->v2); + edge_store_assign(es[1].verts, mf->v2, mf->v3); + edge_store_assign(es[2].verts, mf->v3, mf->v4); + edge_store_assign(es[3].verts, mf->v4, mf->v1); +} + +static void edge_store_from_mface_tri(EdgeUUID es[3], MFace *mf) +{ + edge_store_assign(es[0].verts, mf->v1, mf->v2); + edge_store_assign(es[1].verts, mf->v2, mf->v3); + edge_store_assign(es[2].verts, mf->v3, mf->v1); + es[3].verts[0] = es[3].verts[1] = UINT_MAX; +} + +static int int64_cmp(const void *v1, const void *v2) +{ + const int64_t x1= *(const int64_t *)v1; + const int64_t x2= *(const int64_t *)v2; + + if( x1 > x2 ) return 1; + else if( x1 < x2 ) return -1; + return 0; +} + +static int search_face_cmp(const void *v1, const void *v2) +{ + const SortFace *sfa= v1, *sfb= v2; + + if (sfa->es[0].edval > sfb->es[0].edval) return 1; + else if (sfa->es[0].edval < sfb->es[0].edval) return -1; + + else if (sfa->es[1].edval > sfb->es[1].edval) return 1; + else if (sfa->es[1].edval < sfb->es[1].edval) return -1; + + else if (sfa->es[2].edval > sfb->es[2].edval) return 1; + else if (sfa->es[2].edval < sfb->es[2].edval) return -1; + + else if (sfa->es[3].edval > sfb->es[3].edval) return 1; + else if (sfa->es[3].edval < sfb->es[3].edval) return -1; + else return 0; + +} + +int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge *medges, int totedge, MFace *mfaces, int totface, const short do_verbose, const short do_fixes) +{ +# define PRINT if(do_verbose) printf +# define REMOVE_EDGE_TAG(_med) { _med->v2= _med->v1; do_edge_free= 1; } +# define REMOVE_FACE_TAG(_mf) { _mf->v3=0; do_face_free= 1; } + +// MVert *mv; + MEdge *med; + MFace *mf; + MFace *mf_prev; + int i; + + int do_face_free= FALSE; + int do_edge_free= FALSE; + + int do_edge_recalc= FALSE; + + EdgeHash *edge_hash = BLI_edgehash_new(); + + SortFace *sort_faces= MEM_callocN(sizeof(SortFace) * totface, "search faces"); + SortFace *sf; + SortFace *sf_prev; + int totsortface= 0; + + BLI_assert(!(do_fixes && me == NULL)); + + PRINT("ED_mesh_validate: verts(%d), edges(%d), faces(%d)\n", totvert, totedge, totface); + + if(totedge == 0 && totface != 0) { + PRINT(" locical error, %d faces and 0 edges\n", totface); + do_edge_recalc= TRUE; + } + + for(i=0, med= medges; i<totedge; i++, med++) { + int remove= FALSE; + if(med->v1 == med->v2) { + PRINT(" edge %d: has matching verts, both %d\n", i, med->v1); + remove= do_fixes; + } + if(med->v1 >= totvert) { + PRINT(" edge %d: v1 index out of range, %d\n", i, med->v1); + remove= do_fixes; + } + if(med->v2 >= totvert) { + PRINT(" edge %d: v2 index out of range, %d\n", i, med->v2); + remove= do_fixes; + } + + if(BLI_edgehash_haskey(edge_hash, med->v1, med->v2)) { + PRINT(" edge %d: is a duplicate of, %d\n", i, GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, med->v1, med->v2))); + remove= do_fixes; + } + + if(remove == FALSE){ + BLI_edgehash_insert(edge_hash, med->v1, med->v2, SET_INT_IN_POINTER(i)); + } + else { + REMOVE_EDGE_TAG(med); + } + } + + for(i=0, mf=mfaces, sf=sort_faces; i<totface; i++, mf++) { + int remove= FALSE; + int fidx; + unsigned int fv[4]; + + fidx = mf->v4 ? 3:2; + do { + fv[fidx]= *(&(mf->v1) + fidx); + if(fv[fidx] >= totvert) { + PRINT(" face %d: 'v%d' index out of range, %d\n", i, fidx + 1, fv[fidx]); + remove= do_fixes; + } + } while (fidx--); + + if(remove == FALSE) { + if(mf->v4) { + if(mf->v1 == mf->v2) { PRINT(" face %d: verts invalid, v1/v2 both %d\n", i, mf->v1); remove= do_fixes; } + if(mf->v1 == mf->v3) { PRINT(" face %d: verts invalid, v1/v3 both %d\n", i, mf->v1); remove= do_fixes; } + if(mf->v1 == mf->v4) { PRINT(" face %d: verts invalid, v1/v4 both %d\n", i, mf->v1); remove= do_fixes; } + + if(mf->v2 == mf->v3) { PRINT(" face %d: verts invalid, v2/v3 both %d\n", i, mf->v2); remove= do_fixes; } + if(mf->v2 == mf->v4) { PRINT(" face %d: verts invalid, v2/v4 both %d\n", i, mf->v2); remove= do_fixes; } + + if(mf->v3 == mf->v4) { PRINT(" face %d: verts invalid, v3/v4 both %d\n", i, mf->v3); remove= do_fixes; } + } + else { + if(mf->v1 == mf->v2) { PRINT(" faceT %d: verts invalid, v1/v2 both %d\n", i, mf->v1); remove= do_fixes; } + if(mf->v1 == mf->v3) { PRINT(" faceT %d: verts invalid, v1/v3 both %d\n", i, mf->v1); remove= do_fixes; } + + if(mf->v2 == mf->v3) { PRINT(" faceT %d: verts invalid, v2/v3 both %d\n", i, mf->v2); remove= do_fixes; } + } + + if(remove == FALSE) { + if(totedge) { + if(mf->v4) { + if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) { PRINT(" face %d: edge v1/v2 (%d,%d) is missing egde data\n", i, mf->v1, mf->v2); do_edge_recalc= TRUE; } + if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) { PRINT(" face %d: edge v2/v3 (%d,%d) is missing egde data\n", i, mf->v2, mf->v3); do_edge_recalc= TRUE; } + if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v4)) { PRINT(" face %d: edge v3/v4 (%d,%d) is missing egde data\n", i, mf->v3, mf->v4); do_edge_recalc= TRUE; } + if(!BLI_edgehash_haskey(edge_hash, mf->v4, mf->v1)) { PRINT(" face %d: edge v4/v1 (%d,%d) is missing egde data\n", i, mf->v4, mf->v1); do_edge_recalc= TRUE; } + } + else { + if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) { PRINT(" face %d: edge v1/v2 (%d,%d) is missing egde data\n", i, mf->v1, mf->v2); do_edge_recalc= TRUE; } + if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) { PRINT(" face %d: edge v2/v3 (%d,%d) is missing egde data\n", i, mf->v2, mf->v3); do_edge_recalc= TRUE; } + if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v1)) { PRINT(" face %d: edge v3/v1 (%d,%d) is missing egde data\n", i, mf->v3, mf->v1); do_edge_recalc= TRUE; } + } + } + + sf->index = i; + + if(mf->v4) { + edge_store_from_mface_quad(sf->es, mf); + + qsort(sf->es, 4, sizeof(int64_t), int64_cmp); + } + else { + edge_store_from_mface_tri(sf->es, mf); + qsort(sf->es, 3, sizeof(int64_t), int64_cmp); + } + + totsortface++; + sf++; + } + } + if(remove) { + REMOVE_FACE_TAG(mf); + } + } + + qsort(sort_faces, totsortface, sizeof(SortFace), search_face_cmp); + + sf= sort_faces; + sf_prev= sf; + sf++; + + for(i=1; i<totsortface; i++, sf++) { + int remove= FALSE; + /* on a valid mesh, code below will never run */ + if(memcmp(sf->es, sf_prev->es, sizeof(sf_prev->es)) == 0) { + mf= mfaces + sf->index; + + if(do_verbose) { + mf_prev= mfaces + sf_prev->index; + if(mf->v4) { + PRINT(" face %d & %d: are duplicates (%d,%d,%d,%d) (%d,%d,%d,%d)\n", sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf->v4, mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4); + } + else { + PRINT(" face %d & %d: are duplicates (%d,%d,%d) (%d,%d,%d)\n", sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf_prev->v1, mf_prev->v2, mf_prev->v3); + } + } + + remove= do_fixes; + } + else { + sf_prev= sf; + } + + if(remove) { + REMOVE_FACE_TAG(mf); + } + } + + BLI_edgehash_free(edge_hash, NULL); + MEM_freeN(sort_faces); + + PRINT("BKE_mesh_validate: finished\n\n"); + +# undef PRINT +# undef REMOVE_EDGE_TAG +# undef REMOVE_FACE_TAG + + if(me) { + if(do_face_free) { + mesh_strip_loose_faces(me); + } + + if (do_edge_free) { + mesh_strip_loose_edges(me); + } + + if(do_fixes && do_edge_recalc) { + BKE_mesh_calc_edges(me, TRUE); + } + } + + return (do_face_free || do_edge_free || do_edge_recalc); +} + +int BKE_mesh_validate(Mesh *me, int do_verbose) +{ + printf("MESH: %s\n", me->id.name+2); + return BKE_mesh_validate_arrays(me, me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface, do_verbose, TRUE); +} + +int BKE_mesh_validate_dm(DerivedMesh *dm) +{ + return BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), TRUE, FALSE); +} + +void BKE_mesh_calc_edges(Mesh *mesh, int update) +{ + CustomData edata; + EdgeHashIterator *ehi; + MFace *mf = mesh->mface; + MEdge *med, *med_orig; + EdgeHash *eh = BLI_edgehash_new(); + int i, totedge, totface = mesh->totface; + + if(mesh->totedge==0) + update= 0; + + if(update) { + /* assume existing edges are valid + * useful when adding more faces and generating edges from them */ + med= mesh->medge; + for(i= 0; i<mesh->totedge; i++, med++) + BLI_edgehash_insert(eh, med->v1, med->v2, med); + } + + for (i = 0; i < totface; i++, mf++) { + if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) + BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL); + if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3)) + BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL); + + if (mf->v4) { + if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4)) + BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL); + if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1)) + BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL); + } else { + if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1)) + BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL); + } + } + + totedge = BLI_edgehash_size(eh); + + /* write new edges into a temporary CustomData */ + memset(&edata, 0, sizeof(edata)); + CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); + + ehi = BLI_edgehashIterator_new(eh); + med = CustomData_get_layer(&edata, CD_MEDGE); + for(i = 0; !BLI_edgehashIterator_isDone(ehi); + BLI_edgehashIterator_step(ehi), ++i, ++med) { + + if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) { + *med= *med_orig; /* copy from the original */ + } else { + BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); + med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */ + } + } + BLI_edgehashIterator_free(ehi); + + /* free old CustomData and assign new one */ + CustomData_free(&mesh->edata, mesh->totedge); + mesh->edata = edata; + mesh->totedge = totedge; + + mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE); + + BLI_edgehash_free(eh, NULL); +} diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 63f0f1fa091..7439a47a746 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -40,30 +40,33 @@ #include <math.h> #include <float.h> +#include "MEM_guardedalloc.h" + #include "DNA_armature_types.h" #include "DNA_object_types.h" #include "DNA_meshdata_types.h" -#include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BKE_bmesh.h" #include "BKE_cloth.h" #include "BKE_key.h" +#include "BKE_multires.h" #include "MOD_modifiertypes.h" ModifierTypeInfo *modifierType_getInfo(ModifierType type) { - static ModifierTypeInfo *types[NUM_MODIFIER_TYPES]; + static ModifierTypeInfo *types[NUM_MODIFIER_TYPES]= {NULL}; static int types_init = 1; if (types_init) { - modifier_type_init(types, type); /* MOD_utils.c */ + modifier_type_init(types); /* MOD_utils.c */ types_init= 0; } - if(type >= 0 && type < NUM_MODIFIER_TYPES && - types[type]->name[0] != '\0') { + /* type unsigned, no need to chech < 0 */ + if(type < NUM_MODIFIER_TYPES && types[type]->name[0] != '\0') { return types[type]; } else { @@ -146,14 +149,14 @@ ModifierData *modifiers_findByName(Object *ob, const char *name) void modifiers_clearErrors(Object *ob) { ModifierData *md = ob->modifiers.first; - int qRedraw = 0; + /* int qRedraw = 0; */ for (; md; md=md->next) { if (md->error) { MEM_freeN(md->error); md->error = NULL; - qRedraw = 1; + /* qRedraw = 1; */ } } } @@ -215,14 +218,15 @@ int modifier_sameTopology(ModifierData *md) return ( mti->type == eModifierTypeType_OnlyDeform || mti->type == eModifierTypeType_Nonconstructive); } -void modifier_setError(ModifierData *md, char *format, ...) +void modifier_setError(ModifierData *md, const char *format, ...) { - char buffer[2048]; + char buffer[512]; va_list ap; va_start(ap, format); - vsprintf(buffer, format, ap); + vsnprintf(buffer, sizeof(buffer), format, ap); va_end(ap); + buffer[sizeof(buffer) - 1]= '\0'; if (md->error) MEM_freeN(md->error); @@ -235,13 +239,19 @@ void modifier_setError(ModifierData *md, char *format, ...) * there * * also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg - * then is NULL) + * then is NULL) + * also used for some mesh tools to give warnings */ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *lastPossibleCageIndex_r, int virtual_) { ModifierData *md = (virtual_)? modifiers_getVirtualModifierList(ob): ob->modifiers.first; int i, cageIndex = -1; + if(lastPossibleCageIndex_r) { + /* ensure the value is initialized */ + *lastPossibleCageIndex_r= -1; + } + /* Find the last modifier acting on the cage. */ for (i=0; md; i++,md=md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -491,7 +501,7 @@ int modifier_isCorrectableDeformed(ModifierData *md) return 0; } -int modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob) +int modifiers_isCorrectableDeformed(Object *ob) { ModifierData *md = modifiers_getVirtualModifierList(ob); @@ -526,5 +536,21 @@ void modifier_freeTemporaryData(ModifierData *md) } } +/* ensure modifier correctness when changing ob->data */ +void test_object_modifiers(Object *ob) +{ + ModifierData *md; + + /* just multires checked for now, since only multires + modifies mesh data */ + + if(ob->type != OB_MESH) return; + for(md = ob->modifiers.first; md; md = md->next) { + if(md->type == eModifierType_Multires) { + MultiresModifierData *mmd = (MultiresModifierData*)md; + multiresModifier_set_levels_from_disps(mmd, ob); + } + } +} diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 4b54114505e..f2c5a9cbf37 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -37,6 +37,8 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_pbvh.h" +#include "BLI_editVert.h" +#include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" #include "BKE_mesh.h" @@ -45,7 +47,9 @@ #include "BKE_paint.h" #include "BKE_scene.h" #include "BKE_subsurf.h" -#include "BKE_utildefines.h" +#include "BKE_tessmesh.h" + +#include "BKE_object.h" #include "CCGSubSurf.h" @@ -89,6 +93,36 @@ MultiresModifierData *find_multires_modifier_before(Scene *scene, ModifierData * return NULL; } +/* used for applying scale on mdisps layer and syncing subdivide levels when joining objects + use_first - return first multires modifier if all multires'es are disabled +*/ +MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, int use_first) +{ + ModifierData *md; + MultiresModifierData *mmd= NULL, *firstmmd= NULL; + + /* find first active multires modifier */ + for(md = ob->modifiers.first; md; md = md->next) { + if(md->type == eModifierType_Multires) { + if(!firstmmd) + firstmmd= (MultiresModifierData*)md; + + if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + mmd= (MultiresModifierData*)md; + break; + } + } + } + + if(!mmd && use_first) { + /* active multires have not been found + try to use first one */ + return firstmmd; + } + + return mmd; +} + static int multires_get_level(Object *ob, MultiresModifierData *mmd, int render) { if(render) @@ -151,68 +185,6 @@ void multires_force_render_update(Object *ob) multires_force_update(ob); } -/* XXX */ -#if 0 -void multiresModifier_join(Object *ob) -{ - Base *base = NULL; - int highest_lvl = 0; - - /* First find the highest level of subdivision */ - base = FIRSTBASE; - while(base) { - if(TESTBASELIB_BGMODE(v3d, scene, base) && base->object->type==OB_MESH) { - ModifierData *md; - for(md = base->object->modifiers.first; md; md = md->next) { - if(md->type == eModifierType_Multires) { - int totlvl = ((MultiresModifierData*)md)->totlvl; - if(totlvl > highest_lvl) - highest_lvl = totlvl; - - /* Ensure that all updates are processed */ - multires_force_update(base->object); - } - } - } - base = base->next; - } - - /* No multires meshes selected */ - if(highest_lvl == 0) - return; - - /* Subdivide all the displacements to the highest level */ - base = FIRSTBASE; - while(base) { - if(TESTBASELIB_BGMODE(v3d, scene, base) && base->object->type==OB_MESH) { - ModifierData *md = NULL; - MultiresModifierData *mmd = NULL; - - for(md = base->object->modifiers.first; md; md = md->next) { - if(md->type == eModifierType_Multires) - mmd = (MultiresModifierData*)md; - } - - /* If the object didn't have multires enabled, give it a new modifier */ - if(!mmd) { - md = base->object->modifiers.first; - - while(md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) - md = md->next; - - mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires); - BLI_insertlinkbefore(&base->object->modifiers, md, mmd); - modifier_unique_name(&base->object->modifiers, mmd); - } - - if(mmd) - multiresModifier_subdivide(mmd, base->object, highest_lvl - mmd->totlvl, 0, 0); - } - base = base->next; - } -} -#endif - int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd, Object *ob, DerivedMesh *srcdm) { @@ -229,7 +201,7 @@ int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd, return 1; } - mrdm->release(mrdm); + if(mrdm) mrdm->release(mrdm); return 0; } @@ -275,6 +247,60 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm return result; } +/* reset the multires levels to match the number of mdisps */ +static int get_levels_from_disps(Object *ob) +{ + Mesh *me = ob->data; + MDisps *mdisp, *md; + int i, j, totlvl= 0; + + mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS); + + for(i = 0; i < me->totpoly; ++i) { + int S = me->mpoly[i].totloop; + + md = mdisp + me->mpoly[i].loopstart; + for (j=0; j<me->mpoly[i].totloop; j++, md++) { + if(md->totdisp == 0) continue; + + while(1) { + int side = (1 << (totlvl-1)) + 1; + int lvl_totdisp = side*side*S; + if(md->totdisp == lvl_totdisp) + break; + else if(md->totdisp < lvl_totdisp) + --totlvl; + else + ++totlvl; + + } + + break; + } + } + + return totlvl; +} + +/* reset the multires levels to match the number of mdisps */ +void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob) +{ + Mesh *me = ob->data; + MDisps *mdisp; + + if(me->edit_btmesh) + mdisp = CustomData_get_layer(&me->edit_btmesh->bm->ldata, CD_MDISPS); + else + mdisp = CustomData_get_layer(&me->ldata, CD_MDISPS); + + if(mdisp) { + mmd->totlvl = get_levels_from_disps(ob); + mmd->lvl = MIN2(mmd->sculptlvl, mmd->totlvl); + mmd->sculptlvl = MIN2(mmd->sculptlvl, mmd->totlvl); + mmd->renderlvl = MIN2(mmd->renderlvl, mmd->totlvl); + } +} + static void multires_set_tot_mdisps(Mesh *me, int lvl) { MDisps *mdisps= CustomData_get_layer(&me->ldata, CD_MDISPS); @@ -351,11 +377,9 @@ static void multires_copy_dm_grid(DMGridData *gridA, DMGridData *gridB, int size } } -/* direction=1 for delete higher, direction=0 for lower (not implemented yet) */ -void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction) +static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) { - Mesh *me = get_mesh(ob); - int lvl = multires_get_level(ob, mmd, 0); + Mesh *me = (Mesh*)ob->data; int levels = mmd->totlvl - lvl; MDisps *mdisps; @@ -365,7 +389,7 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire multires_force_update(ob); - if(mdisps && levels > 0 && direction == 1) { + if(mdisps && levels > 0) { if(lvl > 0) { MLoop *ml = me->mloop; int nsize = multires_side_tot[lvl]; @@ -403,11 +427,31 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire multires_set_tot_level(ob, mmd, lvl); } +/* direction=1 for delete higher, direction=0 for lower (not implemented yet) */ +void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction) +{ + Mesh *me = get_mesh(ob); + int lvl = multires_get_level(ob, mmd, 0); + int levels = mmd->totlvl - lvl; + MDisps *mdisps; + + multires_set_tot_mdisps(me, mmd->totlvl); + CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); + mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); + + multires_force_update(ob); + + if(mdisps && levels > 0 && direction == 1) { + multires_del_higher(mmd, ob, lvl); + } + + multires_set_tot_level(ob, mmd, lvl); +} + static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple) { - MultiresModifierData mmd; + MultiresModifierData mmd= {{NULL}}; - memset(&mmd, 0, sizeof(MultiresModifierData)); mmd.lvl = lvl; mmd.sculptlvl = lvl; mmd.renderlvl = lvl; @@ -417,11 +461,10 @@ static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lv return multires_dm_create_from_derived(&mmd, 1, dm, ob, 0, 0); } -static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal) +static DerivedMesh *subsurf_dm_create_local(Object *UNUSED(ob), DerivedMesh *dm, int lvl, int simple, int optimal) { - SubsurfModifierData smd; + SubsurfModifierData smd= {{NULL}}; - memset(&smd, 0, sizeof(SubsurfModifierData)); smd.levels = smd.renderLevels = lvl; smd.flags |= eSubsurfModifierFlag_SubsurfUv; if(simple) @@ -432,12 +475,133 @@ static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl return subsurf_make_derived_from_derived(dm, &smd, 0, NULL, 0, 0); } -void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updateblock, int simple) + + +/* assumes no is normalized; return value's sign is negative if v is on + the other side of the plane */ +static float v3_dist_from_plane(float v[3], float center[3], float no[3]) +{ + float s[3]; + sub_v3_v3v3(s, v, center); + return dot_v3v3(s, no); +} + +void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob) +{ + DerivedMesh *cddm, *dispdm, *origdm; + Mesh *me; + ListBase *fmap; + float (*origco)[3]; + int i, j, offset, totlvl; + + multires_force_update(ob); + + me = get_mesh(ob); + totlvl = mmd->totlvl; + + /* nothing to do */ + if(!totlvl) + return; + + /* XXX - probably not necessary to regenerate the cddm so much? */ + + /* generate highest level with displacements */ + cddm = CDDM_from_mesh(me, NULL); + DM_set_only_copy(cddm, CD_MASK_BAREMESH); + dispdm = multires_dm_create_local(ob, cddm, totlvl, totlvl, 0); + cddm->release(cddm); + + /* copy the new locations of the base verts into the mesh */ + offset = dispdm->getNumVerts(dispdm) - me->totvert; + for(i = 0; i < me->totvert; ++i) { + dispdm->getVertCo(dispdm, offset + i, me->mvert[i].co); + } + + /* heuristic to produce a better-fitting base mesh */ + + cddm = CDDM_from_mesh(me, NULL); + fmap = cddm->getFaceMap(ob, cddm); + origco = MEM_callocN(sizeof(float)*3*me->totvert, "multires apply base origco"); + for(i = 0; i < me->totvert ;++i) + copy_v3_v3(origco[i], me->mvert[i].co); + + for(i = 0; i < me->totvert; ++i) { + IndexNode *n; + float avg_no[3] = {0,0,0}, center[3] = {0,0,0}, push[3]; + float dist; + int tot; + + /* don't adjust verts not used by at least one face */ + if(!fmap[i].first) + continue; + + /* find center */ + for(n = fmap[i].first, tot = 0; n; n = n->next) { + MFace *f = &me->mface[n->index]; + int S = f->v4 ? 4 : 3; + + /* this double counts, not sure if that's bad or good */ + for(j = 0; j < S; ++j) { + int vndx = (&f->v1)[j]; + if(vndx != i) { + add_v3_v3(center, origco[vndx]); + ++tot; + } + } + } + mul_v3_fl(center, 1.0f / tot); + + /* find normal */ + for(n = fmap[i].first; n; n = n->next) { + MFace *f = &me->mface[n->index]; + int S = f->v4 ? 4 : 3; + float v[4][3], no[3]; + + for(j = 0; j < S; ++j) { + int vndx = (&f->v1)[j]; + if(vndx == i) + copy_v3_v3(v[j], center); + else + copy_v3_v3(v[j], origco[vndx]); + } + + if(S == 4) + normal_quad_v3(no, v[0], v[1], v[2], v[3]); + else + normal_tri_v3(no, v[0], v[1], v[2]); + add_v3_v3(avg_no, no); + } + normalize_v3(avg_no); + + /* push vertex away from the plane */ + dist = v3_dist_from_plane(me->mvert[i].co, center, avg_no); + copy_v3_v3(push, avg_no); + mul_v3_fl(push, dist); + add_v3_v3(me->mvert[i].co, push); + + } + + MEM_freeN(origco); + cddm->release(cddm); + + /* subdivide the mesh to highest level without displacements */ + cddm = CDDM_from_mesh(me, NULL); + DM_set_only_copy(cddm, CD_MASK_BAREMESH); + origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0); + cddm->release(cddm); + + /* calc disps */ + multiresModifier_disp_run(dispdm, me, 1, 0, origdm->getGridData(origdm), totlvl); + + origdm->release(origdm); + dispdm->release(dispdm); +} + +static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl, int updateblock, int simple) { Mesh *me = ob->data; MDisps *mdisps; int lvl= mmd->totlvl; - int totlvl= mmd->totlvl+1; if(totlvl > multires_max_levels) return; @@ -510,6 +674,11 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat multires_set_tot_level(ob, mmd, totlvl); } +void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updateblock, int simple) +{ + multires_subdivide(mmd, ob, mmd->totlvl+1, updateblock, simple); +} + static void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3]) { if(axis == 0) { @@ -541,7 +710,7 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int MPoly *mpoly = me->mpoly; MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); int *gridOffset; - int i, k, numGrids, gridSize, dGridSize, dSkip; + int i, k, /*numGrids,*/ gridSize, dGridSize, dSkip; if(!mdisps) { if(invert) @@ -550,7 +719,7 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int return; } - numGrids = dm->getNumGrids(dm); + /*numGrids = dm->getNumGrids(dm);*/ /*UNUSED*/ gridSize = dm->getGridSize(dm); gridData = dm->getGridData(dm); gridOffset = dm->getGridOffset(dm); @@ -747,7 +916,7 @@ void multires_stitch_grids(Object *ob) } DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob, - int useRenderParams, int isFinalCalc) + int useRenderParams, int UNUSED(isFinalCalc)) { Mesh *me= ob->data; DerivedMesh *result; @@ -802,7 +971,7 @@ DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int loca ***************************/ /* Adapted from sculptmode.c */ -static void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v) +void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v) { int x, y, x2, y2; const int st_max = st - 1; @@ -843,7 +1012,7 @@ static void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u add_v3_v3v3(out, d2[0], d2[1]); } -static void old_mdisps_rotate(int S, int newside, int oldside, int x, int y, float *u, float *v) +static void old_mdisps_rotate(int S, int UNUSED(newside), int oldside, int x, int y, float *u, float *v) { float offset = oldside*0.5f - 0.5f; @@ -998,7 +1167,12 @@ static void create_old_vert_edge_map(ListBase **map, IndexNode **mem, const Mult static MultiresFace *find_old_face(ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4) { IndexNode *n1; - int v[4] = {v1, v2, v3, v4}, i, j; + int v[4], i, j; + + v[0]= v1; + v[1]= v2; + v[2]= v3; + v[3]= v4; for(n1 = map[v1].first; n1; n1 = n1->next) { int fnd[4] = {0, 0, 0, 0}; @@ -1145,18 +1319,18 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl) MultiresLevel *lvl, *lvl1; Multires *mr= me->mr; MVert *vsrc, *vdst; - int src, dst; + unsigned int src, dst; int st = multires_side_tot[totlvl - 1] - 1; int extedgelen = multires_side_tot[totlvl] - 2; int *vvmap; // inorder for dst, map to src int crossedgelen; - int i, j, s, x, totvert, tottri, totquad; + int s, x, tottri, totquad; + unsigned int i, j, totvert; src = 0; - dst = 0; vsrc = mr->verts; vdst = dm->getVertArray(dm); - totvert = dm->getNumVerts(dm); + totvert = (unsigned int)dm->getNumVerts(dm); vvmap = MEM_callocN(sizeof(int) * totvert, "multires vvmap"); lvl1 = mr->levels.first; @@ -1247,7 +1421,7 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl) fmem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires fmem"); emem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires emem"); lvl = lvl1; - for(i = 0; i < mr->level_count - 1; ++i) { + for(i = 0; i < (unsigned int)mr->level_count - 1; ++i) { create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface); create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge); lvl = lvl->next; @@ -1282,9 +1456,9 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl) dst = ldst; } - lvl = lvl->next; + /*lvl = lvl->next;*/ /*UNUSED*/ - for(i = 0; i < mr->level_count - 1; ++i) { + for(i = 0; i < (unsigned int)(mr->level_count - 1); ++i) { MEM_freeN(fmap[i]); MEM_freeN(fmem[i]); MEM_freeN(emap[i]); @@ -1306,6 +1480,52 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl) multires_mvert_to_ss(dm, vdst); } +/* Copy the first-level vcol data to the mesh, if it exists */ +/* Warning: higher-level vcol data will be lost */ +static void multires_load_old_vcols(Mesh *me) +{ + MultiresLevel *lvl; + MultiresColFace *colface; + MCol *mcol; + int i, j; + + if(!(lvl = me->mr->levels.first)) + return; + + if(!(colface = lvl->colfaces)) + return; + + /* older multires format never supported multiple vcol layers, + so we can assume the active vcol layer is the correct one */ + if(!(mcol = CustomData_get_layer(&me->fdata, CD_MCOL))) + return; + + for(i = 0; i < me->totface; ++i) { + for(j = 0; j < 4; ++j) { + mcol[i*4 + j].a = colface[i].col[j].a; + mcol[i*4 + j].r = colface[i].col[j].r; + mcol[i*4 + j].g = colface[i].col[j].g; + mcol[i*4 + j].b = colface[i].col[j].b; + } + } +} + +/* Copy the first-level face-flag data to the mesh */ +static void multires_load_old_face_flags(Mesh *me) +{ + MultiresLevel *lvl; + MultiresFace *faces; + int i; + + if(!(lvl = me->mr->levels.first)) + return; + + if(!(faces = lvl->faces)) + return; + + for(i = 0; i < me->totface; ++i) + me->mface[i].flag = faces[i].flag; +} void multires_load_old(Object *ob, Mesh *me) { @@ -1367,8 +1587,593 @@ void multires_load_old(Object *ob, Mesh *me) memset(&me->mr->vdata, 0, sizeof(CustomData)); memset(&me->mr->fdata, 0, sizeof(CustomData)); + multires_load_old_vcols(me); + multires_load_old_face_flags(me); + /* Remove the old multires */ multires_free(me->mr); me->mr= NULL; } +static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob) +{ + MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1); + MultiresModifierData *to_mmd= get_multires_modifier(scene, to_ob, 1); + + if(!mmd) { + /* object could have MDISP even when there is no multires modifier + this could lead to troubles due to i've got no idea how mdisp could be + upsampled correct without modifier data. + just remove mdisps if no multires present (nazgul) */ + + Mesh *me= (Mesh*)ob->data; + + CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface); + CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface); + } + + if(!mmd || !to_mmd) return; + + if(mmd->totlvl>to_mmd->totlvl) multires_del_higher(mmd, ob, to_mmd->totlvl); + else multires_subdivide(mmd, ob, to_mmd->totlvl, 0, mmd->simple); +} + +static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) +{ + DerivedMesh *dm= NULL, *cddm= NULL, *subdm= NULL; + DMGridData **gridData, **subGridData; + Mesh *me= (Mesh*)ob->data; + MFace *mface= me->mface; + MDisps *mdisps; + int *gridOffset; + int i, /*numGrids,*/ gridSize, dGridSize, dSkip, totvert; + float (*vertCos)[3] = NULL; + MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1); + MultiresModifierData high_mmd; + + CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); + mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); + + if(!mdisps || !mmd) return; + + /* we need derived mesh created from highest resolution */ + high_mmd= *mmd; + high_mmd.lvl= high_mmd.totlvl; + + /* unscaled multires with applied displacement */ + subdm= get_multires_dm(scene, &high_mmd, ob); + + /* prepare scaled CDDM to create ccgDN */ + cddm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); + + totvert= cddm->getNumVerts(cddm); + vertCos= MEM_mallocN(sizeof(*vertCos) * totvert, "multiresScale vertCos"); + cddm->getVertCos(cddm, vertCos); + for(i=0; i<totvert; i++) + mul_m3_v3(smat, vertCos[i]); + CDDM_apply_vert_coords(cddm, vertCos); + MEM_freeN(vertCos); + + /* scaled ccgDM for tangent space of object with applied scale */ + dm= subsurf_dm_create_local(ob, cddm, high_mmd.totlvl, high_mmd.simple, 0); + cddm->release(cddm); + + /*numGrids= dm->getNumGrids(dm);*/ /*UNUSED*/ + gridSize= dm->getGridSize(dm); + gridData= dm->getGridData(dm); + gridOffset= dm->getGridOffset(dm); + subGridData= subdm->getGridData(subdm); + + dGridSize= multires_side_tot[high_mmd.totlvl]; + dSkip= (dGridSize-1)/(gridSize-1); + + #pragma omp parallel for private(i) if(me->totface*gridSize*gridSize*4 >= CCG_OMP_LIMIT) + for(i = 0; i < me->totface; ++i) { + const int numVerts= mface[i].v4 ? 4 : 3; + MDisps *mdisp= &mdisps[i]; + int S, x, y, gIndex = gridOffset[i]; + + for(S = 0; S < numVerts; ++S, ++gIndex) { + DMGridData *grid= gridData[gIndex]; + DMGridData *subgrid= subGridData[gIndex]; + float (*dispgrid)[3]= &mdisp->disps[S*dGridSize*dGridSize]; + + for(y = 0; y < gridSize; y++) { + for(x = 0; x < gridSize; x++) { + float *co= grid[x + y*gridSize].co; + float *sco= subgrid[x + y*gridSize].co; + float *no= grid[x + y*gridSize].no; + float *data= dispgrid[dGridSize*y*dSkip + x*dSkip]; + float mat[3][3], tx[3], ty[3], disp[3]; + + /* construct tangent space matrix */ + grid_tangent(gridSize, gIndex, x, y, 0, gridData, tx); + normalize_v3(tx); + + grid_tangent(gridSize, gIndex, x, y, 1, gridData, ty); + normalize_v3(ty); + + column_vectors_to_mat3(mat, tx, ty, no); + + /* scale subgrid coord and calculate displacement */ + mul_m3_v3(smat, sco); + sub_v3_v3v3(disp, sco, co); + + /* convert difference to tangent space */ + invert_m3(mat); + mul_v3_m3v3(data, mat, disp); + } + } + } + } + + dm->release(dm); + subdm->release(subdm); +} + +int multires_mdisp_corners(MDisps *s) +{ + int lvl= 13; + + while(lvl > 0) { + int side = (1 << (lvl-1)) + 1; + if ((s->totdisp % (side*side)) == 0) return s->totdisp / (side*side); + lvl--; + } + + return 0; +} + +void multiresModifier_scale_disp(Scene *scene, Object *ob) +{ + float smat[3][3]; + + /* object's scale matrix */ + object_scale_to_mat3(ob, smat); + + multires_apply_smat(scene, ob, smat); +} + +void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob) +{ + float smat[3][3], tmat[3][3], mat[3][3]; + multires_sync_levels(scene, ob, to_ob); + + /* construct scale matrix for displacement */ + object_scale_to_mat3(to_ob, tmat); + invert_m3(tmat); + object_scale_to_mat3(ob, smat); + mul_m3_m3m3(mat, smat, tmat); + + multires_apply_smat(scene, ob, mat); +} + +/* update multires data after topology changing */ +void multires_topology_changed(Scene *scene, Object *ob) +{ + Mesh *me= (Mesh*)ob->data; + MDisps *mdisp= NULL, *cur= NULL; + int i, grid= 0, corners; + MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1); + + if(mmd) + multires_set_tot_mdisps(me, mmd->totlvl); + + CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); + mdisp= CustomData_get_layer(&me->fdata, CD_MDISPS); + + if(!mdisp) return; + + cur= mdisp; + for(i = 0; i < me->totface; i++, cur++) { + if(mdisp->totdisp) { + corners= multires_mdisp_corners(mdisp); + grid= mdisp->totdisp / corners; + + break; + } + } + + for(i = 0; i < me->totface; i++, mdisp++) { + int nvert= me->mface[i].v4 ? 4 : 3; + + /* allocate memory for mdisp, the whole disp layer would be erased otherwise */ + if(!mdisp->totdisp) { + if(grid) { + mdisp->totdisp= nvert*grid; + mdisp->disps= MEM_callocN(mdisp->totdisp*sizeof(float)*3, "mdisp topology"); + } + + continue; + } + + corners= multires_mdisp_corners(mdisp); + + if(corners!=nvert) { + mdisp->totdisp= (mdisp->totdisp/corners)*nvert; + + if(mdisp->disps) + MEM_freeN(mdisp->disps); + + mdisp->disps= MEM_callocN(mdisp->totdisp*sizeof(float)*3, "mdisp topology"); + } + } +} + +/* makes displacement along grid boundary symmetrical */ +void multires_mdisp_smooth_bounds(MDisps *disps) +{ + int x, y, side, S, corners; + float (*out)[3]; + + corners = multires_mdisp_corners(disps); + side = sqrt(disps->totdisp / corners); + + out = disps->disps; + for(S = 0; S < corners; S++) { + for(y = 0; y < side; ++y) { + for(x = 0; x < side; ++x, ++out) { + float (*dispgrid)[3]; + float *data; + + if(x != 0 && y != 0) continue; + + if(corners == 4) { + if(S == 0) { + if(y == 0) { + dispgrid = &disps->disps[1*side*side]; + data = dispgrid[side * x + 0]; + + (*out)[0] = (*out)[0] + data[1]; + (*out)[1] = (*out)[1] - data[0]; + (*out)[2] = (*out)[2] + data[2]; + + mul_v3_fl(*out, 0.5); + + data[0] = -(*out)[1]; + data[1] = (*out)[0]; + data[2] = (*out)[2]; + } else if (x == 0) { + dispgrid = &disps->disps[3 * side * side]; + data = dispgrid[side * 0 + y]; + + (*out)[0] = (*out)[0] - data[1]; + (*out)[1] = (*out)[1] + data[0]; + (*out)[2] = (*out)[2] + data[2]; + + mul_v3_fl(*out, 0.5); + + data[0] = (*out)[1]; + data[1] = -(*out)[0]; + data[2] = (*out)[2]; + } + } else if (S == 2) { + if(y == 0) { + dispgrid = &disps->disps[3 * side * side]; + data = dispgrid[side * x + 0]; + + (*out)[0] = (*out)[0] + data[1]; + (*out)[1] = (*out)[1] - data[0]; + (*out)[2] = (*out)[2] + data[2]; + + mul_v3_fl(*out, 0.5); + + data[0] = -(*out)[1]; + data[1] = (*out)[0]; + data[2] = (*out)[2]; + } else if(x == 0) { + dispgrid = &disps->disps[1 * side * side]; + data = dispgrid[side * 0 + y]; + + (*out)[0] = (*out)[0] - data[1]; + (*out)[1] = (*out)[1] + data[0]; + (*out)[2] = (*out)[2] + data[2]; + + mul_v3_fl(*out, 0.5); + + data[0] = (*out)[1]; + data[1] = -(*out)[0]; + data[2] = (*out)[2]; + } + } + } else if (corners == 3) { + if(S == 0) { + if(y == 0) { + dispgrid = &disps->disps[1*side*side]; + data = dispgrid[side * x + 0]; + + (*out)[0] = (*out)[0] + data[1]; + (*out)[1] = (*out)[1] - data[0]; + (*out)[2] = (*out)[2] + data[2]; + + mul_v3_fl(*out, 0.5); + + data[0] = -(*out)[1]; + data[1] = (*out)[0]; + data[2] = (*out)[2]; + } else if (x == 0) { + dispgrid = &disps->disps[2 * side * side]; + data = dispgrid[side * 0 + y]; + + (*out)[0] = (*out)[0] - data[1]; + (*out)[1] = (*out)[1] + data[0]; + (*out)[2] = (*out)[2] + data[2]; + + mul_v3_fl(*out, 0.5); + + data[0] = (*out)[1]; + data[1] = -(*out)[0]; + data[2] = (*out)[2]; + } + } else if (S == 2) { + if(x == 0) { + dispgrid = &disps->disps[1 * side * side]; + data = dispgrid[side * 0 + y]; + + (*out)[0] = (*out)[0] - data[1]; + (*out)[1] = (*out)[1] + data[0]; + (*out)[2] = (*out)[2] + data[2]; + + mul_v3_fl(*out, 0.5); + + data[0] = (*out)[1]; + data[1] = -(*out)[0]; + data[2] = (*out)[2]; + } + } + } + } + } + } +} + +/***************** Multires interpolation stuff *****************/ + +static void mdisp_get_crn_rect(int face_side, float crn[3][4][2]) +{ + float offset = face_side*0.5f - 0.5f; + float mid[2]; + + mid[0] = offset * 4 / 3; + mid[1] = offset * 2 / 3; + + crn[0][0][0] = mid[0]; crn[0][0][1] = mid[1]; + crn[0][1][0] = offset; crn[0][1][1] = 0; + crn[0][2][0] = 0; crn[0][2][1] = 0; + crn[0][3][0] = offset; crn[0][3][1] = offset; + + crn[1][0][0] = mid[0]; crn[1][0][1] = mid[1]; + crn[1][1][0] = offset * 2; crn[1][1][1] = offset; + crn[1][2][0] = offset * 2; crn[1][2][1] = 0; + crn[1][3][0] = offset; crn[1][3][1] = 0; + + crn[2][0][0] = mid[0]; crn[2][0][1] = mid[1]; + crn[2][1][0] = offset; crn[2][1][1] = offset; + crn[2][2][0] = offset * 2; crn[2][2][1] = offset * 2; + crn[2][3][0] = offset * 2; crn[2][3][1] = offset; +} + +static int mdisp_pt_in_crn(float p[2], float crn[4][2]) +{ + float v[2][2]; + float a[2][2]; + + sub_v2_v2v2(v[0], crn[1], crn[0]); + sub_v2_v2v2(v[1], crn[3], crn[0]); + + sub_v2_v2v2(a[0], p, crn[0]); + sub_v2_v2v2(a[1], crn[2], crn[0]); + + if(cross_v2v2(a[0], v[0]) * cross_v2v2(a[1], v[0]) < 0) + return 0; + + if(cross_v2v2(a[0], v[1]) * cross_v2v2(a[1], v[1]) < 0) + return 0; + + return 1; +} + +static void face_to_crn_interp(float u, float v, float v1[2], float v2[2], float v3[2], float v4[2], float *x) +{ + float a = (v4[1]-v3[1])*v2[0]+(-v4[1]+v3[1])*v1[0]+(-v2[1]+v1[1])*v4[0]+(v2[1]-v1[1])*v3[0]; + float b = (v3[1]-v)*v2[0]+(v4[1]-2*v3[1]+v)*v1[0]+(-v4[1]+v3[1]+v2[1]-v1[1])*u+(v4[0]-v3[0])*v-v1[1]*v4[0]+(-v2[1]+2*v1[1])*v3[0]; + float c = (v3[1]-v)*v1[0]+(-v3[1]+v1[1])*u+v3[0]*v-v1[1]*v3[0]; + float d = b * b - 4 * a * c; + float x1, x2; + + if(a == 0) { + *x = -c / b; + return; + } + + x1 = (-b - sqrtf(d)) / (2 * a); + x2 = (-b + sqrtf(d)) / (2 * a); + + *x = maxf(x1, x2); +} + +void mdisp_rot_crn_to_face(const int S, const int corners, const int face_side, const float x, const float y, float *u, float *v) +{ + float offset = face_side*0.5f - 0.5f; + + if(corners == 4) { + if(S == 1) { *u= offset + x; *v = offset - y; } + if(S == 2) { *u= offset + y; *v = offset + x; } + if(S == 3) { *u= offset - x; *v = offset + y; } + if(S == 0) { *u= offset - y; *v = offset - x; } + } else { + float crn[3][4][2], vec[4][2]; + float p[2]; + + mdisp_get_crn_rect(face_side, crn); + + interp_v2_v2v2(vec[0], crn[S][0], crn[S][1], x / offset); + interp_v2_v2v2(vec[1], crn[S][3], crn[S][2], x / offset); + interp_v2_v2v2(vec[2], crn[S][0], crn[S][3], y / offset); + interp_v2_v2v2(vec[3], crn[S][1], crn[S][2], y / offset); + + isect_seg_seg_v2_point(vec[0], vec[1], vec[2], vec[3], p); + + (*u) = p[0]; + (*v) = p[1]; + } +} + +int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y) +{ + const float offset = face_side*0.5f - 0.5f; + int S = 0; + + if (corners == 4) { + if(u <= offset && v <= offset) S = 0; + else if(u > offset && v <= offset) S = 1; + else if(u > offset && v > offset) S = 2; + else if(u <= offset && v >= offset) S = 3; + + if(S == 0) { + *y = offset - u; + *x = offset - v; + } else if(S == 1) { + *x = u - offset; + *y = offset - v; + } else if(S == 2) { + *y = u - offset; + *x = v - offset; + } else if(S == 3) { + *x= offset - u; + *y = v - offset; + } + } else { + float crn[3][4][2]; + float p[2] = {u, v}; + + mdisp_get_crn_rect(face_side, crn); + + for (S = 0; S < 3; ++S) { + if (mdisp_pt_in_crn(p, crn[S])) + break; + } + + face_to_crn_interp(u, v, crn[S][0], crn[S][1], crn[S][3], crn[S][2], &p[0]); + face_to_crn_interp(u, v, crn[S][0], crn[S][3], crn[S][1], crn[S][2], &p[1]); + + *x = p[0] * offset; + *y = p[1] * offset; + } + + return S; +} + +void mdisp_apply_weight(const int S, const int corners, int x, int y, const int face_side, + float crn_weight[4][2], float *u_r, float *v_r) +{ + float u, v, xl, yl; + float mid1[2], mid2[2], mid3[2]; + + mdisp_rot_crn_to_face(S, corners, face_side, x, y, &u, &v); + + if(corners == 4) { + xl = u / (face_side - 1); + yl = v / (face_side - 1); + + mid1[0] = crn_weight[0][0] * (1 - xl) + crn_weight[1][0] * xl; + mid1[1] = crn_weight[0][1] * (1 - xl) + crn_weight[1][1] * xl; + mid2[0] = crn_weight[3][0] * (1 - xl) + crn_weight[2][0] * xl; + mid2[1] = crn_weight[3][1] * (1 - xl) + crn_weight[2][1] * xl; + mid3[0] = mid1[0] * (1 - yl) + mid2[0] * yl; + mid3[1] = mid1[1] * (1 - yl) + mid2[1] * yl; + } else { + yl = v / (face_side - 1); + + if(v == face_side - 1) xl = 1; + else xl = 1 - (face_side - 1 - u) / (face_side - 1 - v); + + mid1[0] = crn_weight[0][0] * (1 - xl) + crn_weight[1][0] * xl; + mid1[1] = crn_weight[0][1] * (1 - xl) + crn_weight[1][1] * xl; + mid3[0] = mid1[0] * (1 - yl) + crn_weight[2][0] * yl; + mid3[1] = mid1[1] * (1 - yl) + crn_weight[2][1] * yl; + } + + *u_r = mid3[0]; + *v_r = mid3[1]; +} + +void mdisp_flip_disp(const int S, const int corners, const float axis_x[2], const float axis_y[2], float disp[3]) +{ + float crn_x[2], crn_y[2]; + float vx[2], vy[2], coord[2]; + + if (corners == 4) { + float x[4][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; + float y[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; + + copy_v2_v2(crn_x, x[S]); + copy_v2_v2(crn_y, y[S]); + + mul_v2_v2fl(vx, crn_x, disp[0]); + mul_v2_v2fl(vy, crn_y, disp[1]); + add_v2_v2v2(coord, vx, vy); + + project_v2_v2v2(vx, coord, axis_x); + project_v2_v2v2(vy, coord, axis_y); + + disp[0] = len_v2(vx); + disp[1] = len_v2(vy); + + if(dot_v2v2(vx, axis_x) < 0) + disp[0] = -disp[0]; + + if(dot_v2v2(vy, axis_y) < 0) + disp[1] = -disp[1]; + } else { + /* XXX: it was very overhead code to support displacement flipping + for case of tris without visible profit. + Maybe its not really big limitation? for now? (nazgul) */ + disp[0] = 0; + disp[1] = 0; + } +} + +/* Join two triangular displacements into one quad + Corners mapping: + 2 -------- 3 + | \ tri2 | + | \ | + | tri1 \ | + 0 -------- 1 */ +void mdisp_join_tris(MDisps *dst, MDisps *tri1, MDisps *tri2) +{ + int side, st; + int S, x, y, crn; + float face_u, face_v, crn_u, crn_v; + float (*out)[3]; + MDisps *src; + + if(dst->disps) + MEM_freeN(dst->disps); + + side = sqrt(tri1->totdisp / 3); + st = (side<<1)-1; + + dst->totdisp = 4 * side * side; + out = dst->disps = MEM_callocN(3*dst->totdisp*sizeof(float), "join disps"); + + for(S = 0; S < 4; S++) + for(y = 0; y < side; ++y) + for(x = 0; x < side; ++x, ++out) { + mdisp_rot_crn_to_face(S, 4, st, x, y, &face_u, &face_v); + face_u = st - 1 - face_u; + + if(face_v > face_u) { + src = tri2; + face_u = st - 1 - face_u; + face_v = st - 1 - face_v; + } else src = tri1; + + crn = mdisp_rot_face_to_crn(3, st, face_u, face_v, &crn_u, &crn_v); + + old_mdisps_bilinear((*out), &src->disps[crn*side*side], side, crn_u, crn_v); + (*out)[0] = 0; + (*out)[1] = 0; + } +} diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index b053d615756..df012c47f66 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -36,6 +36,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BLI_ghash.h" #include "DNA_anim_types.h" @@ -46,7 +47,7 @@ #include "BKE_nla.h" #include "BKE_global.h" #include "BKE_library.h" -#include "BKE_utildefines.h" + #include "RNA_access.h" #include "nla_private.h" @@ -77,7 +78,7 @@ void free_nlastrip (ListBase *strips, NlaStrip *strip) /* remove reference to action */ if (strip->act) - strip->act->id.us--; + id_us_min(&strip->act->id); /* free remapping info */ //if (strip->remap) @@ -159,7 +160,7 @@ NlaStrip *copy_nlastrip (NlaStrip *strip) /* increase user-count of action */ if (strip_d->act) - strip_d->act->id.us++; + id_us_plus(&strip_d->act->id); /* copy F-Curves and modifiers */ copy_fcurves(&strip_d->fcurves, &strip->fcurves); @@ -362,7 +363,7 @@ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short return strip->end - scale*(cframe - strip->actstart); } else if (mode == NLATIME_CONVERT_UNMAP) { - return strip->actend - (strip->end - cframe) / scale; + return (strip->end + (strip->actstart * scale - cframe)) / scale; } else /* if (mode == NLATIME_CONVERT_EVAL) */{ if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) { @@ -513,7 +514,7 @@ short BKE_nlastrips_has_space (ListBase *strips, float start, float end) /* if start frame of strip is past the target end-frame, that means that * we've gone past the window we need to check for, so things are fine */ - if (strip->start > end) + if (strip->start >= end) return 1; /* if the end of the strip is greater than either of the boundaries, the range @@ -590,7 +591,7 @@ short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip) /* find the right place to add the strip to the nominated track */ for (ns= strips->first; ns; ns= ns->next) { /* if current strip occurs after the new strip, add it before */ - if (ns->start > strip->end) { + if (ns->start >= strip->end) { BLI_insertlinkbefore(strips, ns, strip); not_added= 0; break; @@ -682,7 +683,7 @@ void BKE_nlastrips_clear_metastrip (ListBase *strips, NlaStrip *strip) } /* free the meta-strip now */ - BLI_freelinkN(strips, strip); + free_nlastrip(strips, strip); } /* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips @@ -916,9 +917,14 @@ void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a) /* Check if there is any space in the given track to add a strip of the given length */ short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end) { - /* sanity checks */ - if ((nlt == NULL) || IS_EQ(start, end)) + /* sanity checks + * - track must exist + * - track must be editable + * - bounds cannot be equal (0-length is nasty) + */ + if ((nlt == NULL) || (nlt->flag & NLATRACK_PROTECTED) || IS_EQ(start, end)) return 0; + if (start > end) { puts("BKE_nlatrack_has_space() error... start and end arguments swapped"); SWAP(float, start, end); @@ -1206,6 +1212,11 @@ void BKE_nlastrip_validate_fcurves (NlaStrip *strip) /* Sanity Validation ------------------------------------ */ +static int nla_editbone_name_check(void *arg, const char *name) +{ + return BLI_ghash_haskey((GHash *)arg, (void *)name); +} + /* Find (and set) a unique name for a strip from the whole AnimData block * Uses a similar method to the BLI method, but is implemented differently * as we need to ensure that the name is unique over several lists of tracks, @@ -1259,28 +1270,8 @@ void BKE_nlastrip_validate_name (AnimData *adt, NlaStrip *strip) /* if the hash-table has a match for this name, try other names... * - in an extreme case, it might not be able to find a name, but then everything else in Blender would fail too :) */ - if (BLI_ghash_haskey(gh, strip->name)) { - char tempname[128]; - int number = 1; - char *dot; - - /* Strip off the suffix */ - dot = strrchr(strip->name, '.'); - if (dot) *dot=0; - - /* Try different possibilities */ - for (number = 1; number <= 999; number++) { - /* assemble alternative name */ - BLI_snprintf(tempname, 128, "%s.%03d", strip->name, number); - - /* if hash doesn't have this, set it */ - if (BLI_ghash_haskey(gh, tempname) == 0) { - BLI_strncpy(strip->name, tempname, sizeof(strip->name)); - break; - } - } - } - + BLI_uniquename_cb(nla_editbone_name_check, (void *)gh, "NlaStrip", '.', strip->name, sizeof(strip->name)); + /* free the hash... */ BLI_ghash_free(gh, NULL, NULL); } @@ -1329,7 +1320,7 @@ static void nlastrip_get_endpoint_overlaps (NlaStrip *strip, NlaTrack *track, fl } /* Determine auto-blending for the given strip */ -void BKE_nlastrip_validate_autoblends (NlaTrack *nlt, NlaStrip *nls) +static void BKE_nlastrip_validate_autoblends (NlaTrack *nlt, NlaStrip *nls) { float *ps=NULL, *pe=NULL; float *ns=NULL, *ne=NULL; @@ -1447,7 +1438,7 @@ void BKE_nla_action_pushdown (AnimData *adt) /* do other necessary work on strip */ if (strip) { /* clear reference to action now that we've pushed it onto the stack */ - adt->action->id.us--; + id_us_min(&adt->action->id); adt->action= NULL; /* if the strip is the first one in the track it lives in, check if there @@ -1585,7 +1576,7 @@ void BKE_nla_tweakmode_exit (AnimData *adt) /* Baking Tools ------------------------------------------- */ -void BKE_nla_bake (Scene *scene, ID *id, AnimData *adt, int flag) +static void BKE_nla_bake (Scene *scene, ID *UNUSED(id), AnimData *adt, int UNUSED(flag)) { /* verify that data is valid diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index eb09ecf2e6e..53bac9171ae 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -27,25 +27,34 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON #include <Python.h> #endif +#include "MEM_guardedalloc.h" + #include <stdlib.h> #include <stddef.h> #include <string.h> +#include <limits.h> #include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_node_types.h" + +#include "BLI_listbase.h" #include "RNA_access.h" +#include "BKE_animsys.h" +#include "BKE_action.h" #include "BKE_fcurve.h" -#include "BKE_animsys.h" /* BKE_free_animdata only */ - +#include "BKE_node.h" +#include "BKE_utildefines.h" +#include "BKE_node.h" #include "PIL_time.h" - #include "CMP_node.h" #include "intern/CMP_util.h" /* stupid include path... */ @@ -62,22 +71,14 @@ ListBase node_all_textures = {NULL, NULL}; /* ************** Type stuff ********** */ -static bNodeType *node_get_type(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id) +static bNodeType *node_get_type(bNodeTree *ntree, int type, ID *id) { - if(type==NODE_GROUP) { - if(ngroup && GS(ngroup->id.name)==ID_NT) { - return ngroup->owntype; - } - return NULL; - } - else { - bNodeType *ntype = ntree->alltypes.first; - for(; ntype; ntype= ntype->next) - if(ntype->type==type && id==ntype->id ) - return ntype; - - return NULL; - } + bNodeType *ntype = ntree->alltypes.first; + for(; ntype; ntype= ntype->next) + if(ntype->type==type && id==ntype->id ) + return ntype; + + return NULL; } void ntreeInitTypes(bNodeTree *ntree) @@ -100,11 +101,11 @@ void ntreeInitTypes(bNodeTree *ntree) if(node->type==NODE_DYNAMIC) { bNodeType *stype= NULL; if(node->id==NULL) { /* empty script node */ - stype= node_get_type(ntree, node->type, NULL, NULL); + stype= node_get_type(ntree, node->type, NULL); } else { /* not an empty script node */ - stype= node_get_type(ntree, node->type, NULL, node->id); + stype= node_get_type(ntree, node->type, node->id); if(!stype) { - stype= node_get_type(ntree, node->type, NULL, NULL); + stype= node_get_type(ntree, node->type, NULL); /* needed info if the pynode script fails now: */ if (node->id) node->storage= ntree; } else { @@ -116,7 +117,7 @@ void ntreeInitTypes(bNodeTree *ntree) if(node->typeinfo) node->typeinfo->initfunc(node); } else { - node->typeinfo= node_get_type(ntree, node->type, (bNodeTree *)node->id, NULL); + node->typeinfo= node_get_type(ntree, node->type, NULL); } if(node->typeinfo==NULL) { @@ -150,9 +151,6 @@ static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype) else sock->limit= stype->limit; sock->type= stype->type; - sock->to_index= stype->own_index; - sock->tosock= stype->internsock; - sock->ns.vec[0]= stype->val1; sock->ns.vec[1]= stype->val2; sock->ns.vec[2]= stype->val3; @@ -166,6 +164,30 @@ static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype) return sock; } +static bNodeSocket *node_add_group_socket(ListBase *lb, bNodeSocket *gsock) +{ + bNodeSocket *sock= MEM_callocN(sizeof(bNodeSocket), "sock"); + + /* make a copy of the group socket */ + *sock = *gsock; + sock->link = NULL; + sock->next = sock->prev = NULL; + sock->new_sock = NULL; + sock->ns.data = NULL; + + sock->own_index = gsock->own_index; + sock->groupsock = gsock; + /* XXX hack: group socket input/output roles are inverted internally, + * need to change the limit value when making actual node sockets from them. + */ + sock->limit = (gsock->limit==1 ? 0xFFF : 1); + + if(lb) + BLI_addtail(lb, sock); + + return sock; +} + static void node_rem_socket(bNodeTree *ntree, ListBase *lb, bNodeSocket *sock) { bNodeLink *link, *next; @@ -186,18 +208,16 @@ static bNodeSocket *verify_socket(ListBase *lb, bNodeSocketType *stype) bNodeSocket *sock; for(sock= lb->first; sock; sock= sock->next) { - /* both indices are zero for non-groups, otherwise it's a unique index */ - if(sock->to_index==stype->own_index) - if(strncmp(sock->name, stype->name, NODE_MAXSTR)==0) - break; + if(strncmp(sock->name, stype->name, NODE_MAXSTR)==0) + break; } if(sock) { sock->type= stype->type; /* in future, read this from tydefs! */ if(stype->limit==0) sock->limit= 0xFFF; else sock->limit= stype->limit; + sock->ns.min= stype->min; sock->ns.max= stype->max; - sock->tosock= stype->internsock; BLI_remlink(lb, sock); @@ -208,6 +228,37 @@ static bNodeSocket *verify_socket(ListBase *lb, bNodeSocketType *stype) } } +static bNodeSocket *verify_group_socket(ListBase *lb, bNodeSocket *gsock) +{ + bNodeSocket *sock; + + for(sock= lb->first; sock; sock= sock->next) { + if(sock->own_index==gsock->own_index) + break; + } + if(sock) { + sock->groupsock = gsock; + + strcpy(sock->name, gsock->name); + sock->type= gsock->type; + + /* XXX hack: group socket input/output roles are inverted internally, + * need to change the limit value when making actual node sockets from them. + */ + sock->limit = (gsock->limit==1 ? 0xFFF : 1); + + sock->ns.min= gsock->ns.min; + sock->ns.max= gsock->ns.max; + + BLI_remlink(lb, sock); + + return sock; + } + else { + return node_add_group_socket(NULL, gsock); + } +} + static void verify_socket_list(bNodeTree *ntree, ListBase *lb, bNodeSocketType *stype_first) { bNodeSocketType *stype; @@ -236,15 +287,41 @@ static void verify_socket_list(bNodeTree *ntree, ListBase *lb, bNodeSocketType * } } -void nodeVerifyType(bNodeTree *ntree, bNode *node) +static void verify_group_socket_list(bNodeTree *ntree, ListBase *lb, ListBase *glb) { - bNodeType *ntype= node->typeinfo; + bNodeSocket *gsock; - if(ntype) { - /* might add some other verify stuff here */ - - verify_socket_list(ntree, &node->inputs, ntype->inputs); - verify_socket_list(ntree, &node->outputs, ntype->outputs); + /* step by step compare */ + for (gsock= glb->first; gsock; gsock=gsock->next) { + /* abusing new_sock pointer for verification here! only used inside this function */ + gsock->new_sock= verify_group_socket(lb, gsock); + } + /* leftovers are removed */ + while(lb->first) + node_rem_socket(ntree, lb, lb->first); + /* and we put back the verified sockets */ + for (gsock= glb->first; gsock; gsock=gsock->next) { + BLI_addtail(lb, gsock->new_sock); + gsock->new_sock = NULL; + } +} + +void nodeVerifyType(bNodeTree *ntree, bNode *node) +{ + /* node groups don't have static sock lists, but use external sockets from the tree instead */ + if (node->type==NODE_GROUP) { + bNodeTree *ngroup= (bNodeTree*)node->id; + if (ngroup) { + verify_group_socket_list(ntree, &node->inputs, &ngroup->inputs); + verify_group_socket_list(ntree, &node->outputs, &ngroup->outputs); + } + } + else { + bNodeType *ntype= node->typeinfo; + if(ntype) { + verify_socket_list(ntree, &node->inputs, ntype->inputs); + verify_socket_list(ntree, &node->outputs, ntype->outputs); + } } } @@ -263,193 +340,38 @@ void ntreeVerifyTypes(bNodeTree *ntree) /* ************** Group stuff ********** */ -bNodeType node_group_typeinfo= { - /* next,prev */ NULL, NULL, - /* type code */ NODE_GROUP, - /* name */ "Group", - /* width+range */ 120, 60, 200, - /* class+opts */ NODE_CLASS_GROUP, NODE_OPTIONS, - /* input sock */ NULL, - /* output sock */ NULL, - /* storage */ "", - /* execfunc */ NULL, - /* butfunc */ NULL, - /* initfunc */ NULL, - /* freestoragefunc */ NULL, - /* copystoragefunc */ NULL, - /* id */ NULL -}; - -/* tag internal sockets */ -static void group_tag_internal_sockets(bNodeTree *ngroup) -{ - bNode *node; - bNodeSocket *sock; - bNodeLink *link; - - /* clear intern tag, but check already for hidden sockets */ - for(node= ngroup->nodes.first; node; node= node->next) { - for(sock= node->inputs.first; sock; sock= sock->next) - sock->intern= sock->flag & SOCK_HIDDEN; - for(sock= node->outputs.first; sock; sock= sock->next) - sock->intern= sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL); - } - /* set tag */ - for(link= ngroup->links.first; link; link= link->next) { - link->fromsock->intern= 1; - link->tosock->intern= 1; - } - - /* remove link pointer to external links (only happens on create group) */ - for(node= ngroup->nodes.first; node; node= node->next) { - for(sock= node->inputs.first; sock; sock= sock->next) - if(sock->intern==0) - sock->link= NULL; - } +/* XXX group typeinfo struct is used directly in ntreeMakeOwnType, needs cleanup */ +static bNodeType ntype_group; - /* set all intern sockets to own_index zero, makes sure that later use won't mixup */ - for(node= ngroup->nodes.first; node; node= node->next) { - for(sock= node->inputs.first; sock; sock= sock->next) - if(sock->intern) - sock->own_index= 0; - for(sock= node->outputs.first; sock; sock= sock->next) - if(sock->intern) - sock->own_index= 0; - } -} - -/* after editing group, new sockets are zero */ -/* this routine ensures unique identifiers for zero sockets that are exposed */ -static void group_verify_own_indices(bNodeTree *ngroup) +/* groups display their internal tree name as label */ +static const char *group_label(bNode *node) { - bNode *node; - bNodeSocket *sock; - - for(node= ngroup->nodes.first; node; node= node->next) { - for(sock= node->inputs.first; sock; sock= sock->next) - if(sock->own_index==0 && sock->intern==0) - sock->own_index= ++(ngroup->cur_index); - for(sock= node->outputs.first; sock; sock= sock->next) - if(sock->own_index==0 && sock->intern==0) - sock->own_index= ++(ngroup->cur_index); - } - //printf("internal index %d\n", ngroup->cur_index); + return node->id->name+2; } - -/* nodetrees can be used as groups, so we need typeinfo structs generated */ -void ntreeMakeOwnType(bNodeTree *ngroup) +void register_node_type_group(ListBase *lb) { - bNode *node; - bNodeSocket *sock; - int totin= 0, totout=0, a; - - /* tags socket when internal linked */ - group_tag_internal_sockets(ngroup); - - /* ensure all sockets have own unique id */ - group_verify_own_indices(ngroup); - - /* counting stats */ - for(node= ngroup->nodes.first; node; node= node->next) { - if(node->type==NODE_GROUP) - break; - for(sock= node->inputs.first; sock; sock= sock->next) - if(sock->intern==0) - totin++; - for(sock= node->outputs.first; sock; sock= sock->next) - if(sock->intern==0) - totout++; - } - /* debug: nodetrees in nodetrees not handled yet */ - if(node) { - printf("group in group, not supported yet\n"); - return; - } - - /* free own type struct */ - if(ngroup->owntype) { - if(ngroup->owntype->inputs) - MEM_freeN(ngroup->owntype->inputs); - if(ngroup->owntype->outputs) - MEM_freeN(ngroup->owntype->outputs); - MEM_freeN(ngroup->owntype); - } - - /* make own type struct */ - ngroup->owntype= MEM_callocN(sizeof(bNodeType), "group type"); - *ngroup->owntype= node_group_typeinfo; /* copy data, for init */ - - /* input type arrays */ - if(totin) { - bNodeSocketType *stype; - bNodeSocketType *inputs= MEM_callocN(sizeof(bNodeSocketType)*(totin+1), "bNodeSocketType"); - a= 0; - - for(node= ngroup->nodes.first; node; node= node->next) { - /* nodes are presumed fully verified, stype and socket list are in sync */ - stype= node->typeinfo->inputs; - for(sock= node->inputs.first; sock; sock= sock->next, stype++) { - if(sock->intern==0) { - /* debug only print */ - if(stype==NULL || stype->type==-1) printf("group verification error %s\n", ngroup->id.name); - - inputs[a]= *stype; - inputs[a].own_index= sock->own_index; - inputs[a].internsock= sock; - a++; - } - } - } - inputs[a].type= -1; /* terminator code */ - ngroup->owntype->inputs= inputs; - } - - /* output type arrays */ - if(totout) { - bNodeSocketType *stype; - bNodeSocketType *outputs= MEM_callocN(sizeof(bNodeSocketType)*(totout+1), "bNodeSocketType"); - a= 0; - - for(node= ngroup->nodes.first; node; node= node->next) { - /* nodes are presumed fully verified, stype and socket list are in sync */ - stype= node->typeinfo->outputs; - for(sock= node->outputs.first; sock; sock= sock->next, stype++) { - if(sock->intern==0) { - /* debug only print */ - if(stype==NULL || stype->type==-1) printf("group verification error %s\n", ngroup->id.name); - - outputs[a]= *stype; - outputs[a].own_index= sock->own_index; - outputs[a].internsock= sock; - a++; - } - } - } - outputs[a].type= -1; /* terminator code */ - ngroup->owntype->outputs= outputs; - } + node_type_base(&ntype_group, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS, NULL, NULL); + node_type_size(&ntype_group, 120, 60, 200); + node_type_label(&ntype_group, group_label); - /* voila, the nodetree has the full definition for generating group-node instances! */ + nodeRegisterType(lb, &ntype_group); } - -static bNodeSocket *groupnode_find_tosock(bNode *gnode, int index) +static bNodeSocket *find_group_node_input(bNode *gnode, bNodeSocket *gsock) { bNodeSocket *sock; - - for(sock= gnode->inputs.first; sock; sock= sock->next) - if(sock->to_index==index) + for (sock=gnode->inputs.first; sock; sock=sock->next) + if (sock->groupsock == gsock) return sock; return NULL; } -static bNodeSocket *groupnode_find_fromsock(bNode *gnode, int index) +static bNodeSocket *find_group_node_output(bNode *gnode, bNodeSocket *gsock) { bNodeSocket *sock; - - for(sock= gnode->outputs.first; sock; sock= sock->next) - if(sock->to_index==index) + for (sock=gnode->outputs.first; sock; sock=sock->next) + if (sock->groupsock == gsock) return sock; return NULL; } @@ -458,8 +380,9 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree) { bNodeLink *link, *linkn; bNode *node, *gnode, *nextn; - bNodeSocket *sock; bNodeTree *ngroup; + bNodeSocket *gsock; + ListBase anim_basepaths = {NULL, NULL}; float min[2], max[2]; int totnode=0; @@ -481,9 +404,9 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree) /* check if all connections are OK, no unselected node has both inputs and outputs to a selection */ for(link= ntree->links.first; link; link= link->next) { - if(link->fromnode->flag & NODE_SELECT) + if(link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT) link->tonode->done |= 1; - if(link->tonode->flag & NODE_SELECT) + if(link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT) link->fromnode->done |= 2; } @@ -496,41 +419,50 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree) return NULL; /* OK! new nodetree */ - ngroup= alloc_libblock(&G.main->nodetree, ID_NT, "NodeGroup"); - ngroup->type= ntree->type; - ngroup->alltypes= ntree->alltypes; + ngroup= ntreeAddTree("NodeGroup", ntree->type, TRUE); /* move nodes over */ for(node= ntree->nodes.first; node; node= nextn) { nextn= node->next; if(node->flag & NODE_SELECT) { + /* keep track of this node's RNA "base" path (the part of the pat identifying the node) + * if the old nodetree has animation data which potentially covers this node + */ + if (ntree->adt) { + PointerRNA ptr; + char *path; + + RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr); + path = RNA_path_from_ID_to_struct(&ptr); + + if (path) + BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); + } + + /* change node-collection membership */ BLI_remlink(&ntree->nodes, node); BLI_addtail(&ngroup->nodes, node); + node->locx-= 0.5f*(min[0]+max[0]); node->locy-= 0.5f*(min[1]+max[1]); - - /* set socket own_index to zero since it can still have a value - * from being in a group before, otherwise it doesn't get a unique - * index in group_verify_own_indices */ - for(sock= node->inputs.first; sock; sock= sock->next) - sock->own_index= 0; - for(sock= node->outputs.first; sock; sock= sock->next) - sock->own_index= 0; } } - /* move links over */ - for(link= ntree->links.first; link; link= linkn) { - linkn= link->next; - if(link->fromnode->flag & link->tonode->flag & NODE_SELECT) { - BLI_remlink(&ntree->links, link); - BLI_addtail(&ngroup->links, link); + /* move animation data over */ + if (ntree->adt) { + LinkData *ld, *ldn=NULL; + + BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths); + + /* paths + their wrappers need to be freed */ + for (ld = anim_basepaths.first; ld; ld = ldn) { + ldn = ld->next; + + MEM_freeN(ld->data); + BLI_freelinkN(&anim_basepaths, ld); } } - /* now we can make own group typeinfo */ - ntreeMakeOwnType(ngroup); - /* make group node */ gnode= nodeAddNodeType(ntree, NODE_GROUP, ngroup, NULL); gnode->locx= 0.5f*(min[0]+max[0]); @@ -540,35 +472,29 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree) for(link= ntree->links.first; link; link= linkn) { linkn= link->next; - if(link->tonode->flag & NODE_SELECT) { - link->tonode= gnode; - sock= groupnode_find_tosock(gnode, link->tosock->own_index); - if(sock==NULL) { - nodeRemLink(ntree, link); - printf("Removed link, cannot mix internal and external sockets in group\n"); - } - else link->tosock= sock; + if(link->fromnode && link->tonode && (link->fromnode->flag & link->tonode->flag & NODE_SELECT)) { + BLI_remlink(&ntree->links, link); + BLI_addtail(&ngroup->links, link); } - else if(link->fromnode->flag & NODE_SELECT) { - link->fromnode= gnode; - sock= groupnode_find_fromsock(gnode, link->fromsock->own_index); - if(sock==NULL) { - nodeRemLink(ntree, link); - printf("Removed link, cannot mix internal and external sockets in group\n"); - } - else link->fromsock= sock; + else if(link->tonode && (link->tonode->flag & NODE_SELECT)) { + gsock = nodeGroupExposeSocket(ngroup, link->tosock, SOCK_IN); + link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock); + link->tosock = node_add_group_socket(&gnode->inputs, gsock); + link->tonode = gnode; } - } - - /* initialize variables of unused input sockets */ - for(node= ngroup->nodes.first; node; node= node->next) { - for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->intern==0) { - bNodeSocket *nsock= groupnode_find_tosock(gnode, sock->own_index); - if(nsock) { - QUATCOPY(nsock->ns.vec, sock->ns.vec); - } + else if(link->fromnode && (link->fromnode->flag & NODE_SELECT)) { + /* search for existing group node socket */ + for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next) + if (gsock->link && gsock->link->fromsock==link->fromsock) + break; + if (!gsock) { + gsock = nodeGroupExposeSocket(ngroup, link->fromsock, SOCK_OUT); + gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock); + link->fromsock = node_add_group_socket(&gnode->outputs, gsock); } + else + link->fromsock = find_group_node_output(gnode, gsock); + link->fromnode = gnode; } } @@ -578,35 +504,21 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree) return gnode; } -/* note: ungroup: group_indices zero! */ - /* here's a nasty little one, need to check users... */ /* should become callbackable... */ -void nodeVerifyGroup(bNodeTree *ngroup) +void nodeGroupVerify(bNodeTree *ngroup) { - /* group changed, so we rebuild the type definition */ - ntreeMakeOwnType(ngroup); +// ntreeMakeGroupSockets(ngroup); if(ngroup->type==NTREE_SHADER) { Material *ma; for(ma= G.main->mat.first; ma; ma= ma->id.next) { if(ma->nodetree) { bNode *node; - - /* find if group is in tree */ for(node= ma->nodetree->nodes.first; node; node= node->next) if(node->id == (ID *)ngroup) - break; - - if(node) { - /* set all type pointers OK */ - ntreeInitTypes(ma->nodetree); - - for(node= ma->nodetree->nodes.first; node; node= node->next) - if(node->id == (ID *)ngroup) - nodeVerifyType(ma->nodetree, node); - } + nodeVerifyType(ma->nodetree, node); } } } @@ -615,20 +527,9 @@ void nodeVerifyGroup(bNodeTree *ngroup) for(sce= G.main->scene.first; sce; sce= sce->id.next) { if(sce->nodetree) { bNode *node; - - /* find if group is in tree */ for(node= sce->nodetree->nodes.first; node; node= node->next) if(node->id == (ID *)ngroup) - break; - - if(node) { - /* set all type pointers OK */ - ntreeInitTypes(sce->nodetree); - - for(node= sce->nodetree->nodes.first; node; node= node->next) - if(node->id == (ID *)ngroup) - nodeVerifyType(sce->nodetree, node); - } + nodeVerifyType(sce->nodetree, node); } } } @@ -637,20 +538,9 @@ void nodeVerifyGroup(bNodeTree *ngroup) for(tx= G.main->tex.first; tx; tx= tx->id.next) { if(tx->nodetree) { bNode *node; - - /* find if group is in tree */ for(node= tx->nodetree->nodes.first; node; node= node->next) if(node->id == (ID *)ngroup) - break; - - if(node) { - /* set all type pointers OK */ - ntreeInitTypes(tx->nodetree); - - for(node= tx->nodetree->nodes.first; node; node= node->next) - if(node->id == (ID *)ngroup) - nodeVerifyType(tx->nodetree, node); - } + nodeVerifyType(tx->nodetree, node); } } } @@ -677,15 +567,15 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup) for(ma= G.main->mat.first; ma; ma= ma->id.next) { if(ma->nodetree) { for(node= ma->nodetree->nodes.first; node; node= node->next) { - if(node->id==(ID *)ngroup) { + if(node->id==&ngroup->id) { for(sock= node->inputs.first; sock; sock= sock->next) if(sock->link) - if(sock->tosock) - sock->tosock->flag |= SOCK_IN_USE; + if(sock->groupsock) + sock->groupsock->flag |= SOCK_IN_USE; for(sock= node->outputs.first; sock; sock= sock->next) if(nodeCountSocketLinks(ma->nodetree, sock)) - if(sock->tosock) - sock->tosock->flag |= SOCK_IN_USE; + if(sock->groupsock) + sock->groupsock->flag |= SOCK_IN_USE; } } } @@ -699,12 +589,12 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup) if(node->id==(ID *)ngroup) { for(sock= node->inputs.first; sock; sock= sock->next) if(sock->link) - if(sock->tosock) - sock->tosock->flag |= SOCK_IN_USE; + if(sock->groupsock) + sock->groupsock->flag |= SOCK_IN_USE; for(sock= node->outputs.first; sock; sock= sock->next) if(nodeCountSocketLinks(sce->nodetree, sock)) - if(sock->tosock) - sock->tosock->flag |= SOCK_IN_USE; + if(sock->groupsock) + sock->groupsock->flag |= SOCK_IN_USE; } } } @@ -718,12 +608,12 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup) if(node->id==(ID *)ngroup) { for(sock= node->inputs.first; sock; sock= sock->next) if(sock->link) - if(sock->tosock) - sock->tosock->flag |= SOCK_IN_USE; + if(sock->groupsock) + sock->groupsock->flag |= SOCK_IN_USE; for(sock= node->outputs.first; sock; sock= sock->next) if(nodeCountSocketLinks(tx->nodetree, sock)) - if(sock->tosock) - sock->tosock->flag |= SOCK_IN_USE; + if(sock->groupsock) + sock->groupsock->flag |= SOCK_IN_USE; } } } @@ -738,21 +628,27 @@ bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name) } /* finds a node based on given socket */ -int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex) +int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex, int *in_out) { bNode *node; bNodeSocket *tsock; int index= 0; for(node= ntree->nodes.first; node; node= node->next) { - for(index=0, tsock= node->inputs.first; tsock; tsock= tsock->next, index++) - if(tsock==sock) + for(index=0, tsock= node->inputs.first; tsock; tsock= tsock->next, index++) { + if(tsock==sock) { + if (in_out) *in_out= SOCK_IN; break; + } + } if(tsock) break; - for(index=0, tsock= node->outputs.first; tsock; tsock= tsock->next, index++) - if(tsock==sock) + for(index=0, tsock= node->outputs.first; tsock; tsock= tsock->next, index++) { + if(tsock==sock) { + if (in_out) *in_out= SOCK_OUT; break; + } + } if(tsock) break; } @@ -773,7 +669,7 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode) bNodeLink *link, *linkn; bNode *node, *nextn; bNodeTree *ngroup, *wgroup; - int index; + ListBase anim_basepaths = {NULL, NULL}; ngroup= (bNodeTree *)gnode->id; if(ngroup==NULL) return 0; @@ -781,98 +677,261 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode) /* clear new pointers, set in copytree */ for(node= ntree->nodes.first; node; node= node->next) node->new_node= NULL; - - wgroup= ntreeCopyTree(ngroup, 0); + + /* wgroup is a temporary copy of the NodeTree we're merging in + * - all of wgroup's nodes are transferred across to their new home + * - ngroup (i.e. the source NodeTree) is left unscathed + */ + wgroup= ntreeCopyTree(ngroup); /* add the nodes into the ntree */ for(node= wgroup->nodes.first; node; node= nextn) { nextn= node->next; + + /* keep track of this node's RNA "base" path (the part of the pat identifying the node) + * if the old nodetree has animation data which potentially covers this node + */ + if (wgroup->adt) { + PointerRNA ptr; + char *path; + + RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr); + path = RNA_path_from_ID_to_struct(&ptr); + + if (path) + BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); + } + + /* migrate node */ BLI_remlink(&wgroup->nodes, node); BLI_addtail(&ntree->nodes, node); + node->locx+= gnode->locx; node->locy+= gnode->locy; + node->flag |= NODE_SELECT; } - /* and the internal links */ - for(link= wgroup->links.first; link; link= linkn) { - linkn= link->next; - BLI_remlink(&wgroup->links, link); - BLI_addtail(&ntree->links, link); - } - - /* restore links to and from the gnode */ + + /* restore external links to and from the gnode */ for(link= ntree->links.first; link; link= link->next) { - if(link->tonode==gnode) { - /* link->tosock->tosock is on the node we look for */ - nodeFindNode(ngroup, link->tosock->tosock, &nextn, &index); - if(nextn==NULL) printf("wrong stuff!\n"); - else if(nextn->new_node==NULL) printf("wrong stuff too!\n"); - else { - link->tonode= nextn->new_node; - link->tosock= BLI_findlink(&link->tonode->inputs, index); + if (link->fromnode==gnode) { + if (link->fromsock->groupsock) { + bNodeSocket *gsock= link->fromsock->groupsock; + if (gsock->link) { + if (gsock->link->fromnode) { + /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */ + link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL); + link->fromsock = gsock->link->fromsock->new_sock; + } + else { + /* group output directly maps to group input */ + bNodeSocket *insock= find_group_node_input(gnode, gsock->link->fromsock); + if (insock->link) { + link->fromnode = insock->link->fromnode; + link->fromsock = insock->link->fromsock; + } + } + } + else { + /* constant group output: copy the stack value to the external socket. + * the link is kept here until all possible external users have been fixed. + */ + QUATCOPY(link->tosock->ns.vec, gsock->ns.vec); + } } } - else if(link->fromnode==gnode) { - /* link->fromsock->tosock is on the node we look for */ - nodeFindNode(ngroup, link->fromsock->tosock, &nextn, &index); - if(nextn==NULL) printf("1 wrong stuff!\n"); - else if(nextn->new_node==NULL) printf("1 wrong stuff too!\n"); + } + /* remove internal output links, these are not used anymore */ + for(link=wgroup->links.first; link; link= linkn) { + linkn = link->next; + if (!link->tonode) + nodeRemLink(wgroup, link); + } + /* restore links from internal nodes */ + for(link= wgroup->links.first; link; link= link->next) { + /* indicates link to group input */ + if (!link->fromnode) { + /* NB: can't use find_group_node_input here, + * because gnode sockets still point to the old tree! + */ + bNodeSocket *insock; + for (insock= gnode->inputs.first; insock; insock= insock->next) + if (insock->groupsock->new_sock == link->fromsock) + break; + if (insock->link) { + link->fromnode = insock->link->fromnode; + link->fromsock = insock->link->fromsock; + } else { - link->fromnode= nextn->new_node; - link->fromsock= BLI_findlink(&link->fromnode->outputs, index); + /* uses group constant input. copy the input value and remove the dead link. */ + QUATCOPY(link->tosock->ns.vec, insock->ns.vec); + nodeRemLink(wgroup, link); } } } - /* remove the gnode & work tree */ - free_libblock(&G.main->nodetree, wgroup); + /* add internal links to the ntree */ + for(link= wgroup->links.first; link; link= linkn) { + linkn= link->next; + BLI_remlink(&wgroup->links, link); + BLI_addtail(&ntree->links, link); + } + + /* and copy across the animation */ + if (wgroup->adt) { + LinkData *ld, *ldn=NULL; + bAction *waction; + + /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */ + waction = wgroup->adt->action = copy_action(wgroup->adt->action); + + /* now perform the moving */ + BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths); + + /* paths + their wrappers need to be freed */ + for (ld = anim_basepaths.first; ld; ld = ldn) { + ldn = ld->next; + + MEM_freeN(ld->data); + BLI_freelinkN(&anim_basepaths, ld); + } + + /* free temp action too */ + free_libblock(&G.main->action, waction); + } + /* delete the group instance. this also removes old input links! */ nodeFreeNode(ntree, gnode); + /* free the group tree (takes care of user count) */ + free_libblock(&G.main->nodetree, wgroup); + /* solve order goes fine, but the level tags not... doing it twice works for now. solve this once */ + /* XXX is this still necessary with new groups? it may have been caused by non-updated sock->link pointers. lukas */ ntreeSolveOrder(ntree); ntreeSolveOrder(ntree); return 1; } -void nodeCopyGroup(bNode *gnode) +void nodeGroupCopy(bNode *gnode) { bNodeSocket *sock; gnode->id->us--; - gnode->id= (ID *)ntreeCopyTree((bNodeTree *)gnode->id, 0); + gnode->id= (ID *)ntreeCopyTree((bNodeTree *)gnode->id); /* new_sock was set in nodeCopyNode */ for(sock=gnode->inputs.first; sock; sock=sock->next) - if(sock->tosock) - sock->tosock= sock->tosock->new_sock; + if(sock->groupsock) + sock->groupsock= sock->groupsock->new_sock; for(sock=gnode->outputs.first; sock; sock=sock->next) - if(sock->tosock) - sock->tosock= sock->tosock->new_sock; + if(sock->groupsock) + sock->groupsock= sock->groupsock->new_sock; +} + +bNodeSocket *nodeGroupAddSocket(bNodeTree *ngroup, const char *name, int type, int in_out) +{ + bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket"); + + strncpy(gsock->name, name, sizeof(gsock->name)); + gsock->type = type; + gsock->ns.sockettype = type; + gsock->ns.min = INT_MIN; + gsock->ns.max = INT_MAX; + zero_v4(gsock->ns.vec); + gsock->ns.data = NULL; + gsock->flag = 0; + + gsock->next = gsock->prev = NULL; + gsock->new_sock = NULL; + gsock->link = NULL; + gsock->ns.data = NULL; + /* assign new unique index */ + gsock->own_index = ngroup->cur_index++; + gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1); + + BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock); + + return gsock; +} + +bNodeSocket *nodeGroupExposeSocket(bNodeTree *ngroup, bNodeSocket *sock, int in_out) +{ + bNodeSocket *gsock= nodeGroupAddSocket(ngroup, sock->name, sock->type, in_out); + /* initialize the default socket value */ + QUATCOPY(gsock->ns.vec, sock->ns.vec); + return gsock; +} + +void nodeGroupExposeAllSockets(bNodeTree *ngroup) +{ + bNode *node; + bNodeSocket *sock, *gsock; + + for (node=ngroup->nodes.first; node; node=node->next) { + for (sock=node->inputs.first; sock; sock=sock->next) { + if (!sock->link && !(sock->flag & SOCK_HIDDEN)) { + gsock = nodeGroupAddSocket(ngroup, sock->name, sock->type, SOCK_IN); + /* initialize the default socket value */ + QUATCOPY(gsock->ns.vec, sock->ns.vec); + sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock); + } + } + for (sock=node->outputs.first; sock; sock=sock->next) { + if (nodeCountSocketLinks(ngroup, sock)==0 && !(sock->flag & SOCK_HIDDEN)) { + gsock = nodeGroupAddSocket(ngroup, sock->name, sock->type, SOCK_OUT); + /* initialize the default socket value */ + QUATCOPY(gsock->ns.vec, sock->ns.vec); + gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock); + } + } + } +} + +void nodeGroupRemoveSocket(bNodeTree *ngroup, bNodeSocket *gsock, int in_out) +{ + nodeRemSocketLinks(ngroup, gsock); + switch (in_out) { + case SOCK_IN: BLI_remlink(&ngroup->inputs, gsock); break; + case SOCK_OUT: BLI_remlink(&ngroup->outputs, gsock); break; + } } /* ************** Add stuff ********** */ void nodeAddSockets(bNode *node, bNodeType *ntype) { - bNodeSocketType *stype; - - if(ntype->inputs) { - stype= ntype->inputs; - while(stype->type != -1) { - node_add_socket_type(&node->inputs, stype); - stype++; + if (node->type==NODE_GROUP) { + bNodeTree *ntree= (bNodeTree*)node->id; + if (ntree) { + bNodeSocket *gsock; + for (gsock=ntree->inputs.first; gsock; gsock=gsock->next) + node_add_group_socket(&node->inputs, gsock); + for (gsock=ntree->outputs.first; gsock; gsock=gsock->next) + node_add_group_socket(&node->outputs, gsock); } } - if(ntype->outputs) { - stype= ntype->outputs; - while(stype->type != -1) { - node_add_socket_type(&node->outputs, stype); - stype++; + else { + bNodeSocketType *stype; + + if(ntype->inputs) { + stype= ntype->inputs; + while(stype->type != -1) { + node_add_socket_type(&node->inputs, stype); + stype++; + } + } + if(ntype->outputs) { + stype= ntype->outputs; + while(stype->type != -1) { + node_add_socket_type(&node->outputs, stype); + stype++; + } } } } + /* Find the first available, non-duplicate name for a given node */ void nodeUniqueName(bNodeTree *ntree, bNode *node) { @@ -884,6 +943,11 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id) bNode *node= NULL; bNodeType *ntype= NULL; + if (ngroup && BLI_findindex(&G.main->nodetree, ngroup)==-1) { + printf("nodeAddNodeType() error: '%s' not in main->nodetree\n", ngroup->id.name); + return NULL; + } + if(type>=NODE_DYNAMIC_MENU) { int a=0, idx= type-NODE_DYNAMIC_MENU; ntype= ntree->alltypes.first; @@ -896,7 +960,7 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id) ntype= ntype->next; } } else - ntype= node_get_type(ntree, type, ngroup, id); + ntype= node_get_type(ntree, type, id); node= MEM_callocN(sizeof(bNode), "new node"); BLI_addtail(&ntree->nodes, node); @@ -960,7 +1024,7 @@ void nodeUpdateType(bNodeTree *ntree, bNode* node, bNodeType *ntype) /* keep socket listorder identical, for copying links */ /* ntree is the target tree */ -bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal) +bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) { bNode *nnode= MEM_callocN(sizeof(bNode), "dupli node"); bNodeSocket *sock, *oldsock; @@ -974,15 +1038,11 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal) oldsock= node->inputs.first; for(sock= nnode->inputs.first; sock; sock= sock->next, oldsock= oldsock->next) { oldsock->new_sock= sock; - if(internal) - sock->own_index= 0; } BLI_duplicatelist(&nnode->outputs, &node->outputs); oldsock= node->outputs.first; for(sock= nnode->outputs.first; sock; sock= sock->next, oldsock= oldsock->next) { - if(internal) - sock->own_index= 0; sock->stack_index= 0; sock->ns.data= NULL; oldsock->new_sock= sock; @@ -1000,15 +1060,61 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal) return nnode; } +/* fromsock and tosock can be NULL */ +/* also used via rna api, so we check for proper input output direction */ bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock) { - bNodeLink *link= MEM_callocN(sizeof(bNodeLink), "link"); + bNodeSocket *sock; + bNodeLink *link= NULL; + int from= 0, to= 0; - BLI_addtail(&ntree->links, link); - link->fromnode= fromnode; - link->fromsock= fromsock; - link->tonode= tonode; - link->tosock= tosock; + if(fromnode) { + /* test valid input */ + for(sock= fromnode->outputs.first; sock; sock= sock->next) + if(sock==fromsock) + break; + if(sock) + from= 1; /* OK */ + else { + for(sock= fromnode->inputs.first; sock; sock= sock->next) + if(sock==fromsock) + break; + if(sock) + from= -1; /* OK but flip */ + } + } + if(tonode) { + for(sock= tonode->inputs.first; sock; sock= sock->next) + if(sock==tosock) + break; + if(sock) + to= 1; /* OK */ + else { + for(sock= tonode->outputs.first; sock; sock= sock->next) + if(sock==tosock) + break; + if(sock) + to= -1; /* OK but flip */ + } + } + + /* this allows NULL sockets to work */ + if(from >= 0 && to >= 0) { + link= MEM_callocN(sizeof(bNodeLink), "link"); + BLI_addtail(&ntree->links, link); + link->fromnode= fromnode; + link->fromsock= fromsock; + link->tonode= tonode; + link->tosock= tosock; + } + else if(from <= 0 && to <= 0) { + link= MEM_callocN(sizeof(bNodeLink), "link"); + BLI_addtail(&ntree->links, link); + link->fromnode= tonode; + link->fromsock= tosock; + link->tonode= fromnode; + link->tosock= fromsock; + } return link; } @@ -1034,104 +1140,83 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock) } -bNodeTree *ntreeAddTree(int type) +bNodeTree *ntreeAddTree(const char *name, int type, const short is_group) { - bNodeTree *ntree= MEM_callocN(sizeof(bNodeTree), "new node tree"); + bNodeTree *ntree; + + if (is_group) + ntree= alloc_libblock(&G.main->nodetree, ID_NT, name); + else { + ntree= MEM_callocN(sizeof(bNodeTree), "new node tree"); + *( (short *)ntree->id.name )= ID_NT; /* not "type", as that is ntree->type */ + BLI_strncpy(ntree->id.name+2, name, sizeof(ntree->id.name)); + } + ntree->type= type; ntree->alltypes.first = NULL; ntree->alltypes.last = NULL; - /* this helps RNA identify ID pointers as nodetree */ - if(ntree->type==NTREE_SHADER) - BLI_strncpy(ntree->id.name, "NTShader Nodetree", sizeof(ntree->id.name)); - else if(ntree->type==NTREE_COMPOSIT) - BLI_strncpy(ntree->id.name, "NTCompositing Nodetree", sizeof(ntree->id.name)); - else if(ntree->type==NTREE_TEXTURE) - BLI_strncpy(ntree->id.name, "NTTexture Nodetree", sizeof(ntree->id.name)); - ntreeInitTypes(ntree); return ntree; } /* Warning: this function gets called during some rather unexpected times - * - internal_select is only 1 when used for duplicating selected nodes (i.e. Shift-D duplicate operator) * - this gets called when executing compositing updates (for threaded previews) * - when the nodetree datablock needs to be copied (i.e. when users get copied) * - for scene duplication use ntreeSwapID() after so we dont have stale pointers. */ -bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select) +bNodeTree *ntreeCopyTree(bNodeTree *ntree) { bNodeTree *newtree; bNode *node, *nnode, *last; - bNodeLink *link, *nlink; - bNodeSocket *sock; - int a; + bNodeLink *link; + bNodeSocket *gsock, *oldgsock; if(ntree==NULL) return NULL; - if(internal_select==0) { - /* is ntree part of library? */ - for(newtree=G.main->nodetree.first; newtree; newtree= newtree->id.next) - if(newtree==ntree) break; - if(newtree) { - newtree= copy_libblock(ntree); - } else { - newtree= MEM_dupallocN(ntree); - copy_libblock_data(&newtree->id, &ntree->id); /* copy animdata and ID props */ - } - newtree->nodes.first= newtree->nodes.last= NULL; - newtree->links.first= newtree->links.last= NULL; + /* is ntree part of library? */ + for(newtree=G.main->nodetree.first; newtree; newtree= newtree->id.next) + if(newtree==ntree) break; + if(newtree) { + newtree= copy_libblock(ntree); + } else { + newtree= MEM_dupallocN(ntree); + copy_libblock_data(&newtree->id, &ntree->id, TRUE); /* copy animdata and ID props */ } - else - newtree= ntree; + newtree->nodes.first= newtree->nodes.last= NULL; + newtree->links.first= newtree->links.last= NULL; - last= ntree->nodes.last; + last = ntree->nodes.last; for(node= ntree->nodes.first; node; node= node->next) { - node->new_node= NULL; - if(internal_select==0 || (node->flag & NODE_SELECT)) { - nnode= nodeCopyNode(newtree, node, internal_select); /* sets node->new */ - if(internal_select) { - node->flag &= ~(NODE_SELECT|NODE_ACTIVE); - nnode->flag |= NODE_SELECT; - } - } + nnode= nodeCopyNode(newtree, node); /* sets node->new */ if(node==last) break; } - /* check for copying links */ - for(link= ntree->links.first; link; link= link->next) { - if(link->fromnode==NULL || link->tonode==NULL); - else if(link->fromnode->new_node && link->tonode->new_node) { - nlink= nodeAddLink(newtree, link->fromnode->new_node, NULL, link->tonode->new_node, NULL); - /* sockets were copied in order */ - for(a=0, sock= link->fromnode->outputs.first; sock; sock= sock->next, a++) { - if(sock==link->fromsock) - break; - } - nlink->fromsock= BLI_findlink(&link->fromnode->new_node->outputs, a); - - for(a=0, sock= link->tonode->inputs.first; sock; sock= sock->next, a++) { - if(sock==link->tosock) - break; - } - nlink->tosock= BLI_findlink(&link->tonode->new_node->inputs, a); - } + /* socket definition for group usage */ + BLI_duplicatelist(&newtree->inputs, &ntree->inputs); + for(gsock= newtree->inputs.first, oldgsock= ntree->inputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) { + oldgsock->new_sock= gsock; + gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL); } - /* own type definition for group usage */ - if(internal_select==0) { - if(ntree->owntype) { - newtree->owntype= MEM_dupallocN(ntree->owntype); - if(ntree->owntype->inputs) - newtree->owntype->inputs= MEM_dupallocN(ntree->owntype->inputs); - if(ntree->owntype->outputs) - newtree->owntype->outputs= MEM_dupallocN(ntree->owntype->outputs); - } + BLI_duplicatelist(&newtree->outputs, &ntree->outputs); + for(gsock= newtree->outputs.first, oldgsock= ntree->outputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) { + oldgsock->new_sock= gsock; + gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL); + } + + /* copy links */ + BLI_duplicatelist(&newtree->links, &ntree->links); + for(link= newtree->links.first; link; link= link->next) { + link->fromnode = (link->fromnode ? link->fromnode->new_node : NULL); + link->fromsock = (link->fromsock ? link->fromsock->new_sock : NULL); + link->tonode = (link->tonode ? link->tonode->new_node : NULL); + link->tosock = (link->tosock ? link->tosock->new_sock : NULL); + /* update the link socket's pointer */ + if (link->tosock) + link->tosock->link = link; } - /* weird this is required... there seem to be link pointers wrong still? */ - /* anyhoo, doing this solves crashes on copying entire tree (copy scene) and delete nodes */ - ntreeSolveOrder(newtree); return newtree; } @@ -1182,12 +1267,11 @@ static void node_init_preview(bNode *node, int xsize, int ysize) } if(node->preview->rect==NULL) { - node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect"); + node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(char)*4, "node preview rect"); node->preview->xsize= xsize; node->preview->ysize= ysize; } - else - memset(node->preview->rect, 0, 4*xsize + xsize*ysize*sizeof(float)*4); + /* no clear, makes nicer previews */ } void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize) @@ -1237,12 +1321,18 @@ void nodeAddToPreview(bNode *node, float *col, int x, int y) if(x>=0 && y>=0) { if(x<preview->xsize && y<preview->ysize) { unsigned char *tar= preview->rect+ 4*((preview->xsize*y) + x); - //if(tar[0]==0.0f) { - tar[0]= FTOCHAR(col[0]); - tar[1]= FTOCHAR(col[1]); - tar[2]= FTOCHAR(col[2]); + + if(TRUE) { + tar[0]= FTOCHAR(linearrgb_to_srgb(col[0])); + tar[1]= FTOCHAR(linearrgb_to_srgb(col[1])); + tar[2]= FTOCHAR(linearrgb_to_srgb(col[2])); + } + else { + tar[0]= FTOCHAR(col[0]); + tar[1]= FTOCHAR(col[1]); + tar[2]= FTOCHAR(col[2]); + } tar[3]= FTOCHAR(col[3]); - //} } //else printf("prv out bound x y %d %d\n", x, y); } @@ -1265,7 +1355,8 @@ void nodeUnlinkNode(bNodeTree *ntree, bNode *node) if(link->fromnode==node) { lb= &node->outputs; - NodeTagChanged(ntree, link->tonode); + if (link->tonode) + NodeTagChanged(ntree, link->tonode); } else if(link->tonode==node) lb= &node->inputs; @@ -1335,13 +1426,8 @@ void ntreeFreeTree(bNodeTree *ntree) nodeFreeNode(ntree, node); } - if(ntree->owntype) { - if(ntree->owntype->inputs) - MEM_freeN(ntree->owntype->inputs); - if(ntree->owntype->outputs) - MEM_freeN(ntree->owntype->outputs); - MEM_freeN(ntree->owntype); - } + BLI_freelistN(&ntree->inputs); + BLI_freelistN(&ntree->outputs); } void ntreeFreeCache(bNodeTree *ntree) @@ -1367,9 +1453,9 @@ void ntreeMakeLocal(bNodeTree *ntree) if(ntree->id.lib==NULL) return; if(ntree->id.us==1) { - ntree->id.lib= 0; + ntree->id.lib= NULL; ntree->id.flag= LIB_LOCAL; - new_id(0, (ID *)ntree, 0); + new_id(NULL, (ID *)ntree, NULL); return; } @@ -1427,11 +1513,11 @@ void ntreeMakeLocal(bNodeTree *ntree) if(local && lib==0) { ntree->id.lib= NULL; ntree->id.flag= LIB_LOCAL; - new_id(0, (ID *)ntree, 0); + new_id(NULL, (ID *)ntree, NULL); } else if(local && lib) { /* this is the mixed case, we copy the tree and assign it to local users */ - bNodeTree *newtree= ntreeCopyTree(ntree, 0); + bNodeTree *newtree= ntreeCopyTree(ntree); newtree->id.us= 0; @@ -1675,7 +1761,7 @@ static int node_recurs_check(bNode *node, bNode ***nsort, int level) if(sock->link) { has_inputlinks= 1; fromnode= sock->link->fromnode; - if(fromnode->done==0) { + if(fromnode && fromnode->done==0) { fromnode->level= node_recurs_check(fromnode, nsort, level); } } @@ -1690,6 +1776,59 @@ static int node_recurs_check(bNode *node, bNode ***nsort, int level) return 0xFFF; } + +static void ntreeSetOutput(bNodeTree *ntree) +{ + bNode *node; + + /* find the active outputs, might become tree type dependant handler */ + for(node= ntree->nodes.first; node; node= node->next) { + if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { + bNode *tnode; + int output= 0; + + /* we need a check for which output node should be tagged like this, below an exception */ + if(node->type==CMP_NODE_OUTPUT_FILE) + continue; + + /* there is more types having output class, each one is checked */ + for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) { + if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) { + + if(ntree->type==NTREE_COMPOSIT) { + + /* same type, exception for viewer */ + if(tnode->type==node->type || + (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && + ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) { + if(tnode->flag & NODE_DO_OUTPUT) { + output++; + if(output>1) + tnode->flag &= ~NODE_DO_OUTPUT; + } + } + } + else { + /* same type */ + if(tnode->type==node->type) { + if(tnode->flag & NODE_DO_OUTPUT) { + output++; + if(output>1) + tnode->flag &= ~NODE_DO_OUTPUT; + } + } + } + } + } + if(output==0) + node->flag |= NODE_DO_OUTPUT; + } + } + + /* here we could recursively set which nodes have to be done, + might be different for editor or for "real" use... */ +} + void ntreeSolveOrder(bNodeTree *ntree) { bNode *node, **nodesort, **nsort; @@ -1708,6 +1847,9 @@ void ntreeSolveOrder(bNodeTree *ntree) for(sock= node->inputs.first; sock; sock= sock->next) sock->link= NULL; } + /* clear group socket links */ + for(sock= ntree->outputs.first; sock; sock= sock->next) + sock->link= NULL; if(totnode==0) return; @@ -1738,38 +1880,11 @@ void ntreeSolveOrder(bNodeTree *ntree) } MEM_freeN(nodesort); - - /* find the active outputs, might become tree type dependant handler */ - for(node= ntree->nodes.first; node; node= node->next) { - if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { - bNode *tnode; - int output= 0; - - /* we need a check for which output node should be tagged like this, below an exception */ - if(node->type==CMP_NODE_OUTPUT_FILE) - continue; - - /* there is more types having output class, each one is checked */ - for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) { - if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) { - if(tnode->type==node->type) { - if(tnode->flag & NODE_DO_OUTPUT) { - output++; - if(output>1) - tnode->flag &= ~NODE_DO_OUTPUT; - } - } - } - } - if(output==0) - node->flag |= NODE_DO_OUTPUT; - } - } - - /* here we could recursively set which nodes have to be done, - might be different for editor or for "real" use... */ + + ntreeSetOutput(ntree); } + /* Should be callback! */ /* Do not call execs here */ void NodeTagChanged(bNodeTree *ntree, bNode *node) @@ -1787,51 +1902,65 @@ void NodeTagChanged(bNodeTree *ntree, bNode *node) } } -void NodeTagIDChanged(bNodeTree *ntree, ID *id) +int NodeTagIDChanged(bNodeTree *ntree, ID *id) { - if(id==NULL) - return; + int change = FALSE; + + if(ELEM(NULL, id, ntree)) + return change; if(ntree->type==NTREE_COMPOSIT) { bNode *node; - for(node= ntree->nodes.first; node; node= node->next) - if(node->id==id) + for(node= ntree->nodes.first; node; node= node->next) { + if(node->id==id) { + change= TRUE; NodeTagChanged(ntree, node); + } + } } + + return change; } /* ******************* executing ************* */ +/* for a given socket, find the actual stack entry */ +static bNodeStack *get_socket_stack(bNodeStack *stack, bNodeSocket *sock, bNodeStack **gin) +{ + switch (sock->stack_type) { + case SOCK_STACK_LOCAL: + return stack + sock->stack_index; + case SOCK_STACK_EXTERN: + return (gin ? gin[sock->stack_index] : NULL); + case SOCK_STACK_CONST: + return sock->stack_ptr; + } + return NULL; +} + /* see notes at ntreeBeginExecTree */ -static void group_node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out, bNodeStack **gin, bNodeStack **gout) +static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out, bNodeStack **gin) { bNodeSocket *sock; /* build pointer stack */ - for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->intern) { - /* yep, intern can have link or is hidden socket */ - if(sock->link) - *(in++)= stack + sock->link->fromsock->stack_index; - else - *(in++)= &sock->ns; + if (in) { + for(sock= node->inputs.first; sock; sock= sock->next) { + *(in++) = get_socket_stack(stack, sock, gin); } - else - *(in++)= gin[sock->stack_index_ext]; } - for(sock= node->outputs.first; sock; sock= sock->next) { - if(sock->intern) - *(out++)= stack + sock->stack_index; - else - *(out++)= gout[sock->stack_index_ext]; + if (out) { + for(sock= node->outputs.first; sock; sock= sock->next) { + *(out++) = get_socket_stack(stack, sock, gin); + } } } -static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNodeStack **in, bNodeStack **out) +static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNodeStack **in) { bNode *node; bNodeTree *ntree= (bNodeTree *)gnode->id; @@ -1844,7 +1973,7 @@ static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNod for(node= ntree->nodes.first; node; node= node->next) { if(node->typeinfo->execfunc) { - group_node_get_stack(node, stack, nsin, nsout, in, out); + node_get_stack(node, stack, nsin, nsout, in); /* for groups, only execute outputs for edited group */ if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { @@ -1856,19 +1985,27 @@ static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNod } } - /* free internal group output nodes */ - if(ntree->type==NTREE_COMPOSIT) { - for(node= ntree->nodes.first; node; node= node->next) { - if(node->typeinfo->execfunc) { - bNodeSocket *sock; - - for(sock= node->outputs.first; sock; sock= sock->next) { - if(sock->intern) { - bNodeStack *ns= stack + sock->stack_index; - if(ns->data) { - free_compbuf(ns->data); - ns->data= NULL; - } + /* free internal buffers */ + if (ntree->type==NTREE_COMPOSIT) { + bNodeSocket *sock; + bNodeStack *ns; + for (sock=ntree->outputs.first; sock; sock=sock->next) { + /* use the hasoutput flag to tag external sockets */ + if (sock->stack_type==SOCK_STACK_LOCAL) { + ns= get_socket_stack(stack, sock, in); + ns->hasoutput = 0; + } + } + /* now free all stacks that are not used from outside */ + for (node=ntree->nodes.first; node; node=node->next) { + for (sock=node->outputs.first; sock; sock=sock->next) { + if (sock->stack_type==SOCK_STACK_LOCAL ) { + ns= get_socket_stack(stack, sock, in); + if (ns->hasoutput!=0 && ns->data) { + free_compbuf(ns->data); + ns->data = NULL; + /* reset the flag */ + ns->hasoutput = 1; } } } @@ -1876,37 +2013,134 @@ static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNod } } +static int set_stack_indexes_default(bNode *node, int index) +{ + bNodeSocket *sock; + + for (sock=node->inputs.first; sock; sock=sock->next) { + if (sock->link && sock->link->fromsock) { + sock->stack_type = sock->link->fromsock->stack_type; + sock->stack_index = sock->link->fromsock->stack_index; + sock->stack_ptr = sock->link->fromsock->stack_ptr; + } + else { + sock->stack_type = SOCK_STACK_CONST; + sock->stack_index = -1; + sock->stack_ptr = &sock->ns; + } + } + + for (sock=node->outputs.first; sock; sock=sock->next) { + sock->stack_type = SOCK_STACK_LOCAL; + sock->stack_index = index++; + sock->stack_ptr = NULL; + } + + return index; +} + +static int ntree_begin_exec_tree(bNodeTree *ntree); +static int set_stack_indexes_group(bNode *node, int index) +{ + bNodeTree *ngroup= (bNodeTree*)node->id; + bNodeSocket *sock; + + if((ngroup->init & NTREE_TYPE_INIT)==0) + ntreeInitTypes(ngroup); + + node->stack_index = index; + index += ntree_begin_exec_tree(ngroup); + + for (sock=node->inputs.first; sock; sock=sock->next) { + if (sock->link && sock->link->fromsock) { + sock->stack_type = sock->link->fromsock->stack_type; + sock->stack_index = sock->link->fromsock->stack_index; + sock->stack_ptr = sock->link->fromsock->stack_ptr; + } + else { + sock->stack_type = SOCK_STACK_CONST; + sock->stack_index = -1; + sock->stack_ptr = &sock->ns; + } + } + + /* identify group node outputs from internal group sockets */ + for(sock= node->outputs.first; sock; sock= sock->next) { + if (sock->groupsock) { + bNodeSocket *insock, *gsock = sock->groupsock; + switch (gsock->stack_type) { + case SOCK_STACK_EXTERN: + /* extern stack is resolved for this group node instance */ + insock= find_group_node_input(node, gsock->link->fromsock); + sock->stack_type = insock->stack_type; + sock->stack_index = insock->stack_index; + sock->stack_ptr = insock->stack_ptr; + break; + case SOCK_STACK_LOCAL: + sock->stack_type = SOCK_STACK_LOCAL; + /* local stack index must be offset by group node instance */ + sock->stack_index = gsock->stack_index + node->stack_index; + sock->stack_ptr = NULL; + break; + case SOCK_STACK_CONST: + sock->stack_type = SOCK_STACK_CONST; + sock->stack_index = -1; + sock->stack_ptr = gsock->stack_ptr; + break; + } + } + else { + sock->stack_type = SOCK_STACK_LOCAL; + sock->stack_index = index++; + sock->stack_ptr = NULL; + } + } + + return index; +} + /* recursively called for groups */ /* we set all trees on own local indices, but put a total counter in the groups, so each instance of a group has own stack */ static int ntree_begin_exec_tree(bNodeTree *ntree) { bNode *node; - bNodeSocket *sock; - int index= 0, index_in= 0, index_out= 0; + bNodeSocket *gsock; + int index= 0, i; if((ntree->init & NTREE_TYPE_INIT)==0) ntreeInitTypes(ntree); + /* group inputs are numbered 0..totinputs, so external stack can easily be addressed */ + i = 0; + for(gsock=ntree->inputs.first; gsock; gsock = gsock->next) { + gsock->stack_type = SOCK_STACK_EXTERN; + gsock->stack_index = i++; + gsock->stack_ptr = NULL; + } + /* create indices for stack, check preview */ for(node= ntree->nodes.first; node; node= node->next) { - - for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->intern==0) - sock->stack_index_ext= index_in++; - } - - for(sock= node->outputs.first; sock; sock= sock->next) { - sock->stack_index= index++; - if(sock->intern==0) - sock->stack_index_ext= index_out++; + /* XXX can this be done by a generic one-for-all function? + * otherwise should use node-type callback. + */ + if(node->type==NODE_GROUP) + index = set_stack_indexes_group(node, index); + else + index = set_stack_indexes_default(node, index); + } + + /* group outputs */ + for(gsock=ntree->outputs.first; gsock; gsock = gsock->next) { + if (gsock->link && gsock->link->fromsock) { + gsock->stack_type = gsock->link->fromsock->stack_type; + gsock->stack_index = gsock->link->fromsock->stack_index; + gsock->stack_ptr = gsock->link->fromsock->stack_ptr; } - - if(node->type==NODE_GROUP) { - if(node->id) { - node->stack_index= index; - index+= ntree_begin_exec_tree((bNodeTree *)node->id); - } + else { + gsock->stack_type = SOCK_STACK_CONST; + gsock->stack_index = -1; + gsock->stack_ptr = &gsock->ns; } } @@ -1914,7 +2148,7 @@ static int ntree_begin_exec_tree(bNodeTree *ntree) } /* copy socket compbufs to stack, initialize usage of curve nodes */ -static void composit_begin_exec(bNodeTree *ntree, int is_group) +static void composit_begin_exec(bNodeTree *ntree, bNodeStack *stack) { bNode *node; bNodeSocket *sock; @@ -1924,16 +2158,14 @@ static void composit_begin_exec(bNodeTree *ntree, int is_group) /* initialize needed for groups */ node->exec= 0; - if(is_group==0) { - for(sock= node->outputs.first; sock; sock= sock->next) { - bNodeStack *ns= ntree->stack + sock->stack_index; - - if(sock->ns.data) { - ns->data= sock->ns.data; - sock->ns.data= NULL; - } + for(sock= node->outputs.first; sock; sock= sock->next) { + bNodeStack *ns= get_socket_stack(stack, sock, NULL); + if(ns && sock->ns.data) { + ns->data= sock->ns.data; + sock->ns.data= NULL; } } + /* cannot initialize them while using in threads */ if(ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) { curvemapping_initialize(node->storage); @@ -1941,75 +2173,60 @@ static void composit_begin_exec(bNodeTree *ntree, int is_group) curvemapping_premultiply(node->storage, 0); } if(node->type==NODE_GROUP) - composit_begin_exec((bNodeTree *)node->id, 1); + composit_begin_exec((bNodeTree *)node->id, stack + node->stack_index); } } /* copy stack compbufs to sockets */ -static void composit_end_exec(bNodeTree *ntree, int is_group) +static void composit_end_exec(bNodeTree *ntree, bNodeStack *stack) { - extern void print_compbuf(char *str, struct CompBuf *cbuf); bNode *node; bNodeStack *ns; - int a; for(node= ntree->nodes.first; node; node= node->next) { - if(is_group==0) { - bNodeSocket *sock; + bNodeSocket *sock; - for(sock= node->outputs.first; sock; sock= sock->next) { - ns= ntree->stack + sock->stack_index; - if(ns->data) { - sock->ns.data= ns->data; - ns->data= NULL; - } + for(sock= node->outputs.first; sock; sock= sock->next) { + ns = get_socket_stack(stack, sock, NULL); + if(ns && ns->data) { + sock->ns.data= ns->data; + ns->data= NULL; } } + if(node->type==CMP_NODE_CURVE_RGB) curvemapping_premultiply(node->storage, 1); if(node->type==NODE_GROUP) - composit_end_exec((bNodeTree *)node->id, 1); + composit_end_exec((bNodeTree *)node->id, stack + node->stack_index); node->need_exec= 0; } - - if(is_group==0) { - /* internally, group buffers are not stored */ - for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++) { - if(ns->data) { - printf("freed leftover buffer from stack\n"); - free_compbuf(ns->data); - ns->data= NULL; - } - } - } } -static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack) +static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack, bNodeStack **gin) { bNodeTree *ntree= (bNodeTree *)gnode->id; bNode *node; + bNodeSocket *sock; stack+= gnode->stack_index; for(node= ntree->nodes.first; node; node= node->next) { if(node->typeinfo->execfunc) { - bNodeSocket *sock; - for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->intern) { - if(sock->link) { - bNodeStack *ns= stack + sock->link->fromsock->stack_index; - ns->hasoutput= 1; - ns->sockettype= sock->link->fromsock->type; - } - else - sock->ns.sockettype= sock->type; - } + bNodeStack *ns = get_socket_stack(stack, sock, gin); + ns->hasoutput= 1; } } + + /* set stack types (for local stack entries) */ + for(sock= node->outputs.first; sock; sock= sock->next) { + bNodeStack *ns = get_socket_stack(stack, sock, NULL); + if (ns) + ns->sockettype = sock->type; + } } } @@ -2067,6 +2284,8 @@ static void tex_end_exec(bNodeTree *ntree) void ntreeBeginExecTree(bNodeTree *ntree) { + bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ + /* let's make it sure */ if(ntree->init & NTREE_EXEC_INIT) return; @@ -2098,13 +2317,9 @@ void ntreeBeginExecTree(bNodeTree *ntree) node->need_exec= 1; for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->link) { - ns= ntree->stack + sock->link->fromsock->stack_index; - ns->hasoutput= 1; - ns->sockettype= sock->link->fromsock->type; - } - else - sock->ns.sockettype= sock->type; + ns = get_socket_stack(ntree->stack, sock, NULL); + if (ns) + ns->hasoutput = 1; if(sock->link) { bNodeLink *link= sock->link; @@ -2118,13 +2333,21 @@ void ntreeBeginExecTree(bNodeTree *ntree) } } - if(node->type==NODE_GROUP && node->id) - group_tag_used_outputs(node, ntree->stack); + /* set stack types (for local stack entries) */ + for(sock= node->outputs.first; sock; sock= sock->next) { + ns = get_socket_stack(ntree->stack, sock, NULL); + if (ns) + ns->sockettype = sock->type; + } + if(node->type==NODE_GROUP && node->id) { + node_get_stack(node, ntree->stack, nsin, NULL, NULL); + group_tag_used_outputs(node, ntree->stack, nsin); + } } if(ntree->type==NTREE_COMPOSIT) - composit_begin_exec(ntree, 0); + composit_begin_exec(ntree, ntree->stack); } ntree->init |= NTREE_EXEC_INIT; @@ -2132,14 +2355,24 @@ void ntreeBeginExecTree(bNodeTree *ntree) void ntreeEndExecTree(bNodeTree *ntree) { + bNodeStack *ns; if(ntree->init & NTREE_EXEC_INIT) { bNodeThreadStack *nts; int a; /* another callback candidate! */ - if(ntree->type==NTREE_COMPOSIT) - composit_end_exec(ntree, 0); + if(ntree->type==NTREE_COMPOSIT) { + composit_end_exec(ntree, ntree->stack); + + for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++) { + if(ns->data) { + printf("freed leftover buffer from stack\n"); + free_compbuf(ns->data); + ns->data= NULL; + } + } + } else if(ntree->type==NTREE_TEXTURE) tex_end_exec(ntree); @@ -2163,23 +2396,6 @@ void ntreeEndExecTree(bNodeTree *ntree) } } -static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out) -{ - bNodeSocket *sock; - - /* build pointer stack */ - for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->link) - *(in++)= stack + sock->link->fromsock->stack_index; - else - *(in++)= &sock->ns; - } - - for(sock= node->outputs.first; sock; sock= sock->next) { - *(out++)= stack + sock->stack_index; - } -} - /* nodes are presorted, so exec is in order of list */ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread) { @@ -2192,7 +2408,7 @@ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread) /* only when initialized */ if((ntree->init & NTREE_EXEC_INIT)==0) ntreeBeginExecTree(ntree); - + /* composite does 1 node per thread, so no multiple stacks needed */ if(ntree->type==NTREE_COMPOSIT) { stack= ntree->stack; @@ -2205,12 +2421,12 @@ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread) for(node= ntree->nodes.first; node; node= node->next) { if(node->need_exec) { if(node->typeinfo->execfunc) { - node_get_stack(node, stack, nsin, nsout); + node_get_stack(node, stack, nsin, nsout, NULL); node->typeinfo->execfunc(callerdata, node, nsin, nsout); } else if(node->type==NODE_GROUP && node->id) { - node_get_stack(node, stack, nsin, nsout); - node_group_execute(stack, callerdata, node, nsin, nsout); + node_get_stack(node, stack, nsin, NULL, NULL); + node_group_execute(stack, callerdata, node, nsin); } } } @@ -2256,7 +2472,7 @@ static void *exec_composite_node(void *node_v) bNode *node= node_v; ThreadData *thd= (ThreadData *)node->threaddata; - node_get_stack(node, thd->stack, nsin, nsout); + node_get_stack(node, thd->stack, nsin, nsout, NULL); if((node->flag & NODE_MUTED) && (!node_only_value(node))) { /* viewers we execute, for feedback to user */ @@ -2269,11 +2485,11 @@ static void *exec_composite_node(void *node_v) node->typeinfo->execfunc(thd->rd, node, nsin, nsout); } else if(node->type==NODE_GROUP && node->id) { - node_group_execute(thd->stack, thd->rd, node, nsin, nsout); + node_group_execute(thd->stack, thd->rd, node, nsin); } node->exec |= NODE_READY; - return 0; + return NULL; } /* return total of executable nodes, for timecursor */ @@ -2297,7 +2513,7 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) for(node= ntree->nodes.first; node; node= node->next) { int a; - node_get_stack(node, thd->stack, nsin, nsout); + node_get_stack(node, thd->stack, nsin, nsout, NULL); /* test the outputs */ /* skip value-only nodes (should be in type!) */ @@ -2362,7 +2578,7 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) for(node= ntree->nodes.first; node; node= node->next) { if(node->need_exec==0 && node_only_value(node)) { if(node->typeinfo->execfunc) { - node_get_stack(node, thd->stack, nsin, nsout); + node_get_stack(node, thd->stack, nsin, nsout, NULL); node->typeinfo->execfunc(thd->rd, node, nsin, nsout); } } @@ -2400,8 +2616,8 @@ static void freeExecutableNode(bNodeTree *ntree) for(node= ntree->nodes.first; node; node= node->next) { if(node->exec & NODE_FREEBUFS) { for(sock= node->outputs.first; sock; sock= sock->next) { - bNodeStack *ns= ntree->stack + sock->stack_index; - if(ns->data) { + bNodeStack *ns= get_socket_stack(ntree->stack, sock, NULL); + if(ns && ns->data) { free_compbuf(ns->data); ns->data= NULL; // printf("freed buf node %s \n", node->name); @@ -2421,7 +2637,7 @@ static bNode *getExecutableNode(bNodeTree *ntree) /* input sockets should be ready */ for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->link) + if(sock->link && sock->link->fromnode) if((sock->link->fromnode->exec & NODE_READY)==0) break; } @@ -2432,6 +2648,25 @@ static bNode *getExecutableNode(bNodeTree *ntree) return NULL; } +/* check if texture nodes need exec or end */ +static void ntree_composite_texnode(bNodeTree *ntree, int init) +{ + bNode *node; + + for(node= ntree->nodes.first; node; node= node->next) { + if(node->type==CMP_NODE_TEXTURE && node->id) { + Tex *tex= (Tex *)node->id; + if(tex->nodetree && tex->use_nodes) { + /* has internal flag to detect it only does it once */ + if(init) + ntreeBeginExecTree(tex->nodetree); + else + ntreeEndExecTree(tex->nodetree); + } + } + } + +} /* optimized tree execute test for compositing */ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) @@ -2447,6 +2682,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) ntreeInitPreview(ntree, 0, 0); ntreeBeginExecTree(ntree); + ntree_composite_texnode(ntree, 1); /* prevent unlucky accidents */ if(G.background) @@ -2459,6 +2695,9 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) /* fixed seed, for example noise texture */ BLI_srandom(rd->cfra); + /* ensures only a single output node is enabled */ + ntreeSetOutput(ntree); + /* sets need_exec tags in nodes */ curnode = totnode= setExecutableNodes(ntree, &thdata); @@ -2469,7 +2708,6 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) if(BLI_available_threads(&threads)) { node= getExecutableNode(ntree); if(node) { - if(ntree->progress && totnode) ntree->progress(ntree->prh, (1.0 - curnode/(float)totnode)); if(ntree->stats_draw) { @@ -2544,7 +2782,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) } /* node copy func */ - ltree= ntreeCopyTree(ntree, 0); + ltree= ntreeCopyTree(ntree); if(adt) { AnimData *ladt= BKE_animdata_from_id(<ree->id); @@ -2557,9 +2795,10 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) } /* end animdata uglyness */ - - /* move over the compbufs */ - /* right after ntreeCopyTree() oldsock pointers are valid */ + + /* ensures only a single output node is enabled */ + ntreeSetOutput(ntree); + for(node= ntree->nodes.first; node; node= node->next) { /* store new_node pointer to original */ @@ -2567,22 +2806,27 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) /* ensure new user input gets handled ok */ node->need_exec= 0; - if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { - if(node->id) { - if(node->flag & NODE_DO_OUTPUT) - node->new_node->id= (ID *)copy_image((Image *)node->id); - else - node->new_node->id= NULL; - } - } - - for(sock= node->outputs.first; sock; sock= sock->next) { + if(ntree->type==NTREE_COMPOSIT) { + /* move over the compbufs */ + /* right after ntreeCopyTree() oldsock pointers are valid */ - sock->new_sock->ns.data= sock->ns.data; - compbuf_set_node(sock->new_sock->ns.data, node->new_node); + if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if(node->id) { + if(node->flag & NODE_DO_OUTPUT) + node->new_node->id= (ID *)copy_image((Image *)node->id); + else + node->new_node->id= NULL; + } + } - sock->ns.data= NULL; - sock->new_sock->new_sock= sock; + for(sock= node->outputs.first; sock; sock= sock->next) { + + sock->new_sock->ns.data= sock->ns.data; + compbuf_set_node(sock->new_sock->ns.data, node->new_node); + + sock->ns.data= NULL; + sock->new_sock->new_sock= sock; + } } } @@ -2610,19 +2854,38 @@ static int outsocket_exists(bNode *node, bNodeSocket *testsock) /* sync local composite with real tree */ /* local composite is supposed to be running, be careful moving previews! */ +/* is called by jobs manager, outside threads, so it doesnt happen during draw */ void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree) { bNode *lnode; - /* move over the compbufs and previews */ - for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) { - if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) { + if(ntree->type==NTREE_COMPOSIT) { + /* move over the compbufs and previews */ + for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) { + if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) { + if(node_exists(ntree, lnode->new_node)) { + + if(lnode->preview && lnode->preview->rect) { + node_free_preview(lnode->new_node); + lnode->new_node->preview= lnode->preview; + lnode->preview= NULL; + } + } + } + } + } + else if(ntree->type==NTREE_SHADER) { + /* copy over contents of previews */ + for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) { if(node_exists(ntree, lnode->new_node)) { + bNode *node= lnode->new_node; - if(lnode->preview && lnode->preview->rect) { - node_free_preview(lnode->new_node); - lnode->new_node->preview= lnode->preview; - lnode->preview= NULL; + if(node->preview && node->preview->rect) { + if(lnode->preview && lnode->preview->rect) { + int xsize= node->preview->xsize; + int ysize= node->preview->ysize; + memcpy(node->preview->rect, lnode->preview->rect, 4*xsize + xsize*ysize*sizeof(char)*4); + } } } } @@ -2693,7 +2956,7 @@ static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack gs[i].name = ""; gs[i].hasinput= ns[i]->hasinput && ns[i]->data; - gs[i].hasoutput= ns[i]->hasinput && ns[i]->data; + gs[i].hasoutput= ns[i]->hasoutput && ns[i]->data; gs[i].sockettype= ns[i]->sockettype; } @@ -2707,13 +2970,11 @@ static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack for (sock=sockets->first, i=0; sock; sock=sock->next, i++) { ns[i]->data= gs[i].link; - ns[i]->hasinput= gs[i].hasinput && gs[i].link; - ns[i]->hasoutput= gs[i].hasoutput; ns[i]->sockettype= gs[i].sockettype; } } -static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in, bNodeStack **out) +static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in) { bNode *node; bNodeTree *ntree= (bNodeTree *)gnode->id; @@ -2728,7 +2989,7 @@ static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *g for(node= ntree->nodes.first; node; node= node->next) { if(node->typeinfo->gpufunc) { - group_node_get_stack(node, stack, nsin, nsout, in, out); + node_get_stack(node, stack, nsin, nsout, in); doit = 0; @@ -2766,15 +3027,15 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat) for(node= ntree->nodes.first; node; node= node->next) { if(node->typeinfo->gpufunc) { - node_get_stack(node, stack, nsin, nsout); + node_get_stack(node, stack, nsin, nsout, NULL); gpu_from_node_stack(&node->inputs, nsin, gpuin); gpu_from_node_stack(&node->outputs, nsout, gpuout); if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) data_from_gpu_stack(&node->outputs, nsout, gpuout); } else if(node->type==NODE_GROUP && node->id) { - node_get_stack(node, stack, nsin, nsout); - gpu_node_group_execute(stack, mat, node, nsin, nsout); + node_get_stack(node, stack, nsin, nsout, NULL); + gpu_node_group_execute(stack, mat, node, nsin); } } @@ -2884,6 +3145,8 @@ void ntreeCompositTagRender(Scene *curscene) for(node= sce->nodetree->nodes.first; node; node= node->next) { if(node->id==(ID *)curscene || node->type==CMP_NODE_COMPOSITE) NodeTagChanged(sce->nodetree, node); + else if(node->type==CMP_NODE_TEXTURE) /* uses scene sizex/sizey */ + NodeTagChanged(sce->nodetree, node); } } } @@ -2899,7 +3162,7 @@ static int node_animation_properties(bNodeTree *ntree, bNode *node) /* check to see if any of the node's properties have fcurves */ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr); - lb = RNA_struct_defined_properties(ptr.type); + lb = RNA_struct_type_properties(ptr.type); for (link=lb->first; link; link=link->next) { int driven, len=1, index; @@ -2961,10 +3224,7 @@ int ntreeCompositTagAnimated(bNodeTree *ntree) NodeTagChanged(ntree, node); tagged= 1; } - else if(node->type==CMP_NODE_R_LAYERS) { - NodeTagChanged(ntree, node); - tagged= 1; - } + /* here was tag render layer, but this is called after a render, so re-composites fail */ else if(node->type==NODE_GROUP) { if( ntreeCompositTagAnimated((bNodeTree *)node->id) ) { NodeTagChanged(ntree, node); @@ -2989,6 +3249,21 @@ void ntreeCompositTagGenerators(bNodeTree *ntree) } } +/* XXX after render animation system gets a refresh, this call allows composite to end clean */ +void ntreeClearTags(bNodeTree *ntree) +{ + bNode *node; + + if(ntree==NULL) return; + + for(node= ntree->nodes.first; node; node= node->next) { + node->need_exec= 0; + if(node->type==NODE_GROUP) + ntreeClearTags((bNodeTree *)node->id); + } +} + + int ntreeTexTagAnimated(bNodeTree *ntree) { bNode *node; @@ -3012,6 +3287,62 @@ int ntreeTexTagAnimated(bNodeTree *ntree) /* ************* node definition init ********** */ +void node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag, + struct bNodeSocketType *inputs, struct bNodeSocketType *outputs) +{ + memset(ntype, 0, sizeof(bNodeType)); + + ntype->type = type; + ntype->name = name; + ntype->nclass = nclass; + ntype->flag = flag; + + ntype->inputs = inputs; + ntype->outputs = outputs; + + /* default size values */ + ntype->width = 140; + ntype->minwidth = 100; + ntype->maxwidth = 320; +} + +void node_type_init(bNodeType *ntype, void (*initfunc)(struct bNode *)) +{ + ntype->initfunc = initfunc; +} + +void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth) +{ + ntype->width = width; + ntype->minwidth = minwidth; + ntype->maxwidth = maxwidth; +} + +void node_type_storage(bNodeType *ntype, const char *storagename, void (*freestoragefunc)(struct bNode *), void (*copystoragefunc)(struct bNode *, struct bNode *)) +{ + if (storagename) + strncpy(ntype->storagename, storagename, sizeof(ntype->storagename)); + else + ntype->storagename[0] = '\0'; + ntype->copystoragefunc = copystoragefunc; + ntype->freestoragefunc = freestoragefunc; +} + +void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **)) +{ + ntype->execfunc = execfunc; +} + +void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out)) +{ + ntype->gpufunc = gpufunc; +} + +void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *)) +{ + ntype->labelfunc = labelfunc; +} + static bNodeType *is_nodetype_registered(ListBase *typelist, int type, ID *id) { bNodeType *ntype= typelist->first; @@ -3037,147 +3368,150 @@ void nodeRegisterType(ListBase *typelist, const bNodeType *ntype) static void registerCompositNodes(ListBase *ntypelist) { - nodeRegisterType(ntypelist, &node_group_typeinfo); - nodeRegisterType(ntypelist, &cmp_node_rlayers); - nodeRegisterType(ntypelist, &cmp_node_image); - nodeRegisterType(ntypelist, &cmp_node_texture); - nodeRegisterType(ntypelist, &cmp_node_value); - nodeRegisterType(ntypelist, &cmp_node_rgb); - nodeRegisterType(ntypelist, &cmp_node_curve_time); - - nodeRegisterType(ntypelist, &cmp_node_composite); - nodeRegisterType(ntypelist, &cmp_node_viewer); - nodeRegisterType(ntypelist, &cmp_node_splitviewer); - nodeRegisterType(ntypelist, &cmp_node_output_file); - nodeRegisterType(ntypelist, &cmp_node_view_levels); - - nodeRegisterType(ntypelist, &cmp_node_curve_rgb); - nodeRegisterType(ntypelist, &cmp_node_mix_rgb); - nodeRegisterType(ntypelist, &cmp_node_hue_sat); - nodeRegisterType(ntypelist, &cmp_node_brightcontrast); - nodeRegisterType(ntypelist, &cmp_node_gamma); - nodeRegisterType(ntypelist, &cmp_node_invert); - nodeRegisterType(ntypelist, &cmp_node_alphaover); - nodeRegisterType(ntypelist, &cmp_node_zcombine); - nodeRegisterType(ntypelist, &cmp_node_colorbalance); - nodeRegisterType(ntypelist, &cmp_node_huecorrect); - - nodeRegisterType(ntypelist, &cmp_node_normal); - nodeRegisterType(ntypelist, &cmp_node_curve_vec); - nodeRegisterType(ntypelist, &cmp_node_map_value); - nodeRegisterType(ntypelist, &cmp_node_normalize); - - nodeRegisterType(ntypelist, &cmp_node_filter); - nodeRegisterType(ntypelist, &cmp_node_blur); - nodeRegisterType(ntypelist, &cmp_node_dblur); - nodeRegisterType(ntypelist, &cmp_node_bilateralblur); - nodeRegisterType(ntypelist, &cmp_node_vecblur); - nodeRegisterType(ntypelist, &cmp_node_dilateerode); - nodeRegisterType(ntypelist, &cmp_node_defocus); - - nodeRegisterType(ntypelist, &cmp_node_valtorgb); - nodeRegisterType(ntypelist, &cmp_node_rgbtobw); - nodeRegisterType(ntypelist, &cmp_node_setalpha); - nodeRegisterType(ntypelist, &cmp_node_idmask); - nodeRegisterType(ntypelist, &cmp_node_math); - nodeRegisterType(ntypelist, &cmp_node_seprgba); - nodeRegisterType(ntypelist, &cmp_node_combrgba); - nodeRegisterType(ntypelist, &cmp_node_sephsva); - nodeRegisterType(ntypelist, &cmp_node_combhsva); - nodeRegisterType(ntypelist, &cmp_node_sepyuva); - nodeRegisterType(ntypelist, &cmp_node_combyuva); - nodeRegisterType(ntypelist, &cmp_node_sepycca); - nodeRegisterType(ntypelist, &cmp_node_combycca); - nodeRegisterType(ntypelist, &cmp_node_premulkey); - - nodeRegisterType(ntypelist, &cmp_node_diff_matte); - nodeRegisterType(ntypelist, &cmp_node_distance_matte); - nodeRegisterType(ntypelist, &cmp_node_chroma_matte); - nodeRegisterType(ntypelist, &cmp_node_color_matte); - nodeRegisterType(ntypelist, &cmp_node_channel_matte); - nodeRegisterType(ntypelist, &cmp_node_color_spill); - nodeRegisterType(ntypelist, &cmp_node_luma_matte); - - nodeRegisterType(ntypelist, &cmp_node_translate); - nodeRegisterType(ntypelist, &cmp_node_rotate); - nodeRegisterType(ntypelist, &cmp_node_scale); - nodeRegisterType(ntypelist, &cmp_node_flip); - nodeRegisterType(ntypelist, &cmp_node_crop); - nodeRegisterType(ntypelist, &cmp_node_displace); - nodeRegisterType(ntypelist, &cmp_node_mapuv); - nodeRegisterType(ntypelist, &cmp_node_glare); - nodeRegisterType(ntypelist, &cmp_node_tonemap); - nodeRegisterType(ntypelist, &cmp_node_lensdist); + register_node_type_group(ntypelist); + + register_node_type_cmp_rlayers(ntypelist); + register_node_type_cmp_image(ntypelist); + register_node_type_cmp_texture(ntypelist); + register_node_type_cmp_value(ntypelist); + register_node_type_cmp_rgb(ntypelist); + register_node_type_cmp_curve_time(ntypelist); + + register_node_type_cmp_composite(ntypelist); + register_node_type_cmp_viewer(ntypelist); + register_node_type_cmp_splitviewer(ntypelist); + register_node_type_cmp_output_file(ntypelist); + register_node_type_cmp_view_levels(ntypelist); + + register_node_type_cmp_curve_rgb(ntypelist); + register_node_type_cmp_mix_rgb(ntypelist); + register_node_type_cmp_hue_sat(ntypelist); + register_node_type_cmp_brightcontrast(ntypelist); + register_node_type_cmp_gamma(ntypelist); + register_node_type_cmp_invert(ntypelist); + register_node_type_cmp_alphaover(ntypelist); + register_node_type_cmp_zcombine(ntypelist); + register_node_type_cmp_colorbalance(ntypelist); + register_node_type_cmp_huecorrect(ntypelist); + + register_node_type_cmp_normal(ntypelist); + register_node_type_cmp_curve_vec(ntypelist); + register_node_type_cmp_map_value(ntypelist); + register_node_type_cmp_normalize(ntypelist); + + register_node_type_cmp_filter(ntypelist); + register_node_type_cmp_blur(ntypelist); + register_node_type_cmp_dblur(ntypelist); + register_node_type_cmp_bilateralblur(ntypelist); + register_node_type_cmp_vecblur(ntypelist); + register_node_type_cmp_dilateerode(ntypelist); + register_node_type_cmp_defocus(ntypelist); + + register_node_type_cmp_valtorgb(ntypelist); + register_node_type_cmp_rgbtobw(ntypelist); + register_node_type_cmp_setalpha(ntypelist); + register_node_type_cmp_idmask(ntypelist); + register_node_type_cmp_math(ntypelist); + register_node_type_cmp_seprgba(ntypelist); + register_node_type_cmp_combrgba(ntypelist); + register_node_type_cmp_sephsva(ntypelist); + register_node_type_cmp_combhsva(ntypelist); + register_node_type_cmp_sepyuva(ntypelist); + register_node_type_cmp_combyuva(ntypelist); + register_node_type_cmp_sepycca(ntypelist); + register_node_type_cmp_combycca(ntypelist); + register_node_type_cmp_premulkey(ntypelist); + + register_node_type_cmp_diff_matte(ntypelist); + register_node_type_cmp_distance_matte(ntypelist); + register_node_type_cmp_chroma_matte(ntypelist); + register_node_type_cmp_color_matte(ntypelist); + register_node_type_cmp_channel_matte(ntypelist); + register_node_type_cmp_color_spill(ntypelist); + register_node_type_cmp_luma_matte(ntypelist); + + register_node_type_cmp_translate(ntypelist); + register_node_type_cmp_rotate(ntypelist); + register_node_type_cmp_scale(ntypelist); + register_node_type_cmp_flip(ntypelist); + register_node_type_cmp_crop(ntypelist); + register_node_type_cmp_displace(ntypelist); + register_node_type_cmp_mapuv(ntypelist); + register_node_type_cmp_glare(ntypelist); + register_node_type_cmp_tonemap(ntypelist); + register_node_type_cmp_lensdist(ntypelist); } static void registerShaderNodes(ListBase *ntypelist) { - nodeRegisterType(ntypelist, &node_group_typeinfo); - nodeRegisterType(ntypelist, &sh_node_output); - nodeRegisterType(ntypelist, &sh_node_mix_rgb); - nodeRegisterType(ntypelist, &sh_node_valtorgb); - nodeRegisterType(ntypelist, &sh_node_rgbtobw); - nodeRegisterType(ntypelist, &sh_node_normal); - nodeRegisterType(ntypelist, &sh_node_geom); - nodeRegisterType(ntypelist, &sh_node_mapping); - nodeRegisterType(ntypelist, &sh_node_curve_vec); - nodeRegisterType(ntypelist, &sh_node_curve_rgb); - nodeRegisterType(ntypelist, &sh_node_math); - nodeRegisterType(ntypelist, &sh_node_vect_math); - nodeRegisterType(ntypelist, &sh_node_squeeze); - nodeRegisterType(ntypelist, &sh_node_camera); - nodeRegisterType(ntypelist, &sh_node_material); - nodeRegisterType(ntypelist, &sh_node_material_ext); - nodeRegisterType(ntypelist, &sh_node_value); - nodeRegisterType(ntypelist, &sh_node_rgb); - nodeRegisterType(ntypelist, &sh_node_texture); - nodeRegisterType(ntypelist, &node_dynamic_typeinfo); - nodeRegisterType(ntypelist, &sh_node_invert); - nodeRegisterType(ntypelist, &sh_node_seprgb); - nodeRegisterType(ntypelist, &sh_node_combrgb); - nodeRegisterType(ntypelist, &sh_node_hue_sat); + register_node_type_group(ntypelist); + + register_node_type_sh_output(ntypelist); + register_node_type_sh_mix_rgb(ntypelist); + register_node_type_sh_valtorgb(ntypelist); + register_node_type_sh_rgbtobw(ntypelist); + register_node_type_sh_normal(ntypelist); + register_node_type_sh_geom(ntypelist); + register_node_type_sh_mapping(ntypelist); + register_node_type_sh_curve_vec(ntypelist); + register_node_type_sh_curve_rgb(ntypelist); + register_node_type_sh_math(ntypelist); + register_node_type_sh_vect_math(ntypelist); + register_node_type_sh_squeeze(ntypelist); + register_node_type_sh_camera(ntypelist); + register_node_type_sh_material(ntypelist); + register_node_type_sh_material_ext(ntypelist); + register_node_type_sh_value(ntypelist); + register_node_type_sh_rgb(ntypelist); + register_node_type_sh_texture(ntypelist); +// register_node_type_sh_dynamic(ntypelist); + register_node_type_sh_invert(ntypelist); + register_node_type_sh_seprgb(ntypelist); + register_node_type_sh_combrgb(ntypelist); + register_node_type_sh_hue_sat(ntypelist); } static void registerTextureNodes(ListBase *ntypelist) { - nodeRegisterType(ntypelist, &node_group_typeinfo); - nodeRegisterType(ntypelist, &tex_node_math); - nodeRegisterType(ntypelist, &tex_node_mix_rgb); - nodeRegisterType(ntypelist, &tex_node_valtorgb); - nodeRegisterType(ntypelist, &tex_node_rgbtobw); - nodeRegisterType(ntypelist, &tex_node_valtonor); - nodeRegisterType(ntypelist, &tex_node_curve_rgb); - nodeRegisterType(ntypelist, &tex_node_curve_time); - nodeRegisterType(ntypelist, &tex_node_invert); - nodeRegisterType(ntypelist, &tex_node_hue_sat); - nodeRegisterType(ntypelist, &tex_node_coord); - nodeRegisterType(ntypelist, &tex_node_distance); - nodeRegisterType(ntypelist, &tex_node_compose); - nodeRegisterType(ntypelist, &tex_node_decompose); - - nodeRegisterType(ntypelist, &tex_node_output); - nodeRegisterType(ntypelist, &tex_node_viewer); - - nodeRegisterType(ntypelist, &tex_node_checker); - nodeRegisterType(ntypelist, &tex_node_texture); - nodeRegisterType(ntypelist, &tex_node_bricks); - nodeRegisterType(ntypelist, &tex_node_image); - - nodeRegisterType(ntypelist, &tex_node_rotate); - nodeRegisterType(ntypelist, &tex_node_translate); - nodeRegisterType(ntypelist, &tex_node_scale); - nodeRegisterType(ntypelist, &tex_node_at); - - nodeRegisterType(ntypelist, &tex_node_proc_voronoi); - nodeRegisterType(ntypelist, &tex_node_proc_blend); - nodeRegisterType(ntypelist, &tex_node_proc_magic); - nodeRegisterType(ntypelist, &tex_node_proc_marble); - nodeRegisterType(ntypelist, &tex_node_proc_clouds); - nodeRegisterType(ntypelist, &tex_node_proc_wood); - nodeRegisterType(ntypelist, &tex_node_proc_musgrave); - nodeRegisterType(ntypelist, &tex_node_proc_noise); - nodeRegisterType(ntypelist, &tex_node_proc_stucci); - nodeRegisterType(ntypelist, &tex_node_proc_distnoise); + register_node_type_group(ntypelist); + + register_node_type_tex_math(ntypelist); + register_node_type_tex_mix_rgb(ntypelist); + register_node_type_tex_valtorgb(ntypelist); + register_node_type_tex_rgbtobw(ntypelist); + register_node_type_tex_valtonor(ntypelist); + register_node_type_tex_curve_rgb(ntypelist); + register_node_type_tex_curve_time(ntypelist); + register_node_type_tex_invert(ntypelist); + register_node_type_tex_hue_sat(ntypelist); + register_node_type_tex_coord(ntypelist); + register_node_type_tex_distance(ntypelist); + register_node_type_tex_compose(ntypelist); + register_node_type_tex_decompose(ntypelist); + + register_node_type_tex_output(ntypelist); + register_node_type_tex_viewer(ntypelist); + + register_node_type_tex_checker(ntypelist); + register_node_type_tex_texture(ntypelist); + register_node_type_tex_bricks(ntypelist); + register_node_type_tex_image(ntypelist); + + register_node_type_tex_rotate(ntypelist); + register_node_type_tex_translate(ntypelist); + register_node_type_tex_scale(ntypelist); + register_node_type_tex_at(ntypelist); + + register_node_type_tex_proc_voronoi(ntypelist); + register_node_type_tex_proc_blend(ntypelist); + register_node_type_tex_proc_magic(ntypelist); + register_node_type_tex_proc_marble(ntypelist); + register_node_type_tex_proc_clouds(ntypelist); + register_node_type_tex_proc_wood(ntypelist); + register_node_type_tex_proc_musgrave(ntypelist); + register_node_type_tex_proc_noise(ntypelist); + register_node_type_tex_proc_stucci(ntypelist); + register_node_type_tex_proc_distnoise(ntypelist); } static void remove_dynamic_typeinfos(ListBase *list) @@ -3191,7 +3525,7 @@ static void remove_dynamic_typeinfos(ListBase *list) if(ntype->inputs) { bNodeSocketType *sock= ntype->inputs; while(sock->type!=-1) { - MEM_freeN(sock->name); + MEM_freeN((void *)sock->name); sock++; } MEM_freeN(ntype->inputs); @@ -3199,13 +3533,13 @@ static void remove_dynamic_typeinfos(ListBase *list) if(ntype->outputs) { bNodeSocketType *sock= ntype->outputs; while(sock->type!=-1) { - MEM_freeN(sock->name); + MEM_freeN((void *)sock->name); sock++; } MEM_freeN(ntype->outputs); } if(ntype->name) { - MEM_freeN(ntype->name); + MEM_freeN((void *)ntype->name); } MEM_freeN(ntype); } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index eddcceb560f..9910392e2d0 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -57,12 +57,11 @@ #include "BLI_editVert.h" #include "BLI_math.h" #include "BLI_pbvh.h" - -#include "BKE_utildefines.h" +#include "BLI_utildefines.h" #include "BKE_main.h" #include "BKE_global.h" - +#include "BKE_idprop.h" #include "BKE_armature.h" #include "BKE_action.h" #include "BKE_bullet.h" @@ -97,7 +96,7 @@ #include "LBM_fluidsim.h" -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON #include "BPY_extern.h" #endif @@ -246,6 +245,13 @@ void free_sculptsession(Object *ob) if(ss->layer_co) MEM_freeN(ss->layer_co); + if(ss->orig_cos) + MEM_freeN(ss->orig_cos); + if(ss->deform_cos) + MEM_freeN(ss->deform_cos); + if(ss->deform_imats) + MEM_freeN(ss->deform_imats); + MEM_freeN(ss); ob->sculpt = NULL; @@ -268,7 +274,7 @@ void free_object(Object *ob) else if(ob->type==OB_CURVE) unlink_curve(ob->data); else if(ob->type==OB_MBALL) unlink_mball(ob->data); } - ob->data= 0; + ob->data= NULL; } for(a=0; a<ob->totcol; a++) { @@ -276,12 +282,12 @@ void free_object(Object *ob) } if(ob->mat) MEM_freeN(ob->mat); if(ob->matbits) MEM_freeN(ob->matbits); - ob->mat= 0; - ob->matbits= 0; + ob->mat= NULL; + ob->matbits= NULL; if(ob->bb) MEM_freeN(ob->bb); - ob->bb= 0; + ob->bb= NULL; if(ob->path) free_path(ob->path); - ob->path= 0; + ob->path= NULL; if(ob->adt) BKE_free_animdata((ID *)ob); if(ob->poselib) ob->poselib->id.us--; if(ob->gpd) ((ID *)ob->gpd)->us--; @@ -317,11 +323,11 @@ static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Objec if (*obpoin==unlinkOb) { *obpoin = NULL; - ob->recalc |= OB_RECALC_ALL; // XXX: should this just be OB_RECALC_DATA? + ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; // XXX: should this just be OB_RECALC_DATA? } } -void unlink_object(Scene *scene, Object *ob) +void unlink_object(Object *ob) { Main *bmain= G.main; Object *obt; @@ -358,7 +364,7 @@ void unlink_object(Scene *scene, Object *ob) if(obt->parent==ob) { obt->parent= NULL; - obt->recalc |= OB_RECALC_ALL; + obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; } modifiers_foreachObjectLink(obt, unlink_object__unlinkModifierLinks, ob); @@ -368,15 +374,15 @@ void unlink_object(Scene *scene, Object *ob) if(cu->bevobj==ob) { cu->bevobj= NULL; - obt->recalc |= OB_RECALC_ALL; + obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; } if(cu->taperobj==ob) { cu->taperobj= NULL; - obt->recalc |= OB_RECALC_ALL; + obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; } if(cu->textoncurve==ob) { cu->textoncurve= NULL; - obt->recalc |= OB_RECALC_ALL; + obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; } } else if(obt->type==OB_ARMATURE && obt->pose) { @@ -533,12 +539,10 @@ void unlink_object(Scene *scene, Object *ob) } /* textures */ - tex= bmain->tex.first; - while(tex) { - if(tex->env) { - if(tex->env->object == ob) tex->env->object= NULL; - } - tex= tex->id.next; + for(tex= bmain->tex.first; tex; tex= tex->id.next) { + if(tex->env && (ob==tex->env->object)) tex->env->object= NULL; + if(tex->pd && (ob==tex->pd->object)) tex->pd->object= NULL; + if(tex->vd && (ob==tex->vd->object)) tex->vd->object= NULL; } /* worlds */ @@ -696,7 +700,7 @@ int exist_object(Object *obtest) return 0; } -void *add_camera(char *name) +void *add_camera(const char *name) { Camera *cam; @@ -718,7 +722,6 @@ Camera *copy_camera(Camera *cam) Camera *camn; camn= copy_libblock(cam); - camn->adt= BKE_copy_animdata(cam->adt); return camn; } @@ -737,11 +740,11 @@ void make_local_camera(Camera *cam) * - mixed: make copy */ - if(cam->id.lib==0) return; + if(cam->id.lib==NULL) return; if(cam->id.us==1) { - cam->id.lib= 0; + cam->id.lib= NULL; cam->id.flag= LIB_LOCAL; - new_id(0, (ID *)cam, 0); + new_id(NULL, (ID *)cam, NULL); return; } @@ -755,9 +758,9 @@ void make_local_camera(Camera *cam) } if(local && lib==0) { - cam->id.lib= 0; + cam->id.lib= NULL; cam->id.flag= LIB_LOCAL; - new_id(0, (ID *)cam, 0); + new_id(NULL, (ID *)cam, NULL); } else if(local && lib) { camn= copy_camera(cam); @@ -767,7 +770,7 @@ void make_local_camera(Camera *cam) while(ob) { if(ob->data==cam) { - if(ob->id.lib==0) { + if(ob->id.lib==NULL) { ob->data= camn; camn->id.us++; cam->id.us--; @@ -798,7 +801,7 @@ float dof_camera(Object *ob) return cam->YF_dofdist; } -void *add_lamp(char *name) +void *add_lamp(const char *name) { Lamp *la; @@ -886,11 +889,11 @@ void make_local_lamp(Lamp *la) * - mixed: make copy */ - if(la->id.lib==0) return; + if(la->id.lib==NULL) return; if(la->id.us==1) { - la->id.lib= 0; + la->id.lib= NULL; la->id.flag= LIB_LOCAL; - new_id(0, (ID *)la, 0); + new_id(NULL, (ID *)la, NULL); return; } @@ -904,9 +907,9 @@ void make_local_lamp(Lamp *la) } if(local && lib==0) { - la->id.lib= 0; + la->id.lib= NULL; la->id.flag= LIB_LOCAL; - new_id(0, (ID *)la, 0); + new_id(NULL, (ID *)la, NULL); } else if(local && lib) { lan= copy_lamp(la); @@ -916,7 +919,7 @@ void make_local_lamp(Lamp *la) while(ob) { if(ob->data==la) { - if(ob->id.lib==0) { + if(ob->id.lib==NULL) { ob->data= lan; lan->id.us++; la->id.us--; @@ -973,7 +976,7 @@ static void *add_obdata_from_type(int type) } } -static char *get_obdata_defname(int type) +static const char *get_obdata_defname(int type) { switch (type) { case OB_MESH: return "Mesh"; @@ -993,7 +996,7 @@ static char *get_obdata_defname(int type) } /* more general add: creates minimum required data, but without vertices etc. */ -Object *add_only_object(int type, char *name) +Object *add_only_object(int type, const char *name) { Object *ob; @@ -1011,10 +1014,13 @@ Object *add_only_object(int type, char *name) * but rotations default to quaternions */ ob->rotmode= ROT_MODE_EUL; - /* axis-angle must not have a 0,0,0 axis, so set y-axis as default... */ - ob->rotAxis[1]= ob->drotAxis[1]= 1.0f; - /* quaternions should be 1,0,0,0 by default.... */ - ob->quat[0]= ob->dquat[0]= 1.0f; + + unit_axis_angle(ob->rotAxis, &ob->rotAngle); + unit_axis_angle(ob->drotAxis, &ob->drotAngle); + + unit_qt(ob->quat); + unit_qt(ob->dquat); + /* rotation locks should be 4D for 4 component rotations by default... */ ob->protectflag = OB_LOCK_ROT4D; @@ -1022,7 +1028,7 @@ Object *add_only_object(int type, char *name) unit_m4(ob->parentinv); unit_m4(ob->obmat); ob->dt= OB_TEXTURE; - ob->empty_drawtype= OB_ARROWS; + ob->empty_drawtype= OB_PLAINAXES; ob->empty_drawsize= 1.0; if(type==OB_CAMERA || type==OB_LAMP) { @@ -1073,7 +1079,7 @@ Object *add_object(struct Scene *scene, int type) Base *base; char name[32]; - strcpy(name, get_obdata_defname(type)); + BLI_strncpy(name, get_obdata_defname(type), sizeof(name)); ob = add_only_object(type, name); ob->data= add_obdata_from_type(type); @@ -1082,7 +1088,7 @@ Object *add_object(struct Scene *scene, int type) base= scene_add_base(scene, ob); scene_select_base(scene, base); - ob->recalc |= OB_RECALC_ALL; + ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; return ob; } @@ -1122,7 +1128,7 @@ BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb) return bsbn; } -ParticleSystem *copy_particlesystem(ParticleSystem *psys) +static ParticleSystem *copy_particlesystem(ParticleSystem *psys) { ParticleSystem *psysn; ParticleData *pa; @@ -1267,6 +1273,17 @@ static void copy_object_pose(Object *obn, Object *ob) } } +static void copy_object_transform(Object *ob_tar, Object *ob_src) +{ + copy_v3_v3(ob_tar->loc, ob_src->loc); + copy_v3_v3(ob_tar->rot, ob_src->rot); + copy_v3_v3(ob_tar->quat, ob_src->quat); + copy_v3_v3(ob_tar->rotAxis, ob_src->rotAxis); + ob_tar->rotAngle= ob_src->rotAngle; + ob_tar->rotmode= ob_src->rotmode; + copy_v3_v3(ob_tar->size, ob_src->size); +} + Object *copy_object(Object *ob) { Object *obn; @@ -1315,8 +1332,8 @@ Object *copy_object(Object *ob) /* increase user numbers */ id_us_plus((ID *)obn->data); + id_us_plus((ID *)obn->gpd); id_lib_extern((ID *)obn->dup_group); - for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]); @@ -1339,6 +1356,8 @@ Object *copy_object(Object *ob) obn->gpulamp.first = obn->gpulamp.last = NULL; obn->pc_ids.first = obn->pc_ids.last = NULL; + + obn->mpath= NULL; return obn; } @@ -1466,7 +1485,7 @@ static void armature_set_id_extern(Object *ob) { bArmature *arm= ob->data; bPoseChannel *pchan; - int lay= arm->layer_protected; + unsigned int lay= arm->layer_protected; for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) { if(!(pchan->bone->layer & lay)) @@ -1529,25 +1548,25 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) ob->proxy_group= gob; id_lib_extern(&target->id); - ob->recalc= target->recalc= OB_RECALC_ALL; + ob->recalc= target->recalc= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; - /* copy transform */ + /* copy transform + * - gob means this proxy comes from a group, just apply the matrix + * so the object wont move from its dupli-transform. + * + * - no gob means this is being made from a linked object, + * this is closer to making a copy of the object - in-place. */ if(gob) { - VECCOPY(ob->loc, gob->loc); - VECCOPY(ob->rot, gob->rot); - VECCOPY(ob->size, gob->size); - - group_tag_recalc(gob->dup_group); + ob->rotmode= target->rotmode; + mul_m4_m4m4(ob->obmat, target->obmat, gob->obmat); + object_apply_mat4(ob, ob->obmat, FALSE, TRUE); } else { - VECCOPY(ob->loc, target->loc); - VECCOPY(ob->rot, target->rot); - VECCOPY(ob->size, target->size); + copy_object_transform(ob, target); + ob->parent= target->parent; /* libdata */ + copy_m4_m4(ob->parentinv, target->parentinv); } - ob->parent= target->parent; /* libdata */ - copy_m4_m4(ob->parentinv, target->parentinv); - /* copy animdata stuff - drivers only for now... */ object_copy_proxy_drivers(ob, target); @@ -1588,7 +1607,17 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) armature_set_id_extern(ob); } - + + /* copy IDProperties */ + if(ob->id.properties) { + IDP_FreeProperty(ob->id.properties); + MEM_freeN(ob->id.properties); + ob->id.properties= NULL; + } + if(target->id.properties) { + ob->id.properties= IDP_CopyProperty(target->id.properties); + } + /* copy drawtype info */ ob->dt= target->dt; } @@ -1598,7 +1627,7 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) /* there is also a timing calculation in drawobject() */ -int no_speed_curve= 0; +static int no_speed_curve= 0; void disable_speed_curve(int val) { @@ -1607,7 +1636,7 @@ void disable_speed_curve(int val) // XXX THIS CRUFT NEEDS SERIOUS RECODING ASAP! /* ob can be NULL */ -float bsystem_time(struct Scene *scene, Object *ob, float cfra, float ofs) +float bsystem_time(struct Scene *scene, Object *UNUSED(ob), float cfra, float ofs) { /* returns float ( see BKE_curframe in scene.c) */ cfra += scene->r.subframe; @@ -1636,7 +1665,7 @@ void object_scale_to_mat3(Object *ob, float mat[][3]) size_to_mat3( mat,vec); } -// TODO: this should take rotation orders into account later... + void object_rot_to_mat3(Object *ob, float mat[][3]) { float rmat[3][3], dmat[3][3]; @@ -1659,41 +1688,67 @@ void object_rot_to_mat3(Object *ob, float mat[][3]) } else { /* quats are normalised before use to eliminate scaling issues */ - normalize_qt(ob->quat); - quat_to_mat3( rmat,ob->quat); - quat_to_mat3( dmat,ob->dquat); + float tquat[4]; + + normalize_qt_qt(tquat, ob->quat); + quat_to_mat3(rmat, tquat); + + normalize_qt_qt(tquat, ob->dquat); + quat_to_mat3(dmat, tquat); } /* combine these rotations */ - // XXX is this correct? if errors, change the order of multiplication... mul_m3_m3m3(mat, dmat, rmat); } -void object_mat3_to_rot(Object *ob, float mat[][3], int use_compat) +void object_mat3_to_rot(Object *ob, float mat[][3], short use_compat) { - if (ob->rotmode == ROT_MODE_QUAT) - mat3_to_quat(ob->quat, mat); - else if (ob->rotmode == ROT_MODE_AXISANGLE) - mat3_to_axis_angle(ob->rotAxis, &ob->rotAngle, mat); - else { - if(use_compat) { - float eul[3]; - VECCOPY(eul, ob->rot); - mat3_to_compatible_eulO(ob->rot, eul, ob->rotmode, mat); + switch(ob->rotmode) { + case ROT_MODE_QUAT: + { + float dquat[4]; + mat3_to_quat(ob->quat, mat); + normalize_qt_qt(dquat, ob->dquat); + invert_qt(dquat); + mul_qt_qtqt(ob->quat, dquat, ob->quat); } - else - mat3_to_eulO(ob->rot, ob->rotmode, mat); + break; + case ROT_MODE_AXISANGLE: + mat3_to_axis_angle(ob->rotAxis, &ob->rotAngle, mat); + sub_v3_v3(ob->rotAxis, ob->drotAxis); + ob->rotAngle -= ob->drotAngle; + break; + default: /* euler */ + if(use_compat) mat3_to_compatible_eulO(ob->rot, ob->rot, ob->rotmode, mat); + else mat3_to_eulO(ob->rot, ob->rotmode, mat); + sub_v3_v3(ob->rot, ob->drot); } } /* see pchan_apply_mat4() for the equivalent 'pchan' function */ -void object_apply_mat4(Object *ob, float mat[][4]) +void object_apply_mat4(Object *ob, float mat[][4], const short use_compat, const short use_parent) { - float mat3[3][3]; - copy_v3_v3(ob->loc, mat[3]); - mat4_to_size(ob->size, mat); - copy_m3_m4(mat3, mat); - object_mat3_to_rot(ob, mat3, 0); + float rot[3][3]; + + if(use_parent && ob->parent) { + float rmat[4][4], diff_mat[4][4], imat[4][4]; + mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat); + invert_m4_m4(imat, diff_mat); + mul_m4_m4m4(rmat, mat, imat); /* get the parent relative matrix */ + object_apply_mat4(ob, rmat, use_compat, FALSE); + + /* same as below, use rmat rather then mat */ + mat4_to_loc_rot_size(ob->loc, rot, ob->size, rmat); + object_mat3_to_rot(ob, rot, use_compat); + } + else { + mat4_to_loc_rot_size(ob->loc, rot, ob->size, mat); + object_mat3_to_rot(ob, rot, use_compat); + } + + sub_v3_v3(ob->loc, ob->dloc); + sub_v3_v3(ob->size, ob->dsize); + /* object_mat3_to_rot handles delta rotations */ } void object_to_mat3(Object *ob, float mat[][3]) /* no parent */ @@ -1721,12 +1776,13 @@ void object_to_mat4(Object *ob, float mat[][4]) add_v3_v3v3(mat[3], ob->loc, ob->dloc); } +/* extern */ int enable_cu_speed= 1; static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) { Curve *cu; - float q[4], vec[4], dir[3], quat[4], radius, x1, ctime; + float vec[4], dir[3], quat[4], radius, ctime; float timeoffs = 0.0, sf_orig = 0.0; unit_m4(mat); @@ -1754,12 +1810,17 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) * we divide the curvetime calculated in the previous step by the length of the path, to get a time * factor, which then gets clamped to lie within 0.0 - 1.0 range */ - ctime= cu->ctime / cu->pathlen; + if (IS_EQ(cu->pathlen, 0.0f) == 0) + ctime= cu->ctime / cu->pathlen; + else + ctime= cu->ctime; + CLAMP(ctime, 0.0, 1.0); } else { ctime= scene->r.cfra - give_timeoffset(ob); - ctime /= cu->pathlen; + if (IS_EQ(cu->pathlen, 0.0f) == 0) + ctime /= cu->pathlen; CLAMP(ctime, 0.0, 1.0); } @@ -1774,9 +1835,11 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) /* vec: 4 items! */ - if( where_on_path(par, ctime, vec, dir, NULL, &radius, NULL) ) { + if( where_on_path(par, ctime, vec, dir, cu->flag & CU_FOLLOW ? quat:NULL, &radius, NULL) ) { if(cu->flag & CU_FOLLOW) { +#if 0 + float x1, q[4]; vec_to_quat( quat,dir, ob->trackflag, ob->upflag); /* the tilt */ @@ -1787,8 +1850,11 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) q[2]= -x1*dir[1]; q[3]= -x1*dir[2]; mul_qt_qtqt(quat, q, quat); - - quat_to_mat4( mat,quat); +#else + quat_apply_track(quat, ob->trackflag, ob->upflag); +#endif + normalize_qt(quat); + quat_to_mat4(mat, quat); } if(cu->flag & CU_PATH_RADIUS) { @@ -2044,7 +2110,7 @@ void where_is_object_time(Scene *scene, Object *ob, float ctime) } /* solve constraints */ - if (ob->constraints.first && !(ob->flag & OB_NO_CONSTRAINTS)) { + if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) { bConstraintOb *cob; cob= constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); @@ -2129,7 +2195,7 @@ static void solve_parenting (Scene *scene, Object *ob, Object *par, float obmat[ copy_m3_m4(originmat, tmat); // origin, voor help line - if( (ob->partype & 15)==PARSKEL ) { + if( (ob->partype & PARTYPE)==PARSKEL ) { VECCOPY(ob->orig, par->obmat[3]); } else { @@ -2215,7 +2281,7 @@ void what_does_parent(Scene *scene, Object *ob, Object *workob) where_is_object(scene, workob); } -BoundBox *unit_boundbox() +BoundBox *unit_boundbox(void) { BoundBox *bb; float min[3] = {-1.0f,-1.0f,-1.0f}, max[3] = {-1.0f,-1.0f,-1.0f}; @@ -2516,46 +2582,64 @@ void object_handle_update(Scene *scene, Object *ob) if (G.f & G_DEBUG) printf("recalcdata %s\n", ob->id.name+2); - /* includes all keys and modifiers */ - if(ob->type==OB_MESH) { - BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL; - + + if(adt) { /* evaluate drivers */ - // XXX: should we push this to derivedmesh instead? + // XXX: for mesh types, should we push this to derivedmesh instead? BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS); + - // here was vieweditdatamask? XXX - if(em) { - makeDerivedMesh(scene, ob, em, CD_MASK_BAREMESH); - } else - makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH); } - else if(ob->type==OB_MBALL) { - makeDispListMBall(scene, ob); - } - else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - makeDispListCurveTypes(scene, ob, 0); - } - else if(ELEM(ob->type, OB_CAMERA, OB_LAMP)) { - /* evaluate drivers */ - BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS); - } - else if(ob->type==OB_LATTICE) { - lattice_calc_modifiers(scene, ob); - } - else if(ob->type==OB_ARMATURE) { - /* evaluate drivers */ - BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS); - + + /* includes all keys and modifiers */ + switch(ob->type) { + case OB_MESH: + { +#if 0 // XXX, comment for 2.56a release, background wont set 'scene->customdata_mask' + BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL; + BLI_assert((scene->customdata_mask & CD_MASK_BAREMESH) == CD_MASK_BAREMESH); + if(em) { + makeDerivedMesh(scene, ob, em, scene->customdata_mask); /* was CD_MASK_BAREMESH */ + } else + makeDerivedMesh(scene, ob, NULL, scene->customdata_mask); + +#else /* ensure CD_MASK_BAREMESH for now */ + BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL; + if(em) { + makeDerivedMesh(scene, ob, em, scene->customdata_mask | CD_MASK_BAREMESH); /* was CD_MASK_BAREMESH */ + } else + makeDerivedMesh(scene, ob, NULL, scene->customdata_mask | CD_MASK_BAREMESH); +#endif + + } + break; + + case OB_ARMATURE: if(ob->id.lib && ob->proxy_from) { - copy_pose_result(ob->pose, ob->proxy_from->pose); // printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name); + copy_pose_result(ob->pose, ob->proxy_from->pose); } else { where_is_pose(scene, ob); } + break; + + case OB_MBALL: + makeDispListMBall(scene, ob); + break; + + case OB_CURVE: + case OB_SURF: + case OB_FONT: + makeDispListCurveTypes(scene, ob, 0); + break; + + case OB_LATTICE: + lattice_calc_modifiers(scene, ob); + break; } + if(ob->particlesystem.first) { ParticleSystem *tpsys, *psys; DerivedMesh *dm; @@ -2879,7 +2963,7 @@ void object_delete_ptcache(Object *ob, int index) /* shape key utility function */ /************************* Mesh ************************/ -static KeyBlock *insert_meshkey(Scene *scene, Object *ob, char *name, int from_mix) +static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, int from_mix) { Mesh *me= ob->data; Key *key= me->key; @@ -2910,7 +2994,7 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, char *name, int from_m return kb; } /************************* Lattice ************************/ -static KeyBlock *insert_lattkey(Scene *scene, Object *ob, char *name, int from_mix) +static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int from_mix) { Lattice *lt= ob->data; Key *key= lt->key; @@ -2942,7 +3026,7 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, char *name, int from_m return kb; } /************************* Curve ************************/ -static KeyBlock *insert_curvekey(Scene *scene, Object *ob, char *name, int from_mix) +static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int from_mix) { Curve *cu= ob->data; Key *key= cu->key; @@ -2978,7 +3062,7 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, char *name, int from_ return kb; } -KeyBlock *object_insert_shape_key(Scene *scene, Object *ob, char *name, int from_mix) +KeyBlock *object_insert_shape_key(Scene *scene, Object *ob, const char *name, int from_mix) { if(ob->type==OB_MESH) return insert_meshkey(scene, ob, name, from_mix); else if ELEM(ob->type, OB_CURVE, OB_SURF)return insert_curvekey(scene, ob, name, from_mix); diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 919a724d1ec..981b3b31e71 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -1,4 +1,4 @@ -/** +/* * blenkernel/packedFile.c - (cleaned up mar-01 nzc) * * $Id$ @@ -47,6 +47,7 @@ #include "DNA_packedFile_types.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "BKE_utildefines.h" #include "BKE_global.h" @@ -162,7 +163,7 @@ PackedFile *newPackedFileMemory(void *mem, int memlen) return pf; } -PackedFile *newPackedFile(ReportList *reports, char *filename) +PackedFile *newPackedFile(ReportList *reports, const char *filename) { PackedFile *pf = NULL; int file, filelen; @@ -179,7 +180,7 @@ PackedFile *newPackedFile(ReportList *reports, char *filename) // convert relative filenames to absolute filenames strcpy(name, filename); - BLI_path_abs(name, G.sce); + BLI_path_abs(name, G.main->name); // open the file // and create a PackedFile structure @@ -214,13 +215,20 @@ void packAll(Main *bmain, ReportList *reports) Image *ima; VFont *vf; bSound *sound; - - for(ima=bmain->image.first; ima; ima=ima->id.next) - if(ima->packedfile == NULL && ima->id.lib==NULL && ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) - ima->packedfile = newPackedFile(reports, ima->name); + + for(ima=bmain->image.first; ima; ima=ima->id.next) { + if(ima->packedfile == NULL && ima->id.lib==NULL) { + if(ima->source==IMA_SRC_FILE) { + ima->packedfile = newPackedFile(reports, ima->name); + } + else if(ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { + BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported.", ima->id.name+2); + } + } + } for(vf=bmain->vfont.first; vf; vf=vf->id.next) - if(vf->packedfile == NULL && vf->id.lib==NULL && strcmp(vf->name, "<builtin>") != 0) + if(vf->packedfile == NULL && vf->id.lib==NULL && strcmp(vf->name, FO_BUILTIN_NAME) != 0) vf->packedfile = newPackedFile(reports, vf->name); for(sound=bmain->sound.first; sound; sound=sound->id.next) @@ -256,7 +264,7 @@ static char *find_new_name(char *name) */ -int writePackedFile(ReportList *reports, char *filename, PackedFile *pf, int guimode) +int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, int guimode) { int file, number, remove_tmp = FALSE; int ret_value = RET_OK; @@ -267,7 +275,7 @@ int writePackedFile(ReportList *reports, char *filename, PackedFile *pf, int gui if (guimode) {} //XXX waitcursor(1); strcpy(name, filename); - BLI_path_abs(name, G.sce); + BLI_path_abs(name, G.main->name); if (BLI_exists(name)) { for (number = 1; number <= 999; number++) { @@ -324,7 +332,7 @@ PF_NOFILE - the original file doens't exist */ -int checkPackedFile(char *filename, PackedFile *pf) +int checkPackedFile(const char *filename, PackedFile *pf) { struct stat st; int ret_val, i, len, file; @@ -332,7 +340,7 @@ int checkPackedFile(char *filename, PackedFile *pf) char name[FILE_MAXDIR + FILE_MAXFILE]; strcpy(name, filename); - BLI_path_abs(name, G.sce); + BLI_path_abs(name, G.main->name); if (stat(name, &st)) { ret_val = PF_NOFILE; @@ -451,7 +459,7 @@ int unpackVFont(ReportList *reports, VFont *vfont, int how) if (newname != NULL) { ret_value = RET_OK; freePackedFile(vfont->packedfile); - vfont->packedfile = 0; + vfont->packedfile = NULL; strcpy(vfont->name, newname); MEM_freeN(newname); } @@ -460,7 +468,7 @@ int unpackVFont(ReportList *reports, VFont *vfont, int how) return (ret_value); } -int unpackSound(ReportList *reports, bSound *sound, int how) +int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how) { char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; char *newname; @@ -477,9 +485,9 @@ int unpackSound(ReportList *reports, bSound *sound, int how) MEM_freeN(newname); freePackedFile(sound->packedfile); - sound->packedfile = 0; + sound->packedfile = NULL; - sound_load(NULL, sound); + sound_load(bmain, sound); ret_value = RET_OK; } @@ -529,6 +537,6 @@ void unpackAll(Main *bmain, ReportList *reports, int how) for(sound=bmain->sound.first; sound; sound=sound->id.next) if(sound->packedfile) - unpackSound(reports, sound, how); + unpackSound(bmain, reports, sound, how); } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index ffb99c10c40..e53888127f2 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1,4 +1,6 @@ /* + * $Id$ + * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -23,7 +25,7 @@ * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** - */ + */ #include "DNA_object_types.h" @@ -31,6 +33,9 @@ #include "DNA_scene_types.h" #include "DNA_brush_types.h" +#include "BLI_utildefines.h" + + #include "BKE_brush.h" #include "BKE_library.h" #include "BKE_paint.h" @@ -100,7 +105,7 @@ void paint_init(Paint *p, const char col[3]) p->flags |= PAINT_SHOW_BRUSH; } -void free_paint(Paint *paint) +void free_paint(Paint *UNUSED(paint)) { /* nothing */ } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index dbc598071f9..4b3b30e6cd2 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -46,6 +46,8 @@ #include "DNA_scene_types.h" #include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" #include "BLI_kdtree.h" #include "BLI_rand.h" #include "BLI_threads.h" @@ -62,7 +64,7 @@ #include "BKE_group.h" #include "BKE_main.h" #include "BKE_lattice.h" -#include "BKE_utildefines.h" + #include "BKE_displist.h" #include "BKE_particle.h" #include "BKE_object.h" @@ -77,8 +79,6 @@ #include "RE_render_ext.h" -static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, - float *fuv, float *orco, ParticleTexture *ptex, int event); static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex); static void do_child_modifiers(ParticleSimulationData *sim, @@ -159,21 +159,21 @@ static void psys_free_path_cache_buffers(ParticleCacheKey **cache, ListBase *buf ParticleSystem *psys_get_current(Object *ob) { ParticleSystem *psys; - if(ob==0) return 0; + if(ob==NULL) return NULL; for(psys=ob->particlesystem.first; psys; psys=psys->next){ if(psys->flag & PSYS_CURRENT) return psys; } - return 0; + return NULL; } short psys_get_current_num(Object *ob) { ParticleSystem *psys; short i; - if(ob==0) return 0; + if(ob==NULL) return 0; for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) if(psys->flag & PSYS_CURRENT) @@ -186,7 +186,7 @@ void psys_set_current_num(Object *ob, int index) ParticleSystem *psys; short i; - if(ob==0) return; + if(ob==NULL) return; for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) { if(i == index) @@ -197,7 +197,7 @@ void psys_set_current_num(Object *ob, int index) } Object *psys_find_object(Scene *scene, ParticleSystem *psys) { - Base *base = scene->base.first; + Base *base; ParticleSystem *tpsys; for(base = scene->base.first; base; base = base->next) { @@ -211,7 +211,7 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys) } Object *psys_get_lattice(ParticleSimulationData *sim) { - Object *lattice=0; + Object *lattice=NULL; if(psys_in_edit_mode(sim->scene, sim->psys)==0){ @@ -225,7 +225,7 @@ Object *psys_get_lattice(ParticleSimulationData *sim) } } if(lattice) - init_latt_deform(lattice,0); + init_latt_deform(lattice, NULL); } return lattice; @@ -273,7 +273,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) } psmd= psys_get_modifier(ob, psys); - if(psys->renderdata) { + if(psys->renderdata || G.rendering) { if(!(psmd->modifier.mode & eModifierMode_Render)) return 0; } @@ -360,7 +360,7 @@ int psys_uses_gravity(ParticleSimulationData *sim) /************************************************/ /* Freeing stuff */ /************************************************/ -void fluid_free_settings(SPHFluidSettings *fluid) +static void fluid_free_settings(SPHFluidSettings *fluid) { if(fluid) MEM_freeN(fluid); @@ -368,6 +368,8 @@ void fluid_free_settings(SPHFluidSettings *fluid) void psys_free_settings(ParticleSettings *part) { + MTex *mtex; + int a; BKE_free_animdata(&part->id); free_partdeflect(part->pd); free_partdeflect(part->pd2); @@ -379,15 +381,18 @@ void psys_free_settings(ParticleSettings *part) boid_free_settings(part->boids); fluid_free_settings(part->fluid); + + for(a=0; a<MAX_MTEX; a++) { + mtex= part->mtex[a]; + if(mtex && mtex->tex) mtex->tex->id.us--; + if(mtex) MEM_freeN(mtex); + } } -void free_hair(Object *ob, ParticleSystem *psys, int dynamics) +void free_hair(Object *UNUSED(ob), ParticleSystem *psys, int dynamics) { PARTICLE_P; - if(psys->part->type != PART_HAIR) - return; - LOOP_PARTICLES { if(pa->hair) MEM_freeN(pa->hair); @@ -406,9 +411,10 @@ void free_hair(Object *ob, ParticleSystem *psys, int dynamics) modifier_free((ModifierData*)psys->clmd); psys->clmd = NULL; + psys->pointcache = BKE_ptcache_add(&psys->ptcaches); } else { - cloth_free_modifier(ob, psys->clmd); + cloth_free_modifier(psys->clmd); } } @@ -463,7 +469,7 @@ void psys_free_children(ParticleSystem *psys) { if(psys->child) { MEM_freeN(psys->child); - psys->child=0; + psys->child= NULL; psys->totchild=0; } @@ -533,7 +539,7 @@ void psys_free(Object *ob, ParticleSystem * psys) if(psys->child){ MEM_freeN(psys->child); - psys->child = 0; + psys->child = NULL; psys->totchild = 0; } @@ -554,7 +560,7 @@ void psys_free(Object *ob, ParticleSystem * psys) if(psys->part){ psys->part->id.us--; - psys->part=0; + psys->part=NULL; } BKE_ptcache_free_list(&psys->ptcaches); @@ -563,6 +569,9 @@ void psys_free(Object *ob, ParticleSystem * psys) BLI_freelistN(&psys->targets); BLI_kdtree_free(psys->tree); + + if(psys->fluid_springs) + MEM_freeN(psys->fluid_springs); pdEndEffectors(&psys->effectors); @@ -1000,6 +1009,8 @@ static float interpolate_particle_value(float v1, float v2, float v3, float v4, value= w[0]*v1 + w[1]*v2 + w[2]*v3; if(four) value += w[3]*v4; + + CLAMP(value, 0.f, 1.f); return value; } @@ -1055,9 +1066,10 @@ typedef struct ParticleInterpolationData { } ParticleInterpolationData; /* Assumes pointcache->mem_cache exists, so for disk cached particles call psys_make_temp_pointcache() before use */ /* It uses ParticleInterpolationData->pm to store the current memory cache frame so it's thread safe. */ -static void get_pointcache_keys_for_time(Object *ob, PointCache *cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2) +static void get_pointcache_keys_for_time(Object *UNUSED(ob), PointCache *cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2) { static PTCacheMem *pm = NULL; + int index1, index2; if(index < 0) { /* initialize */ *cur = cache->mem_cache.first; @@ -1072,15 +1084,19 @@ static void get_pointcache_keys_for_time(Object *ob, PointCache *cache, PTCacheM pm = *cur; - BKE_ptcache_make_particle_key(key2, pm->index_array ? pm->index_array[index] - 1 : index, pm->data, (float)pm->frame); - if(pm->prev->index_array && pm->prev->index_array[index] == 0) + index2 = BKE_ptcache_mem_index_find(pm, index); + index1 = BKE_ptcache_mem_index_find(pm->prev, index); + + BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame); + if(index1 < 0) copy_particle_key(key1, key2, 1); else - BKE_ptcache_make_particle_key(key1, pm->prev->index_array ? pm->prev->index_array[index] - 1 : index, pm->prev->data, (float)pm->prev->frame); + BKE_ptcache_make_particle_key(key1, index1, pm->prev->data, (float)pm->prev->frame); } else if(cache->mem_cache.first) { pm = cache->mem_cache.first; - BKE_ptcache_make_particle_key(key2, pm->index_array ? pm->index_array[index] - 1 : index, pm->data, (float)pm->frame); + index2 = BKE_ptcache_mem_index_find(pm, index); + BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame); copy_particle_key(key1, key2, 1); } } @@ -1091,14 +1107,7 @@ static int get_pointcache_times_for_particle(PointCache *cache, int index, float int ret = 0; for(pm=cache->mem_cache.first; pm; pm=pm->next) { - if(pm->index_array) { - if(pm->index_array[index]) { - *start = pm->frame; - ret++; - break; - } - } - else { + if(BKE_ptcache_mem_index_find(pm, index) >= 0) { *start = pm->frame; ret++; break; @@ -1106,14 +1115,7 @@ static int get_pointcache_times_for_particle(PointCache *cache, int index, float } for(pm=cache->mem_cache.last; pm; pm=pm->prev) { - if(pm->index_array) { - if(pm->index_array[index]) { - *end = pm->frame; - ret++; - break; - } - } - else { + if(BKE_ptcache_mem_index_find(pm, index) >= 0) { *end = pm->frame; ret++; break; @@ -1128,13 +1130,8 @@ float psys_get_dietime_from_cache(PointCache *cache, int index) { int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */ for(pm=cache->mem_cache.last; pm; pm=pm->prev) { - if(pm->index_array) { - if(pm->index_array[index]) - return (float)pm->frame; - } - else { + if(BKE_ptcache_mem_index_find(pm, index) >= 0) return (float)pm->frame; - } } return (float)dietime; @@ -1161,7 +1158,7 @@ static void init_particle_interpolation(Object *ob, ParticleSystem *psys, Partic pind->dietime = (key + pa->totkey - 1)->time; } else if(pind->cache) { - float start, end; + float start=0.0f, end=0.0f; get_pointcache_keys_for_time(ob, pind->cache, &pind->pm, -1, 0.0f, NULL, NULL); pind->birthtime = pa ? pa->time : pind->cache->startframe; pind->dietime = pa ? pa->dietime : pind->cache->endframe; @@ -1205,12 +1202,12 @@ static void mvert_to_particle(ParticleKey *key, MVert *mvert, HairKey *hkey) key->time = hkey->time; } -static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, float frs_sec, ParticleInterpolationData *pind, ParticleKey *result) +static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, ParticleInterpolationData *pind, ParticleKey *result) { PTCacheEditPoint *point = pind->epoint; ParticleKey keys[4]; int point_vel = (point && point->keys->vel); - float real_t, dfra, keytime; + float real_t, dfra, keytime, invdt; /* billboards wont fill in all of these, so start cleared */ memset(keys, 0, sizeof(keys)); @@ -1349,11 +1346,12 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData dfra = keys[2].time - keys[1].time; keytime = (real_t - keys[1].time) / dfra; + invdt = dfra * 0.04f * psys->part->timetweak; /* convert velocity to timestep size */ if(pind->keyed || pind->cache || point_vel){ - mul_v3_fl(keys[1].vel, dfra / frs_sec); - mul_v3_fl(keys[2].vel, dfra / frs_sec); + mul_v3_fl(keys[1].vel, invdt); + mul_v3_fl(keys[2].vel, invdt); interp_qt_qtqt(result->rot,keys[1].rot,keys[2].rot,keytime); } @@ -1364,7 +1362,7 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData /* the velocity needs to be converted back from cubic interpolation */ if(pind->keyed || pind->cache || point_vel) - mul_v3_fl(result->vel, frs_sec / dfra); + mul_v3_fl(result->vel, 1.f/invdt); } /************************************************/ /* Particles on a dm */ @@ -1480,7 +1478,7 @@ void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*or } else { VECCOPY(orco, vec); - if(ornor) + if(ornor && nor) VECCOPY(ornor, nor); } } @@ -1650,7 +1648,7 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, float * return DMCACHE_NOTFOUND; } -static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, int *mapindex, float *mapfw) +static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float UNUSED(foffset), int *mapindex, float *mapfw) { if(index < 0) return 0; @@ -1806,7 +1804,7 @@ ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys) /* Particles on a shape */ /************************************************/ /* ready for future use */ -static void psys_particle_on_shape(int distr, int index, float *fuv, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor) +static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index), float *UNUSED(fuv), float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor) { /* TODO */ float zerovec[3]={0.0f,0.0f,0.0f}; @@ -1835,9 +1833,11 @@ static void psys_particle_on_shape(int distr, int index, float *fuv, float *vec, void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor){ if(psmd){ if(psmd->psys->part->distr==PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT){ - if(vec){ - VECCOPY(vec,fuv); - } + if(vec) + copy_v3_v3(vec,fuv); + + if(orco) + copy_v3_v3(orco, fuv); return; } /* we cant use the num_dmcache */ @@ -1865,144 +1865,186 @@ static float vert_weight(MDeformVert *dvert, int group) return 0.0; } -static void do_prekink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, short type, short axis, float obmat[][4]) +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) { - float vec[3]={0.0,0.0,0.0}, q1[4]={1,0,0,0},q2[4]; - float t; + 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]; - CLAMP(time,0.0,1.0); + if(par == NULL || type == PART_KINK_NO) + return; + + CLAMP(time, 0.f, 1.f); if(shape!=0.0f && type!=PART_KINK_BRAID) { if(shape<0.0f) - time= (float)pow(time, 1.0+shape); + time= (float)pow(time, 1.f+shape); else - time= (float)pow(time, 1.0/(1.0-shape)); + time= (float)pow(time, 1.f/(1.f-shape)); } - t=time; + t = time * freq *(float)M_PI; + + if(smooth_start) { + dt = fabs(t); + /* smooth the beginning of kink */ + CLAMP(dt, 0.f, (float)M_PI); + dt = sin(dt/2.f); + } - t*=(float)M_PI*freq; + if(type != PART_KINK_RADIAL) { + float temp[3]; - if(par==0) return; + kink[axis]=1.f; - switch(type){ - case PART_KINK_CURL: - vec[axis]=1.0; - if(par_rot) - QUATCOPY(q2,par_rot) - else - vec_to_quat( q2,par->vel,axis,(axis+1)%3); - mul_qt_v3(q2,vec); - mul_v3_fl(vec,amplitude); - VECADD(state->co,state->co,vec); + if(obmat) + mul_mat3_m4_v3(obmat, kink); + + if(par_rot) + mul_qt_v3(par_rot, kink); - VECSUB(vec,state->co,par->co); + /* make sure kink is normal to strand */ + project_v3_v3v3(temp, kink, par->vel); + sub_v3_v3(kink, temp); + normalize_v3(kink); + } - if(t!=0.0) - axis_angle_to_quat(q1,par->vel,t); - - mul_qt_v3(q1,vec); - - VECADD(state->co,par->co,vec); - break; - case PART_KINK_RADIAL: - VECSUB(vec,state->co,par->co); + copy_v3_v3(result, state->co); + sub_v3_v3v3(par_vec, par->co, state->co); - normalize_v3(vec); - mul_v3_fl(vec,amplitude*(float)sin(t)); + switch(type) { + case PART_KINK_CURL: + { + mul_v3_fl(par_vec, -1.f); - VECADD(state->co,state->co,vec); - break; - case PART_KINK_WAVE: - vec[axis]=1.0; - if(obmat) - mul_mat3_m4_v3(obmat,vec); + if(flat > 0.f) { + float proj[3]; + project_v3_v3v3(proj, par_vec, par->vel); + madd_v3_v3fl(par_vec, proj, -flat); - if(par_rot) - mul_qt_v3(par_rot,vec); + project_v3_v3v3(proj, par_vec, kink); + madd_v3_v3fl(par_vec, proj, -flat); + } - project_v3_v3v3(q1,vec,par->vel); - - VECSUB(vec,vec,q1); - normalize_v3(vec); + axis_angle_to_quat(q1, kink, (float)M_PI/2.f); - mul_v3_fl(vec,amplitude*(float)sin(t)); + mul_qt_v3(q1, par_vec); - VECADD(state->co,state->co,vec); - break; - case PART_KINK_BRAID: - if(par){ - float y_vec[3]={0.0,1.0,0.0}; - float z_vec[3]={0.0,0.0,1.0}; - float vec_from_par[3], vec_one[3], radius, state_co[3]; - float inp_y,inp_z,length; - - if(par_rot) - QUATCOPY(q2,par_rot) - else - vec_to_quat(q2,par->vel,axis,(axis+1)%3); - mul_qt_v3(q2,y_vec); - mul_qt_v3(q2,z_vec); - - VECSUB(vec_from_par,state->co,par->co); - radius= normalize_v3_v3(vec_one, vec_from_par); + madd_v3_v3fl(par_vec, kink, amplitude); - inp_y=dot_v3v3(y_vec,vec_one); - inp_z=dot_v3v3(z_vec,vec_one); + /* rotate kink vector around strand tangent */ + if(t!=0.f) { + axis_angle_to_quat(q1, par->vel, t); + mul_qt_v3(q1, par_vec); + } - if(inp_y>0.5){ - VECCOPY(state_co,y_vec); + add_v3_v3v3(result, par->co, par_vec); + break; + } + case PART_KINK_RADIAL: + { + if(flat > 0.f) { + float proj[3]; + /* flatten along strand */ + project_v3_v3v3(proj, par_vec, par->vel); + madd_v3_v3fl(result, proj, flat); + } - mul_v3_fl(y_vec,amplitude*(float)cos(t)); - mul_v3_fl(z_vec,amplitude/2.0f*(float)sin(2.0f*t)); - } - else if(inp_z>0.0){ - VECCOPY(state_co,z_vec); - mul_v3_fl(state_co,(float)sin(M_PI/3.0f)); - VECADDFAC(state_co,state_co,y_vec,-0.5f); + madd_v3_v3fl(result, par_vec, -amplitude*(float)sin(t)); + break; + } + case PART_KINK_WAVE: + { + madd_v3_v3fl(result, kink, amplitude*(float)sin(t)); - mul_v3_fl(y_vec,-amplitude*(float)cos(t + M_PI/3.0f)); - mul_v3_fl(z_vec,amplitude/2.0f*(float)cos(2.0f*t + M_PI/6.0f)); - } - else{ - VECCOPY(state_co,z_vec); - mul_v3_fl(state_co,-(float)sin(M_PI/3.0f)); - VECADDFAC(state_co,state_co,y_vec,-0.5f); + if(flat > 0.f) { + float proj[3]; + /* flatten along wave */ + project_v3_v3v3(proj, par_vec, kink); + madd_v3_v3fl(result, proj, flat); - mul_v3_fl(y_vec,amplitude*(float)-sin(t+M_PI/6.0f)); - mul_v3_fl(z_vec,amplitude/2.0f*(float)-sin(2.0f*t+M_PI/3.0f)); - } + /* flatten along strand */ + project_v3_v3v3(proj, par_vec, par->vel); + madd_v3_v3fl(result, proj, flat); + } + break; + } + case PART_KINK_BRAID: + { + float y_vec[3]={0.f,1.f,0.f}; + float z_vec[3]={0.f,0.f,1.f}; + float vec_one[3], state_co[3]; + float inp_y, inp_z, length; + + if(par_rot) { + mul_qt_v3(par_rot, y_vec); + mul_qt_v3(par_rot, z_vec); + } + + mul_v3_fl(par_vec, -1.f); + normalize_v3_v3(vec_one, par_vec); - mul_v3_fl(state_co,amplitude); - VECADD(state_co,state_co,par->co); - VECSUB(vec_from_par,state->co,state_co); + inp_y=dot_v3v3(y_vec, vec_one); + inp_z=dot_v3v3(z_vec, vec_one); - length=normalize_v3(vec_from_par); - mul_v3_fl(vec_from_par,MIN2(length,amplitude/2.0f)); + if(inp_y>0.5){ + copy_v3_v3(state_co, y_vec); - VECADD(state_co,par->co,y_vec); - VECADD(state_co,state_co,z_vec); - VECADD(state_co,state_co,vec_from_par); + mul_v3_fl(y_vec, amplitude*(float)cos(t)); + mul_v3_fl(z_vec, amplitude/2.f*(float)sin(2.f*t)); + } + else if(inp_z>0.0){ + mul_v3_v3fl(state_co, z_vec, (float)sin(M_PI/3.f)); + VECADDFAC(state_co,state_co,y_vec,-0.5f); - shape=(2.0f*(float)M_PI)*(1.0f+shape); + mul_v3_fl(y_vec, -amplitude * (float)cos(t + M_PI/3.f)); + mul_v3_fl(z_vec, amplitude/2.f * (float)cos(2.f*t + M_PI/6.f)); + } + else{ + mul_v3_v3fl(state_co, z_vec, -(float)sin(M_PI/3.f)); + madd_v3_v3fl(state_co, y_vec, -0.5f); - if(t<shape){ - shape=t/shape; - shape=(float)sqrt((double)shape); - interp_v3_v3v3(state->co,state->co,state_co,shape); - } - else{ - VECCOPY(state->co,state_co); - } - } - break; + mul_v3_fl(y_vec, amplitude * (float)-sin(t + M_PI/6.f)); + mul_v3_fl(z_vec, amplitude/2.f * (float)-sin(2.f*t + M_PI/3.f)); + } + + mul_v3_fl(state_co, amplitude); + add_v3_v3(state_co, par->co); + sub_v3_v3v3(par_vec, state->co, state_co); + + length = normalize_v3(par_vec); + mul_v3_fl(par_vec, MIN2(length, amplitude/2.f)); + + add_v3_v3v3(state_co, par->co, y_vec); + add_v3_v3(state_co, z_vec); + add_v3_v3(state_co, par_vec); + + shape = 2.f*(float)M_PI * (1.f+shape); + + if(t<shape){ + shape = t/shape; + shape = (float)sqrt((double)shape); + interp_v3_v3v3(result, result, state_co, shape); + } + else{ + copy_v3_v3(result, state_co); + } + break; + } } + + /* blend the start of the kink */ + if(dt < 1.f) + interp_v3_v3v3(state->co, state->co, result, dt); + else + copy_v3_v3(state->co, result); } -static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clumpfac, float clumppow, float pa_clump) +static float do_clump(ParticleKey *state, ParticleKey *par, float time, float clumpfac, float clumppow, float pa_clump) { + float clump = 0.f; + if(par && clumpfac!=0.0){ - float clump, cpow; + float cpow; if(clumppow<0.0) cpow=1.0f+clumppow; @@ -2013,8 +2055,11 @@ static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clu clump = -clumpfac*pa_clump*(float)pow(1.0-(double)time,(double)cpow); else clump = clumpfac*pa_clump*(float)pow((double)time,(double)cpow); + interp_v3_v3v3(state->co,state->co,par->co,clump); } + + return clump; } void precalc_guides(ParticleSimulationData *sim, ListBase *effectors) { @@ -2127,7 +2172,7 @@ int do_guides(ListBase *effectors, ParticleKey *state, int index, float time) } par.co[0] = par.co[1] = par.co[2] = 0.0f; VECCOPY(key.co, vec_to_point); - do_prekink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, pd->kink, pd->kink_axis, 0); + do_kink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, 0.f, pd->kink, pd->kink_axis, 0, 0); do_clump(&key, &par, guidetime, pd->clump_fac, pd->clump_pow, 1.0f); VECCOPY(vec_to_point, key.co); @@ -2188,7 +2233,7 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float VECADDFAC(state->co,state->co,mat[0],rough[0]); VECADDFAC(state->co,state->co,mat[1],rough[1]); } -static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) +static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *UNUSED(rootco), float effector, float UNUSED(dfra), float UNUSED(cfra), float *length, float *vec) { float force[3] = {0.0f,0.0f,0.0f}; ParticleKey eff_key; @@ -2211,12 +2256,13 @@ static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheK normalize_v3(force); - VECADDFAC(ca->co, (ca-1)->co, force, *length); - - if(k < steps) { + if(k < steps) sub_v3_v3v3(vec, (ca+1)->co, ca->co); + + madd_v3_v3v3fl(ca->co, (ca-1)->co, force, *length); + + if(k < steps) *length = len_v3(vec); - } } static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *state, float max_length, float *cur_length, float length, float *dvec) { @@ -2232,20 +2278,23 @@ static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *st return k; } } -static void offset_child(ChildParticle *cpa, ParticleKey *par, ParticleKey *child, float flat, float radius) +static void offset_child(ChildParticle *cpa, ParticleKey *par, float *par_rot, ParticleKey *child, float flat, float radius) { - VECCOPY(child->co,cpa->fuv); - mul_v3_fl(child->co,radius); + copy_v3_v3(child->co, cpa->fuv); + mul_v3_fl(child->co, radius); child->co[0]*=flat; - VECCOPY(child->vel,par->vel); - - mul_qt_v3(par->rot,child->co); + copy_v3_v3(child->vel, par->vel); - QUATCOPY(child->rot,par->rot); + if(par_rot) { + mul_qt_v3(par_rot, child->co); + copy_qt_qt(child->rot, par_rot); + } + else + unit_qt(child->rot); - VECADD(child->co,child->co,par->co); + add_v3_v3(child->co, par->co); } float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup) { @@ -2375,12 +2424,9 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c if(totchild==0) return 0; /* init random number generator */ - if(ctx->sim.psys->part->flag & PART_ANIM_BRANCHING) - seed= 31415926 + ctx->sim.psys->seed + (int)cfra; - else - seed= 31415926 + ctx->sim.psys->seed; + seed= 31415926 + ctx->sim.psys->seed; - if(part->flag & PART_BRANCHING || ctx->editupdate || totchild < 10000) + if(ctx->editupdate || totchild < 10000) totthread= 1; for(i=0; i<totthread; i++) { @@ -2423,7 +2469,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c } /* note: this function must be thread safe, except for branching! */ -static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i) +static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *child_keys, int i) { ParticleThreadContext *ctx= thread->ctx; Object *ob= ctx->sim.ob; @@ -2431,44 +2477,29 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle ParticleSettings *part = psys->part; ParticleCacheKey **cache= psys->childcache; ParticleCacheKey **pcache= psys_in_edit_mode(ctx->sim.scene, psys) ? psys->edit->pathcache : psys->pathcache; - ParticleCacheKey *state, *par = NULL, *key[4]; - ParticleData *pa=NULL; + ParticleCacheKey *child, *par = NULL, *key[4]; ParticleTexture ptex; - float *cpa_fuv=0, *par_rot=0; - float co[3], orco[3], ornor[3], hairmat[4][4], t, cpa_1st[3], dvec[3]; - float branch_begin, branch_end, branch_prob, rough_rand; + float *cpa_fuv=0, *par_rot=0, rot[4]; + float orco[3], ornor[3], hairmat[4][4], t, dvec[3], off1[4][3], off2[4][3]; float length, max_length = 1.0f, cur_length = 0.0f; - float eff_length, eff_vec[3]; + float eff_length, eff_vec[3], weight[4]; int k, cpa_num; short cpa_from; if(!pcache) return; - if(part->flag & PART_BRANCHING) { - branch_begin=rng_getFloat(thread->rng_path); - branch_end=branch_begin+(1.0f-branch_begin)*rng_getFloat(thread->rng_path); - branch_prob=rng_getFloat(thread->rng_path); - rough_rand=rng_getFloat(thread->rng_path); - } - else { - branch_begin= 0.0f; - branch_end= 0.0f; - branch_prob= 0.0f; - rough_rand= 0.0f; - } - - if(i<psys->totpart){ - branch_begin=0.0f; - branch_end=1.0f; - branch_prob=0.0f; - } - if(ctx->between){ + ParticleData *pa = psys->particles + cpa->pa[0]; int w, needupdate; - float foffset; - - if(ctx->editupdate && !(part->flag & PART_BRANCHING)) { + float foffset, wsum=0.f; + float co[3]; + float p_min = part->parting_min; + float p_max = part->parting_max; + /* Virtual parents don't work nicely with parting. */ + float p_fac = part->parents > 0.f ? 0.f : part->parting_fac; + + if(ctx->editupdate) { needupdate= 0; w= 0; while(w<4 && cpa->pa[w]>=0) { @@ -2482,223 +2513,223 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle if(!needupdate) return; else - memset(keys, 0, sizeof(*keys)*(ctx->steps+1)); + memset(child_keys, 0, sizeof(*child_keys)*(ctx->steps+1)); } /* get parent paths */ - w= 0; - while(w<4 && cpa->pa[w]>=0){ - key[w] = pcache[cpa->pa[w]]; - w++; + for(w=0; w<4; w++) { + if(cpa->pa[w] >= 0) { + key[w] = pcache[cpa->pa[w]]; + weight[w] = cpa->w[w]; + } + else { + key[w] = pcache[0]; + weight[w] = 0.f; + } + } + + /* modify weights to create parting */ + if(p_fac > 0.f) { + for(w=0; w<4; w++) { + if(w && weight[w] > 0.f) { + float d; + if(part->flag & PART_CHILD_LONG_HAIR) { + /* For long hair use tip distance/root distance as parting factor instead of root to tip angle. */ + float d1 = len_v3v3(key[0]->co, key[w]->co); + float d2 = len_v3v3((key[0]+key[0]->steps-1)->co, (key[w]+key[w]->steps-1)->co); + + d = d1 > 0.f ? d2/d1 - 1.f : 10000.f; + } + else { + float v1[3], v2[3]; + sub_v3_v3v3(v1, (key[0]+key[0]->steps-1)->co, key[0]->co); + sub_v3_v3v3(v2, (key[w]+key[w]->steps-1)->co, key[w]->co); + normalize_v3(v1); + normalize_v3(v2); + + d = saacos(dot_v3v3(v1, v2)) * 180.f / M_PI; + } + + if(p_max > p_min) + d = (d - p_min)/(p_max - p_min); + else + d = (d - p_min) <= 0.f ? 0.f : 1.f; + + CLAMP(d, 0.f, 1.f); + + if(d > 0.f) + weight[w] *= (1.f - d); + } + wsum += weight[w]; + } + for(w=0; w<4; w++) + weight[w] /= wsum; + + interp_v4_v4v4(weight, cpa->w, weight, p_fac); } /* get the original coordinates (orco) for texture usage */ cpa_num = cpa->num; - foffset= cpa->foffset; + foffset = cpa->foffset; cpa_fuv = cpa->fuv; cpa_from = PART_FROM_FACE; psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0); - if(part->path_start==0.0f) { - /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ - VECCOPY(cpa_1st,co); - mul_m4_v3(ob->obmat,cpa_1st); - } + mul_m4_v3(ob->obmat, co); - pa = psys->particles + cpa->pa[0]; + for(w=0; w<4; w++) + sub_v3_v3v3(off1[w], co, key[w]->co); psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat); - - pa=0; } else{ - if(ctx->editupdate && !(part->flag & PART_BRANCHING)) { + ParticleData *pa = psys->particles + cpa->parent; + float co[3]; + if(ctx->editupdate) { if(!(psys->edit->points[cpa->parent].flag & PEP_EDIT_RECALC)) return; - memset(keys, 0, sizeof(*keys)*(ctx->steps+1)); + memset(child_keys, 0, sizeof(*child_keys)*(ctx->steps+1)); } /* get the parent path */ - key[0]=pcache[cpa->parent]; + key[0] = pcache[cpa->parent]; /* get the original coordinates (orco) for texture usage */ - pa=psys->particles+cpa->parent; - - cpa_from=part->from; - cpa_num=pa->num; - cpa_fuv=pa->fuv; + cpa_from = part->from; + cpa_num = pa->num; + cpa_fuv = pa->fuv; psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0); psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat); } - keys->steps = ctx->steps; - - /* correct child ipo timing */ -#if 0 // XXX old animation system - if((part->flag&PART_ABS_TIME)==0 && part->ipo){ - float dsta=part->end-part->sta; - calc_ipo(part->ipo, 100.0f*(ctx->cfra-(part->sta+dsta*cpa->rand[1]))/(part->lifetime*(1.0f - part->randlife*cpa->rand[0]))); - execute_ipo((ID *)part, part->ipo); - } -#endif // XXX old animation system + child_keys->steps = ctx->steps; /* get different child parameters from textures & vgroups */ get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex); if(ptex.exist < PSYS_FRAND(i + 24)) { - keys->steps = -1; + child_keys->steps = -1; return; } /* create the child path */ - for(k=0,state=keys; k<=ctx->steps; k++,state++){ + for(k=0,child=child_keys; k<=ctx->steps; k++,child++){ if(ctx->between){ int w=0; - state->co[0] = state->co[1] = state->co[2] = 0.0f; - state->vel[0] = state->vel[1] = state->vel[2] = 0.0f; - state->rot[0] = state->rot[1] = state->rot[2] = state->rot[3] = 0.0f; + zero_v3(child->co); + zero_v3(child->vel); + unit_qt(child->rot); - //QUATCOPY(state->rot,key[0]->rot); + for(w=0; w<4; w++) { + copy_v3_v3(off2[w], off1[w]); - /* child position is the weighted sum of parent positions */ - while(w<4 && cpa->pa[w]>=0){ - state->co[0] += cpa->w[w] * key[w]->co[0]; - state->co[1] += cpa->w[w] * key[w]->co[1]; - state->co[2] += cpa->w[w] * key[w]->co[2]; - - state->vel[0] += cpa->w[w] * key[w]->vel[0]; - state->vel[1] += cpa->w[w] * key[w]->vel[1]; - state->vel[2] += cpa->w[w] * key[w]->vel[2]; - key[w]++; - w++; - } - if(part->path_start==0.0f) { - if(k==0){ - /* calculate the offset between actual child root position and first position interpolated from parents */ - VECSUB(cpa_1st,cpa_1st,state->co); + if(part->flag & PART_CHILD_LONG_HAIR) { + /* Use parent rotation (in addition to emission location) to determine child offset. */ + if(k) + mul_qt_v3((key[w]+k)->rot, off2[w]); + + /* Fade the effect of rotation for even lengths in the end */ + project_v3_v3v3(dvec, off2[w], (key[w]+k)->vel); + madd_v3_v3fl(off2[w], dvec, -(float)k/(float)ctx->steps); } - /* apply offset for correct positioning */ - VECADD(state->co,state->co,cpa_1st); + + add_v3_v3(off2[w], (key[w]+k)->co); } + + /* child position is the weighted sum of parent positions */ + interp_v3_v3v3v3v3(child->co, off2[0], off2[1], off2[2], off2[3], weight); + interp_v3_v3v3v3v3(child->vel, (key[0]+k)->vel, (key[1]+k)->vel, (key[2]+k)->vel, (key[3]+k)->vel, weight); + + copy_qt_qt(child->rot, (key[0]+k)->rot); } else{ + if(k) { + mul_qt_qtqt(rot, (key[0]+k)->rot, key[0]->rot); + par_rot = rot; + } + else { + par_rot = key[0]->rot; + } /* offset the child from the parent position */ - offset_child(cpa, (ParticleKey*)key[0], (ParticleKey*)state, part->childflat, part->childrad); - - key[0]++; + offset_child(cpa, (ParticleKey*)(key[0]+k), par_rot, (ParticleKey*)child, part->childflat, part->childrad); } } /* apply effectors */ if(part->flag & PART_CHILD_EFFECT) { - for(k=0,state=keys; k<=ctx->steps; k++,state++) { + for(k=0,child=child_keys; k<=ctx->steps; k++,child++) { if(k) { - do_path_effectors(&ctx->sim, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec); + do_path_effectors(&ctx->sim, cpa->pa[0], child, k, ctx->steps, child_keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec); } else { - sub_v3_v3v3(eff_vec,(state+1)->co,state->co); - eff_length= len_v3(eff_vec); + sub_v3_v3v3(eff_vec, (child+1)->co, child->co); + eff_length = len_v3(eff_vec); } } } - for(k=0,state=keys; k<=ctx->steps; k++,state++){ - t=(float)k/(float)ctx->steps; + for(k=0,child=child_keys; k<=ctx->steps; k++,child++){ + t = (float)k/(float)ctx->steps; + + if(ctx->totparent) + /* this is now threadsafe, virtual parents are calculated before rest of children */ + par = (i >= ctx->totparent) ? cache[cpa->parent] : NULL; + else if(cpa->parent >= 0) + par = pcache[cpa->parent]; - if(ctx->totparent){ - if(i>=ctx->totparent) { - /* this is now threadsafe, virtual parents are calculated before rest of children */ - par = cache[cpa->parent] + k; + if(par) { + if(k) { + mul_qt_qtqt(rot, (par+k)->rot, par->rot); + par_rot = rot; } - else - par=0; - } - else if(cpa->parent>=0){ - par=pcache[cpa->parent]+k; - par_rot = par->rot; + else { + par_rot = par->rot; + } + par += k; } /* apply different deformations to the child path */ - do_child_modifiers(&ctx->sim, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t); - - /* TODO: better branching */ - //if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING) - // rough_t = t * rough_rand; - //else - // rough_t = t; - - /* TODO: better branching */ - //if(part->flag & PART_BRANCHING && ctx->between==0){ - // if(branch_prob > part->branch_thres){ - // branchfac=0.0f; - // } - // else{ - // if(part->flag & PART_SYMM_BRANCHING){ - // if(t < branch_begin || t > branch_end) - // branchfac=0.0f; - // else{ - // if((t-branch_begin)/(branch_end-branch_begin)<0.5) - // branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin); - // else - // branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin); - - // CLAMP(branchfac,0.0f,1.0f); - // } - // } - // else{ - // if(t < branch_begin){ - // branchfac=0.0f; - // } - // else{ - // branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f); - // CLAMP(branchfac,0.0f,1.0f); - // } - // } - // } - - // if(i<psys->totpart) - // interp_v3_v3v3(state->co, (pcache[i] + k)->co, state->co, branchfac); - // else - // /* this is not threadsafe, but should only happen for - // * branching particles particles, which are not threaded */ - // interp_v3_v3v3(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac); - //} + do_child_modifiers(&ctx->sim, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)child, t); /* we have to correct velocity because of kink & clump */ if(k>1){ - VECSUB((state-1)->vel,state->co,(state-2)->co); - mul_v3_fl((state-1)->vel,0.5); + sub_v3_v3v3((child-1)->vel, child->co, (child-2)->co); + mul_v3_fl((child-1)->vel, 0.5); if(ctx->ma && (part->draw & PART_DRAW_MAT_COL)) - get_strand_normal(ctx->ma, ornor, cur_length, (state-1)->vel); + get_strand_normal(ctx->ma, ornor, cur_length, (child-1)->vel); } if(k == ctx->steps) - VECSUB(state->vel,state->co,(state-1)->co); + sub_v3_v3v3(child->vel, child->co, (child-1)->co); /* check if path needs to be cut before actual end of data points */ if(k){ - VECSUB(dvec,state->co,(state-1)->co); - length=1.0f/(float)ctx->steps; - k=check_path_length(k,keys,state,max_length,&cur_length,length,dvec); + sub_v3_v3v3(dvec, child->co, (child-1)->co); + length = 1.0f/(float)ctx->steps; + k = check_path_length(k, child_keys, child, max_length, &cur_length, length, dvec); } else{ /* initialize length calculation */ - max_length= ptex.length; - cur_length= 0.0f; + max_length = ptex.length; + cur_length = 0.0f; } if(ctx->ma && (part->draw & PART_DRAW_MAT_COL)) { - VECCOPY(state->col, &ctx->ma->r) - get_strand_normal(ctx->ma, ornor, cur_length, state->vel); + VECCOPY(child->col, &ctx->ma->r) + get_strand_normal(ctx->ma, ornor, cur_length, child->vel); } } + + /* Hide virtual parents */ + if(i < ctx->totparent) + child_keys->steps = -1; } static void *exec_child_path_cache(void *data) @@ -2724,10 +2755,8 @@ static void *exec_child_path_cache(void *data) void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupdate) { - ParticleSettings *part = sim->psys->part; ParticleThread *pthreads; ParticleThreadContext *ctx; - ParticleCacheKey **cache; ListBase threads; int i, totchild, totparent, totthread; @@ -2745,8 +2774,8 @@ void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupd totchild= ctx->totchild; totparent= ctx->totparent; - if(editupdate && sim->psys->childcache && !(part->flag & PART_BRANCHING) && totchild == sim->psys->totchildcache) { - cache = sim->psys->childcache; + if(editupdate && sim->psys->childcache && totchild == sim->psys->totchildcache) { + ; /* just overwrite the existing cache */ } else { /* clear out old and create new empty path cache */ @@ -2786,6 +2815,43 @@ void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupd psys_threads_free(pthreads); } +/* figure out incremental rotations along path starting from unit quat */ +static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCacheKey *key1, ParticleCacheKey *key2, float *prev_tangent, int i) +{ + float cosangle, angle, tangent[3], normal[3], q[4]; + + switch(i) { + case 0: + /* start from second key */ + break; + case 1: + /* calculate initial tangent for incremental rotations */ + sub_v3_v3v3(prev_tangent, key0->co, key1->co); + normalize_v3(prev_tangent); + unit_qt(key1->rot); + break; + default: + sub_v3_v3v3(tangent, key0->co, key1->co); + normalize_v3(tangent); + + cosangle= dot_v3v3(tangent, prev_tangent); + + /* note we do the comparison on cosangle instead of + * angle, since floating point accuracy makes it give + * different results across platforms */ + if(cosangle > 0.999999f) { + QUATCOPY(key1->rot, key2->rot); + } + else { + angle= saacos(cosangle); + cross_v3_v3v3(normal, prev_tangent, tangent); + axis_angle_to_quat( q,normal, angle); + mul_qt_qtqt(key1->rot, q, key2->rot); + } + + copy_v3_v3(prev_tangent, tangent); + } +} /* Calculates paths ready for drawing/rendering. */ /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Makes child strands possible and creates them too into the cache. */ @@ -2796,21 +2862,22 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) ParticleEditSettings *pset = &sim->scene->toolsettings->particle; ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; - ParticleCacheKey *ca, **cache= psys->pathcache; + ParticleCacheKey *ca, **cache; - DerivedMesh *hair_dm = psys->hair_out_dm; + DerivedMesh *hair_dm = (psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) ? psys->hair_out_dm : NULL; ParticleKey result; Material *ma; ParticleInterpolationData pind; + ParticleTexture ptex; PARTICLE_P; float birthtime = 0.0, dietime = 0.0; - float t, time = 0.0, dfra = 1.0, frs_sec = sim->scene->r.frs_sec; + float t, time = 0.0, dfra = 1.0 /* , frs_sec = sim->scene->r.frs_sec*/ /*UNUSED*/; float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}; - float prev_tangent[3], hairmat[4][4]; + float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4]; float rotmat[3][3]; int k; int steps = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step)); @@ -2831,7 +2898,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) BLI_srandom(psys->seed); keyed = psys->flag & PSYS_KEYED; - baked = !hair_dm && psys->pointcache->mem_cache.first; + baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR; /* clear out old and create new empty path cache */ psys_free_path_cache(psys, psys->edit); @@ -2853,8 +2920,8 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) /*---first main loop: create all actual particles' paths---*/ LOOP_SHOWN_PARTICLES { if(!psys->totchild) { - BLI_srandom(psys->seed + p); - pa_length = 1.0f - part->randlength * BLI_frand(); + psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f); + pa_length = ptex.length * (1.0f - part->randlength * PSYS_FRAND(psys->seed + p)); if(vg_length) pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length); } @@ -2898,22 +2965,19 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) /*--interpolate actual path from data points--*/ for(k=0, ca=cache[p]; k<=steps; k++, ca++){ time = (float)k / (float)steps; - t = birthtime + time * (dietime - birthtime); - result.time = -t; - - do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, &result); + do_particle_interpolation(psys, p, pa, t, &pind, &result); + copy_v3_v3(ca->co, result.co); /* dynamic hair is in object space */ /* keyed and baked are already in global space */ if(hair_dm) - mul_m4_v3(sim->ob->obmat, result.co); + mul_m4_v3(sim->ob->obmat, ca->co); else if(!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR)) - mul_m4_v3(hairmat, result.co); + mul_m4_v3(hairmat, ca->co); - VECCOPY(ca->co, result.co); - VECCOPY(ca->col, col); + copy_v3_v3(ca->col, col); } /*--modify paths and calculate rotation & velocity--*/ @@ -2948,54 +3012,25 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) /* finally do rotation & velocity */ for(k=1, ca=cache[p]+1; k<=steps; k++, ca++) { - /* figure out rotation */ - float cosangle, angle, tangent[3], normal[3], q[4]; - - if(k == 1) { - /* calculate initial tangent for incremental rotations */ - VECSUB(tangent, ca->co, (ca - 1)->co); - normalize_v3_v3(prev_tangent, tangent); - - /* First rotation is based on emitting face orientation. */ - /* This is way better than having flipping rotations resulting */ - /* from using a global axis as a rotation pole (vec_to_quat()). */ - /* It's not an ideal solution though since it disregards the */ - /* initial tangent, but taking that in to account will allow */ - /* the possibility of flipping again. -jahka */ - mat3_to_quat_is_ok( (ca-1)->rot,rotmat); - } - else { - VECSUB(tangent, ca->co, (ca - 1)->co); - normalize_v3(tangent); - - cosangle= dot_v3v3(tangent, prev_tangent); - - /* note we do the comparison on cosangle instead of - * angle, since floating point accuracy makes it give - * different results across platforms */ - if(cosangle > 0.999999f) { - QUATCOPY((ca - 1)->rot, (ca - 2)->rot); - } - else { - angle= saacos(cosangle); - cross_v3_v3v3(normal, prev_tangent, tangent); - axis_angle_to_quat( q,normal, angle); - mul_qt_qtqt((ca - 1)->rot, q, (ca - 2)->rot); - } - - VECCOPY(prev_tangent, tangent); - } + cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k); if(k == steps) - QUATCOPY(ca->rot, (ca - 1)->rot); - + copy_qt_qt(ca->rot, (ca - 1)->rot); /* set velocity */ - VECSUB(ca->vel, ca->co, (ca-1)->co); + sub_v3_v3v3(ca->vel, ca->co, (ca-1)->co); if(k==1) - VECCOPY((ca-1)->vel, ca->vel); + copy_v3_v3((ca-1)->vel, ca->vel); } + /* First rotation is based on emitting face orientation. + * This is way better than having flipping rotations resulting + * from using a global axis as a rotation pole (vec_to_quat()). + * It's not an ideal solution though since it disregards the + * initial tangent, but taking that in to account will allow + * the possibility of flipping again. -jahka + */ + mat3_to_quat_is_ok(cache[p]->rot, rotmat); } psys->totcached = totpart; @@ -3028,7 +3063,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf float birthtime = 0.0, dietime = 0.0; float t, time = 0.0, keytime = 0.0, frs_sec; - float hairmat[4][4], rotmat[3][3], prev_tangent[3]; + float hairmat[4][4], rotmat[3][3], prev_tangent[3] = {0.0f, 0.0f, 0.0f}; int k, i; int steps = (int)pow(2.0, (double)pset->draw_step); int totpart = edit->totpoint, recalc_set=0; @@ -3050,12 +3085,8 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf frs_sec = (psys || edit->pid.flag & PTCACHE_VEL_PER_SEC) ? 25.0f : 1.0f; - if(pset->brushtype == PE_BRUSH_WEIGHT){ - /* use weight painting colors now... */ -#if 0 - sel_col[0] = sel_col[1] = sel_col[2] = 1.0f; - nosel_col[0] = nosel_col[1] = nosel_col[2] = 0.0f; -#endif + if(pset->brushtype == PE_BRUSH_WEIGHT) { + ;/* use weight painting colors now... */ } else{ sel_col[0] = (float)edit->sel_col[0] / 255.0f; @@ -3083,6 +3114,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf /* should init_particle_interpolation set this ? */ if(pset->brushtype==PE_BRUSH_WEIGHT){ pind.hkey[0] = NULL; + /* pa != NULL since the weight brush is only available for hair */ pind.hkey[1] = pa->hair; } @@ -3096,9 +3128,9 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf if(psys) { psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); - VECCOPY(rotmat[0], hairmat[2]); - VECCOPY(rotmat[1], hairmat[1]); - VECCOPY(rotmat[2], hairmat[0]); + copy_v3_v3(rotmat[0], hairmat[2]); + copy_v3_v3(rotmat[1], hairmat[1]); + copy_v3_v3(rotmat[2], hairmat[0]); } birthtime = pind.birthtime; @@ -3112,66 +3144,32 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf /*--interpolate actual path from data points--*/ for(k=0, ca=cache[i]; k<=steps; k++, ca++){ time = (float)k / (float)steps; - t = birthtime + time * (dietime - birthtime); - result.time = -t; - - do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result); + do_particle_interpolation(psys, i, pa, t, &pind, &result); + copy_v3_v3(ca->co, result.co); /* non-hair points are already in global space */ if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) { - mul_m4_v3(hairmat, result.co); + mul_m4_v3(hairmat, ca->co); - /* create rotations for proper creation of children */ if(k) { - float cosangle, angle, tangent[3], normal[3], q[4]; - - if(k == 1) { - /* calculate initial tangent for incremental rotations */ - VECSUB(tangent, ca->co, (ca - 1)->co); - normalize_v3_v3(prev_tangent, tangent); - - /* First rotation is based on emitting face orientation. */ - /* This is way better than having flipping rotations resulting */ - /* from using a global axis as a rotation pole (vec_to_quat()). */ - /* It's not an ideal solution though since it disregards the */ - /* initial tangent, but taking that in to account will allow */ - /* the possibility of flipping again. -jahka */ - mat3_to_quat_is_ok( (ca-1)->rot,rotmat); - } - else { - VECSUB(tangent, ca->co, (ca - 1)->co); - normalize_v3(tangent); - - cosangle= dot_v3v3(tangent, prev_tangent); - - /* note we do the comparison on cosangle instead of - * angle, since floating point accuracy makes it give - * different results across platforms */ - if(cosangle > 0.999999f) { - QUATCOPY((ca - 1)->rot, (ca - 2)->rot); - } - else { - angle= saacos(cosangle); - cross_v3_v3v3(normal, prev_tangent, tangent); - axis_angle_to_quat( q,normal, angle); - mul_qt_qtqt((ca - 1)->rot, q, (ca - 2)->rot); - } - - VECCOPY(prev_tangent, tangent); - } + cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k); if(k == steps) - QUATCOPY(ca->rot, (ca - 1)->rot); - } - - } + copy_qt_qt(ca->rot, (ca - 1)->rot); - VECCOPY(ca->co, result.co); + /* set velocity */ + sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co); - ca->vel[0] = ca->vel[1] = 0.0f; - ca->vel[1] = 1.0f; + if(k==1) + copy_v3_v3((ca - 1)->vel, ca->vel); + } + } + else { + ca->vel[0] = ca->vel[1] = 0.0f; + ca->vel[1] = 1.0f; + } /* selection coloring in edit mode */ if(pset->brushtype==PE_BRUSH_WEIGHT){ @@ -3219,12 +3217,27 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf ca->time = t; } + if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) { + /* First rotation is based on emitting face orientation. + * This is way better than having flipping rotations resulting + * from using a global axis as a rotation pole (vec_to_quat()). + * It's not an ideal solution though since it disregards the + * initial tangent, but taking that in to account will allow + * the possibility of flipping again. -jahka + */ + mat3_to_quat_is_ok(cache[i]->rot, rotmat); + } } edit->totcached = totpart; if(psys) { - ParticleSimulationData sim = {scene, ob, psys, psys_get_modifier(ob, psys), NULL}; + ParticleSimulationData sim= {0}; + sim.scene= scene; + sim.ob= ob; + sim.psys= psys; + sim.psmd= psys_get_modifier(ob, psys); + psys_cache_child_paths(&sim, cfra, 1); } @@ -3342,7 +3355,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 *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]) { float vec[3]; @@ -3384,7 +3397,7 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa /************************************************/ /* ParticleSettings handling */ /************************************************/ -ModifierData *object_add_particle_system(Scene *scene, Object *ob, char *name) +ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *name) { ParticleSystem *psys; ModifierData *md; @@ -3423,7 +3436,7 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, char *name) psys->cfra=bsystem_time(scene,ob,scene->r.cfra+1,0.0); DAG_scene_sort(G.main, scene); - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); return md; } @@ -3460,7 +3473,7 @@ void object_remove_particle_system(Scene *scene, Object *ob) ob->mode &= ~OB_MODE_PARTICLE_EDIT; DAG_scene_sort(G.main, scene); - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } static void default_particle_settings(ParticleSettings *part) { @@ -3471,7 +3484,7 @@ static void default_particle_settings(ParticleSettings *part) part->bb_uv_split=1; part->bb_align=PART_BB_VIEW; part->bb_split_offset=PART_BB_OFF_LINEAR; - part->flag=PART_REACT_MULTIPLE|PART_HAIR_GEOMETRY|PART_EDISTR|PART_TRAND; + part->flag=PART_EDISTR|PART_TRAND|PART_HIDE_ADVANCED_HAIR; part->sta= 1.0; part->end= 200.0; @@ -3490,14 +3503,13 @@ static void default_particle_settings(ParticleSettings *part) part->adapt_angle= 5; part->adapt_pix= 3; part->kink_axis= 2; + part->kink_amp_clump= 1.f; part->reactevent= PART_EVENT_DEATH; part->disp=100; part->from= PART_FROM_FACE; part->normfac= 1.0f; - part->reactshape=1.0f; - part->mass=1.0; part->size=0.05; part->childsize=1.0; @@ -3541,7 +3553,7 @@ static void default_particle_settings(ParticleSettings *part) } -ParticleSettings *psys_new_settings(char *name, Main *main) +ParticleSettings *psys_new_settings(const char *name, Main *main) { ParticleSettings *part; @@ -3558,13 +3570,23 @@ ParticleSettings *psys_new_settings(char *name, Main *main) ParticleSettings *psys_copy_settings(ParticleSettings *part) { ParticleSettings *partn; - + int a; + partn= copy_libblock(part); - if(partn->pd) partn->pd= MEM_dupallocN(part->pd); - if(partn->pd2) partn->pd2= MEM_dupallocN(part->pd2); - partn->effector_weights = MEM_dupallocN(part->effector_weights); + partn->pd= MEM_dupallocN(part->pd); + partn->pd2= MEM_dupallocN(part->pd2); + partn->effector_weights= MEM_dupallocN(part->effector_weights); + partn->fluid= MEM_dupallocN(part->fluid); partn->boids = boid_copy_settings(part->boids); + + for(a=0; a<MAX_MTEX; a++) { + if(part->mtex[a]) { + partn->mtex[a]= MEM_mallocN(sizeof(MTex), "psys_copy_tex"); + memcpy(partn->mtex[a], part->mtex[a], sizeof(MTex)); + id_us_plus((ID *)partn->mtex[a]->tex); + } + } return partn; } @@ -3671,82 +3693,128 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, fl return 1; } -static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float *fw, float *orco, ParticleTexture *ptex, int event) +#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) if((event & mtex->mapto) & type) {pvalue = texture_value_blend(def, pvalue, value, texfac, blend);} +#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) if(event & type) { if(pvalue < 0.f) pvalue = 1.f+pvalue; CLAMP(pvalue, 0.0, 1.0); } +#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) if(event & type) { CLAMP(pvalue, -1.0, 1.0); } + +static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, float *fw, float *orco, ParticleTexture *ptex, int event, float cfra) { - MTex *mtex; - int m,setvars=0; - float value, rgba[4], texco[3]; + MTex *mtex, **mtexp = part->mtex; + int m; + float value, rgba[4], texvec[3]; - if(ma) for(m=0; m<MAX_MTEX; m++){ - mtex=ma->mtex[m]; - if(mtex && (ma->septex & (1<<m))==0 && mtex->pmapto){ + ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = + ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = + ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f; + + ptex->length= 1.0f - part->randlength * PSYS_FRAND(child_index + 26); + ptex->length*= part->clength_thres < PSYS_FRAND(child_index + 27) ? part->clength : 1.0f; + + for(m=0; m<MAX_MTEX; m++, mtexp++){ + mtex = *mtexp; + if(mtex && mtex->mapto){ float def=mtex->def_var; short blend=mtex->blendtype; + short texco = mtex->texco; - if((mtex->texco & TEXCO_UV) && fw) { - if(!get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texco)) - VECCOPY(texco,orco); - } - else - VECCOPY(texco,orco); + if(ELEM(texco, TEXCO_UV, TEXCO_ORCO) && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID)) + texco = TEXCO_GLOB; - externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3); - if((event & mtex->pmapto) & MAP_PA_TIME){ - if((setvars&MAP_PA_TIME)==0){ - ptex->time=0.0; - setvars|=MAP_PA_TIME; - } - ptex->time= texture_value_blend(mtex->def_var,ptex->time,value,mtex->timefac,blend); + switch(texco) { + case TEXCO_GLOB: + copy_v3_v3(texvec, par->state.co); + break; + case TEXCO_OBJECT: + copy_v3_v3(texvec, par->state.co); + if(mtex->object) + mul_m4_v3(mtex->object->imat, texvec); + break; + case TEXCO_UV: + if(fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texvec)) + break; + /* no break, failed to get uv's, so let's try orco's */ + case TEXCO_ORCO: + copy_v3_v3(texvec, orco); + break; + case TEXCO_PARTICLE: + /* texture coordinates in range [-1,1] */ + texvec[0] = 2.f * (cfra - par->time)/(par->dietime-par->time) - 1.f; + texvec[1] = 0.f; + texvec[2] = 0.f; + break; } - if((event & mtex->pmapto) & MAP_PA_LENGTH) - ptex->length= texture_value_blend(def,ptex->length,value,mtex->lengthfac,blend); - if((event & mtex->pmapto) & MAP_PA_CLUMP) - ptex->clump= texture_value_blend(def,ptex->clump,value,mtex->clumpfac,blend); - if((event & mtex->pmapto) & MAP_PA_KINK) - ptex->kink= texture_value_blend(def,ptex->kink,value,mtex->kinkfac,blend); - if((event & mtex->pmapto) & MAP_PA_ROUGH) + + externtex(mtex, texvec, &value, rgba, rgba+1, rgba+2, rgba+3, 0); + + if((event & mtex->mapto) & PAMAP_ROUGH) ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,mtex->roughfac,blend); - if((event & mtex->pmapto) & MAP_PA_DENS) - ptex->exist= texture_value_blend(def,ptex->exist,value,mtex->padensfac,blend); + + SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac); + SET_PARTICLE_TEXTURE(PAMAP_CLUMP, ptex->clump, mtex->clumpfac); + SET_PARTICLE_TEXTURE(PAMAP_KINK, ptex->kink, mtex->kinkfac); + SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac); } } - if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); } - if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); } - if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); } - if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); } - if(event & MAP_PA_ROUGH) { - CLAMP(ptex->rough1,0.0,1.0); - CLAMP(ptex->rough2,0.0,1.0); - CLAMP(ptex->roughe,0.0,1.0); - } - if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } + + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length); + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_CLUMP, ptex->clump); + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_KINK, ptex->kink); + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_ROUGH, ptex->rough1); + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist); } -void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *pa, ParticleTexture *ptex, int event) +void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTexture *ptex, int event, float cfra) { + ParticleSettings *part = sim->psys->part; + MTex **mtexp = part->mtex; MTex *mtex; int m; - float value, rgba[4], co[3], texco[3]; + float value, rgba[4], co[3], texvec[3]; int setvars=0; - if(ma) for(m=0; m<MAX_MTEX; m++){ - mtex=ma->mtex[m]; - if(mtex && (ma->septex & (1<<m))==0 && mtex->pmapto){ + /* initialize ptex */ + ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = + ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink = + ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f; + + ptex->time = (float)(pa - sim->psys->particles)/(float)sim->psys->totpart; + + for(m=0; m<MAX_MTEX; m++, mtexp++){ + mtex = *mtexp; + if(mtex && mtex->mapto){ float def=mtex->def_var; short blend=mtex->blendtype; + short texco = mtex->texco; - if((mtex->texco & TEXCO_UV) && ELEM(sim->psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { - if(!get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) { - /* failed to get uv's, let's try orco's */ - psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); - } - } - else { - psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); + if(texco == TEXCO_UV && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID)) + texco = TEXCO_GLOB; + + switch(texco) { + case TEXCO_GLOB: + copy_v3_v3(texvec, pa->state.co); + break; + case TEXCO_OBJECT: + copy_v3_v3(texvec, pa->state.co); + if(mtex->object) + mul_m4_v3(mtex->object->imat, texvec); + break; + case TEXCO_UV: + if(get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texvec)) + break; + /* no break, failed to get uv's, so let's try orco's */ + case TEXCO_ORCO: + psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texvec, 0); + break; + case TEXCO_PARTICLE: + /* texture coordinates in range [-1,1] */ + texvec[0] = 2.f * (cfra - pa->time)/(pa->dietime-pa->time) - 1.f; + texvec[1] = 0.f; + texvec[2] = 0.f; + break; } - externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3); + externtex(mtex, texvec, &value, rgba, rgba+1, rgba+2, rgba+3, 0); - if((event & mtex->pmapto) & MAP_PA_TIME){ + if((event & mtex->mapto) & PAMAP_TIME) { /* the first time has to set the base value for time regardless of blend mode */ if((setvars&MAP_PA_TIME)==0){ int flip= (mtex->timefac < 0.0f); @@ -3758,32 +3826,26 @@ void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *p else ptex->time= texture_value_blend(def,ptex->time,value,mtex->timefac,blend); } - if((event & mtex->pmapto) & MAP_PA_LIFE) - ptex->life= texture_value_blend(def,ptex->life,value,mtex->lifefac,blend); - if((event & mtex->pmapto) & MAP_PA_DENS) - ptex->exist= texture_value_blend(def,ptex->exist,value,mtex->padensfac,blend); - if((event & mtex->pmapto) & MAP_PA_SIZE) - ptex->size= texture_value_blend(def,ptex->size,value,mtex->sizefac,blend); - if((event & mtex->pmapto) & MAP_PA_IVEL) - ptex->ivel= texture_value_blend(def,ptex->ivel,value,mtex->ivelfac,blend); - if((event & mtex->pmapto) & MAP_PA_PVEL) - texture_rgb_blend(ptex->pvel,rgba,ptex->pvel,value,mtex->pvelfac,blend); - if((event & mtex->pmapto) & MAP_PA_LENGTH) - ptex->length= texture_value_blend(def,ptex->length,value,mtex->lengthfac,blend); - if((event & mtex->pmapto) & MAP_PA_CLUMP) - ptex->clump= texture_value_blend(def,ptex->clump,value,mtex->clumpfac,blend); - if((event & mtex->pmapto) & MAP_PA_KINK) - ptex->kink= texture_value_blend(def,ptex->kink,value,mtex->kinkfac,blend); - } - } - if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); } - if(event & MAP_PA_LIFE) { CLAMP(ptex->life,0.0,1.0); } - if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } - if(event & MAP_PA_SIZE) { CLAMP(ptex->size,0.0,1.0); } - if(event & MAP_PA_IVEL) { CLAMP(ptex->ivel,0.0,1.0); } - if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); } - if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); } - if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); } + SET_PARTICLE_TEXTURE(PAMAP_LIFE, ptex->life, mtex->lifefac) + SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac) + SET_PARTICLE_TEXTURE(PAMAP_SIZE, ptex->size, mtex->sizefac) + SET_PARTICLE_TEXTURE(PAMAP_IVEL, ptex->ivel, mtex->ivelfac) + SET_PARTICLE_TEXTURE(PAMAP_FIELD, ptex->field, mtex->fieldfac) + SET_PARTICLE_TEXTURE(PAMAP_GRAVITY, ptex->gravity, mtex->gravityfac) + SET_PARTICLE_TEXTURE(PAMAP_DAMP, ptex->damp, mtex->dampfac) + SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac) + } + } + + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_TIME, ptex->time) + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LIFE, ptex->life) + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist) + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_SIZE, ptex->size) + CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_IVEL, ptex->ivel) + CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_FIELD, ptex->field) + CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_GRAVITY, ptex->gravity) + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DAMP, ptex->damp) + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length) } /************************************************/ /* Particle State */ @@ -3821,33 +3883,13 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, return (cfra-time)/life; } -float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *pa_time) +float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float UNUSED(cfra), float *UNUSED(pa_time)) { ParticleSettings *part = psys->part; float size; // time XXX - if(part->childtype==PART_CHILD_FACES){ + if(part->childtype==PART_CHILD_FACES) size=part->size; - -#if 0 // XXX old animation system - if((part->flag&PART_ABS_TIME)==0 && part->ipo){ - IpoCurve *icu; - - if(pa_time) - time=*pa_time; - else - time=psys_get_child_time(psys,cpa,cfra,NULL,NULL); - - /* correction for lifetime */ - calc_ipo(part->ipo, 100*time); - - for(icu = part->ipo->curve.first; icu; icu=icu->next) { - if(icu->adrcode == PART_SIZE) - size = icu->curval; - } - } -#endif // XXX old animation system - } else size=psys->particles[cpa->parent].size; @@ -3863,19 +3905,7 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread ParticleSystem *psys = ctx->sim.psys; int i = cpa - psys->child; - ptex->length= 1.0f - part->randlength * PSYS_FRAND(i + 26); - ptex->clump=1.0; - ptex->kink=1.0; - ptex->rough1= 1.0; - ptex->rough2= 1.0; - ptex->roughe= 1.0; - ptex->exist= 1.0; - ptex->effector= 1.0; - - ptex->length*= part->clength_thres < PSYS_FRAND(i + 27) ? part->clength : 1.0f; - - get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex, - MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); + get_cpa_texture(ctx->dm, psys, part, psys->particles + cpa->pa[0], i, cpa_num, cpa_fuv, orco, ptex, PAMAP_DENS|PAMAP_CHILD, psys->cfra); if(ptex->exist < PSYS_FRAND(i + 24)) @@ -3902,26 +3932,42 @@ static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *pte int i = cpa - sim->psys->child; int guided = 0; + float kink_freq = part->kink_freq; + float rough1 = part->rough1; + float rough2 = part->rough2; + float rough_end = part->rough_end; + + if(ptex) { + kink_freq *= ptex->kink; + rough1 *= ptex->rough1; + rough2 *= ptex->rough2; + rough_end *= ptex->roughe; + } + if(part->flag & PART_CHILD_EFFECT) /* state is safe to cast, since only co and vel are used */ guided = do_guides(sim->psys->effectors, (ParticleKey*)state, cpa->parent, t); if(guided==0){ - if(part->kink) - do_prekink(state, par, par_rot, t, part->kink_freq * ptex->kink, part->kink_shape, - part->kink_amp, part->kink, part->kink_axis, sim->ob->obmat); - - do_clump(state, par, t, part->clumpfac, part->clumppow, ptex->clump); + float clump = do_clump(state, par, t, part->clumpfac, part->clumppow, ptex ? ptex->clump : 1.f); + + if(kink_freq != 0.f) { + float kink_amp = part->kink_amp * (1.f - part->kink_amp_clump * clump); + + do_kink(state, par, par_rot, t, kink_freq, part->kink_shape, + kink_amp, part->kink_flat, part->kink, part->kink_axis, + sim->ob->obmat, sim->psys->part->childtype == PART_CHILD_FACES); + } } - if(part->rough1 != 0.0 && ptex->rough1 != 0.0) - do_rough(orco, mat, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state); + if(rough1 > 0.f) + do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state); - if(part->rough2 != 0.0 && ptex->rough2 != 0.0) - do_rough(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state); + if(rough2 > 0.f) + do_rough(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, rough2, part->rough2_size, part->rough2_thres, state); - if(part->rough_end != 0.0 && ptex->roughe != 0.0) - do_rough_end(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state); + if(rough_end > 0.f) + do_rough_end(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, rough_end, part->rough_end_shape, state); } /* get's hair (or keyed) particles state at the "path time" specified in state->time */ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, int vel) @@ -3937,10 +3983,9 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * ParticleThreadContext ctx; /* fake thread context for child modifiers */ ParticleInterpolationData pind; - float t, frs_sec = sim->scene->r.frs_sec; + float t; float co[3], orco[3]; float hairmat[4][4]; - int totparent = 0; int totpart = psys->totpart; int totchild = psys->totchild; short between = 0, edit = 0; @@ -3950,11 +3995,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * float *cpa_fuv; int cpa_num; short cpa_from; - //if(psys_in_edit_mode(scene, psys)){ - // if((psys->edit_path->flag & PSYS_EP_SHOW_CHILD)==0) - // totchild=0; - // edit=1; - //} + /* initialize keys to zero */ + memset(keys, 0, 4*sizeof(ParticleKey)); t=state->time; CLAMP(t, 0.0, 1.0); @@ -3969,7 +4011,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * * account when subdividing for instance */ pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : psys->hair_out_dm; init_particle_interpolation(sim->ob, psys, pa, &pind); - do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state); + do_particle_interpolation(psys, p, pa, t, &pind, state); if(!keyed && !cached) { if((pa->flag & PARS_REKEY)==0) { @@ -3996,11 +4038,6 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL); if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ - totparent=(int)(totchild*part->parents*0.3); - - if(G.rendering && part->child_nbr && part->ren_child_nbr) - totparent*=(float)part->child_nbr/(float)part->ren_child_nbr; - /* part->parents could still be 0 so we can't test with totparent */ between=1; } @@ -4031,7 +4068,10 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * pa = psys->particles + cpa->parent; - psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); + if(part->type == PART_HAIR) + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); + else + unit_m4(hairmat); pa=0; } @@ -4047,9 +4087,16 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * cpa_num=pa->num; cpa_fuv=pa->fuv; - psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0); + - psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); + if(part->type == PART_HAIR) { + psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0); + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); + } + else { + copy_v3_v3(orco, cpa->fuv); + unit_m4(hairmat); + } } /* correct child ipo timing */ @@ -4090,7 +4137,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * } else{ /* offset the child from the parent position */ - offset_child(cpa, keys, state, part->childflat, part->childrad); + offset_child(cpa, keys, keys->rot, state, part->childflat, part->childrad); } par = keys; @@ -4169,11 +4216,11 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta if(pa) { if(!always) - if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0) - || (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0)) + if((cfra < pa->time && (part->flag & PART_UNBORN)==0) + || (cfra > pa->dietime && (part->flag & PART_DIED)==0)) return 0; - state->time = MIN2(state->time, pa->dietime); + cfra = MIN2(cfra, pa->dietime); } if(sim->psys->flag & PSYS_KEYED){ @@ -4183,41 +4230,42 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta } else{ if(cpa){ + float mat[4][4]; ParticleKey *key1; float t = (cfra - pa->time) / pa->lifetime; key1=&pa->state; - offset_child(cpa, key1, state, part->childflat, part->childrad); - + offset_child(cpa, key1, key1->rot, state, part->childflat, part->childrad); + CLAMP(t,0.0,1.0); - if(part->kink) /* TODO: part->kink_freq*pa_kink */ - do_prekink(state,key1,key1->rot,t,part->kink_freq,part->kink_shape,part->kink_amp,part->kink,part->kink_axis,sim->ob->obmat); - - /* TODO: pa_clump vgroup */ - do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0); + + unit_m4(mat); + do_child_modifiers(sim, NULL, key1, key1->rot, cpa, cpa->fuv, mat, state, t); if(psys->lattice) calc_latt_deform(sim->psys->lattice, state->co,1.0f); } else{ - if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) - || pa->prev_state.time <= 0.0f) + if(pa->state.time==cfra || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)) copy_particle_key(state, &pa->state, 1); - else if(pa->prev_state.time==state->time) + else if(pa->prev_state.time==cfra) copy_particle_key(state, &pa->prev_state, 1); else { + float dfra, frs_sec = sim->scene->r.frs_sec; /* let's interpolate to try to be as accurate as possible */ - if(pa->state.time + 2.0f > state->time && pa->prev_state.time - 2.0f < state->time) { - ParticleKey keys[4]; - float dfra, keytime, frs_sec = sim->scene->r.frs_sec; + if(pa->state.time + 2.f >= state->time && pa->prev_state.time - 2.f <= state->time) { + if(pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.f) { + /* prev_state is wrong so let's not use it, this can happen at frames 1, 0 or particle birth */ + dfra = state->time - pa->state.time; - if(pa->prev_state.time >= pa->state.time) { - /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */ copy_particle_key(state, &pa->state, 1); - VECADDFAC(state->co, state->co, state->vel, (state->time-pa->state.time)/frs_sec); + madd_v3_v3v3fl(state->co, state->co, state->vel, dfra/frs_sec); } else { + ParticleKey keys[4]; + float keytime; + copy_particle_key(keys+1, &pa->prev_state, 1); copy_particle_key(keys+2, &pa->state, 1); @@ -4232,12 +4280,21 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta psys_interpolate_particle(-1, keys, keytime, state, 1); /* convert back to real velocity */ - mul_v3_fl(state->vel, 1.0f / (dfra * timestep)); + mul_v3_fl(state->vel, 1.f / (dfra * timestep)); interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime); interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime); } } + else if(pa->state.time + 1.f >= state->time && pa->state.time - 1.f <= state->time) { + /* linear interpolation using only pa->state */ + + dfra = state->time - pa->state.time; + + copy_particle_key(state, &pa->state, 1); + + madd_v3_v3v3fl(state->co, state->co, state->vel, dfra/frs_sec); + } else { /* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */ copy_particle_key(state, &pa->state, 0); @@ -4252,7 +4309,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta } } -void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco) +void psys_get_dupli_texture(Object *UNUSED(ob), ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco) { MFace *mface; MTFace *mtface; @@ -4285,7 +4342,7 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo if(num == DMCACHE_NOTFOUND) num= pa->num; - if (num >= psmd->dm->getNumFaces(psmd->dm)) { + if (num >= psmd->dm->getNumTessFaces(psmd->dm)) { /* happens when simplify is enabled * gives invalid coords but would crash otherwise */ num= DMCACHE_NOTFOUND; @@ -4357,7 +4414,7 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa normalize_v3(side); cross_v3_v3v3(nor, vec, side); - unit_m4(mat); + unit_m4(mat); VECCOPY(mat[0], vec); VECCOPY(mat[1], side); VECCOPY(mat[2], nor); @@ -4450,9 +4507,12 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] VECADDFAC(center, center, yvec, bb->offset[1]); } - void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) { - ParticleSimulationData sim = {scene, ob, psys, psys_get_modifier(ob, psys)}; + ParticleSimulationData sim= {0}; + sim.scene= scene; + sim.ob= ob; + sim.psys= psys; + sim.psmd= psys_get_modifier(ob, psys); psys->lattice = psys_get_lattice(&sim); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 955de554e00..b4900553814 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -29,6 +29,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <stddef.h> #include "BLI_storage.h" /* _LARGEFILE_SOURCE */ #include <stdlib.h> @@ -53,6 +54,7 @@ #include "DNA_ipo_types.h" // XXX old animation system stuff... to be removed! #include "DNA_listBase.h" +#include "BLI_edgehash.h" #include "BLI_rand.h" #include "BLI_jitter.h" #include "BLI_math.h" @@ -61,7 +63,10 @@ #include "BLI_kdopbvh.h" #include "BLI_listbase.h" #include "BLI_threads.h" +#include "BLI_storage.h" /* For _LARGEFILE64_SOURCE; zlib needs this on some systems */ +#include "BLI_utildefines.h" +#include "BKE_main.h" #include "BKE_animsys.h" #include "BKE_boids.h" #include "BKE_cdderivedmesh.h" @@ -70,7 +75,7 @@ #include "BKE_effect.h" #include "BKE_particle.h" #include "BKE_global.h" -#include "BKE_utildefines.h" + #include "BKE_DerivedMesh.h" #include "BKE_object.h" #include "BKE_material.h" @@ -115,7 +120,8 @@ static int particles_are_dynamic(ParticleSystem *psys) { else return ELEM3(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID); } -int psys_get_current_display_percentage(ParticleSystem *psys) + +static int psys_get_current_display_percentage(ParticleSystem *psys) { ParticleSettings *part=psys->part; @@ -124,8 +130,18 @@ int psys_get_current_display_percentage(ParticleSystem *psys) || (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */ return 100; - return psys->part->disp; - } + return psys->part->disp; +} + +static int tot_particles(ParticleSystem *psys, PTCacheID *pid) +{ + if(pid && psys->pointcache->flag & PTCACHE_EXTERNAL) + return pid->cache->totpoint; + else if(psys->part->distr == PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) + return psys->part->grid_res * psys->part->grid_res * psys->part->grid_res - psys->totunexist; + else + return psys->part->totpart - psys->totunexist; +} void psys_reset(ParticleSystem *psys, int mode) { @@ -133,9 +149,12 @@ void psys_reset(ParticleSystem *psys, int mode) if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) { if(mode == PSYS_RESET_ALL || !(psys->flag & PSYS_EDITED)) { - psys_free_particles(psys); + /* don't free if not absolutely necessary */ + if(psys->totpart != tot_particles(psys, NULL)) { + psys_free_particles(psys); + psys->totpart= 0; + } - psys->totpart= 0; psys->totkeyed= 0; psys->flag &= ~(PSYS_HAIR_DONE|PSYS_KEYED); @@ -155,7 +174,7 @@ void psys_reset(ParticleSystem *psys, int mode) /* reset children */ if(psys->child) { MEM_freeN(psys->child); - psys->child= 0; + psys->child= NULL; } psys->totchild= 0; @@ -165,6 +184,13 @@ void psys_reset(ParticleSystem *psys, int mode) /* reset point cache */ BKE_ptcache_invalidate(psys->pointcache); + + if(psys->fluid_springs) { + MEM_freeN(psys->fluid_springs); + psys->fluid_springs = NULL; + } + + psys->tot_fluidsprings = psys->alloc_fluidsprings = 0; } static void realloc_particles(ParticleSimulationData *sim, int new_totpart) @@ -194,9 +220,22 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) psys->free_edit = NULL; } - newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles"); - if(psys->part->phystype == PART_PHYS_BOIDS) - newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles"); + if(totpart) { + newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles"); + if(newpars == NULL) + return; + + if(psys->part->phystype == PART_PHYS_BOIDS) { + newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles"); + + if(newboids == NULL) { + /* allocation error! */ + if(newpars) + MEM_freeN(newpars); + return; + } + } + } if(psys->particles) { totsaved=MIN2(psys->totpart,totpart); @@ -239,7 +278,7 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) if(psys->child) { MEM_freeN(psys->child); - psys->child=0; + psys->child=NULL; psys->totchild=0; } } @@ -274,7 +313,7 @@ static void alloc_child_particles(ParticleSystem *psys, int tot) } MEM_freeN(psys->child); - psys->child=0; + psys->child=NULL; psys->totchild=0; } @@ -332,12 +371,17 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) /* cache the verts/faces! */ LOOP_PARTICLES { + if(pa->num < 0) { + pa->num_dmcache = -1; + continue; + } + if(psys->part->from == PART_FROM_VERT) { if(nodearray[pa->num]) pa->num_dmcache= GET_INT_FROM_POINTER(nodearray[pa->num]->link); } else { /* FROM_FACE/FROM_VOLUME */ - /* Note that somtimes the pa->num is over the nodearray size, this is bad, maybe there is a better place to fix this, + /* Note that sometimes the pa->num is over the nodearray size, this is bad, maybe there is a better place to fix this, * but for now passing NULL is OK. every face will be searched for the particle so its slower - Campbell */ pa->num_dmcache= psys_particle_dm_face_lookup(ob, dm, pa->num, pa->fuv, pa->num < totelem ? nodearray[pa->num] : NULL); } @@ -358,7 +402,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) { - ParticleData *pa=0; + ParticleData *pa=NULL; float min[3], max[3], delta[3], d; MVert *mv, *mvert = dm->getVertDataArray(dm,0); int totvert=dm->getNumVerts(dm), from=psys->part->from; @@ -367,8 +411,8 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) mv=mvert; /* find bounding box of dm */ - VECCOPY(min,mv->co); - VECCOPY(max,mv->co); + copy_v3_v3(min, mv->co); + copy_v3_v3(max, mv->co); mv++; for(i=1; i<totvert; i++, mv++){ @@ -384,30 +428,35 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) VECSUB(delta,max,min); /* determine major axis */ - axis = (delta[0]>=delta[1])?0:((delta[1]>=delta[2])?1:2); - + axis = (delta[0]>=delta[1]) ? 0 : ((delta[1]>=delta[2]) ? 1 : 2); + d = delta[axis]/(float)res; - size[axis]=res; - size[(axis+1)%3]=(int)ceil(delta[(axis+1)%3]/d); - size[(axis+2)%3]=(int)ceil(delta[(axis+2)%3]/d); + size[axis] = res; + size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d); + size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d); /* float errors grrr.. */ size[(axis+1)%3] = MIN2(size[(axis+1)%3],res); size[(axis+2)%3] = MIN2(size[(axis+2)%3],res); - min[0]+=d/2.0f; - min[1]+=d/2.0f; - min[2]+=d/2.0f; + size[0] = MAX2(size[0], 1); + size[1] = MAX2(size[1], 1); + size[2] = MAX2(size[2], 1); + + /* no full offset for flat/thin objects */ + min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f; + min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f; + min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f; for(i=0,p=0,pa=psys->particles; i<res; i++){ for(j=0; j<res; j++){ for(k=0; k<res; k++,p++,pa++){ - pa->fuv[0]=min[0]+(float)i*d; - pa->fuv[1]=min[1]+(float)j*d; - pa->fuv[2]=min[2]+(float)k*d; + pa->fuv[0] = min[0] + (float)i*d; + pa->fuv[1] = min[1] + (float)j*d; + pa->fuv[2] = min[2] + (float)k*d; pa->flag |= PARS_UNEXIST; - pa->hair_index=0; /* abused in volume calculation */ + pa->hair_index = 0; /* abused in volume calculation */ } } } @@ -418,9 +467,9 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) pa=psys->particles; - min[0]-=d/2.0f; - min[1]-=d/2.0f; - min[2]-=d/2.0f; + min[0] -= d/2.0f; + min[1] -= d/2.0f; + min[2] -= d/2.0f; for(i=0,mv=mvert; i<totvert; i++,mv++){ sub_v3_v3v3(vec,mv->co,min); @@ -435,13 +484,13 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) else if(ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)){ float co1[3], co2[3]; - MFace *mface=0; + MFace *mface= NULL, *mface_array; float v1[3], v2[3], v3[3], v4[4], lambda; int a, a1, a2, a0mul, a1mul, a2mul, totface; int amax= from==PART_FROM_FACE ? 3 : 1; totface=dm->getNumTessFaces(dm); - mface=dm->getTessFaceDataArray(dm,CD_MFACE); + mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE); for(a=0; a<amax; a++){ if(a==0){ a0mul=res*res; a1mul=res; a2mul=1; } @@ -450,22 +499,22 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) for(a1=0; a1<size[(a+1)%3]; a1++){ for(a2=0; a2<size[(a+2)%3]; a2++){ - mface=dm->getTessFaceDataArray(dm,CD_MFACE); - - pa=psys->particles + a1*a1mul + a2*a2mul; - VECCOPY(co1,pa->fuv); - co1[a]-=d/2.0f; - VECCOPY(co2,co1); - co2[a]+=delta[a] + 0.001f*d; - co1[a]-=0.001f*d; + mface= mface_array; + + pa = psys->particles + a1*a1mul + a2*a2mul; + copy_v3_v3(co1, pa->fuv); + co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f; + copy_v3_v3(co2, co1); + co2[a] += delta[a] + 0.001f*d; + co1[a] -= 0.001f*d; /* lets intersect the faces */ for(i=0; i<totface; i++,mface++){ - VECCOPY(v1,mvert[mface->v1].co); - VECCOPY(v2,mvert[mface->v2].co); - VECCOPY(v3,mvert[mface->v3].co); + copy_v3_v3(v1, mvert[mface->v1].co); + copy_v3_v3(v2, mvert[mface->v2].co); + copy_v3_v3(v3, mvert[mface->v3].co); - if(isect_axial_line_tri_v3(a,co1, co2, v2, v3, v1, &lambda)){ + if(isect_axial_line_tri_v3(a, co1, co2, v2, v3, v1, &lambda)){ if(from==PART_FROM_FACE) (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; else /* store number of intersections */ @@ -473,9 +522,9 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) } if(mface->v4){ - VECCOPY(v4,mvert[mface->v4].co); + copy_v3_v3(v4, mvert[mface->v4].co); - if(isect_axial_line_tri_v3(a,co1, co2, v4, v1, v3, &lambda)){ + if(isect_axial_line_tri_v3(a, co1, co2, v4, v1, v3, &lambda)){ if(from==PART_FROM_FACE) (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; else @@ -500,8 +549,24 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) } } + if(psys->part->flag & PART_GRID_HEXAGONAL) { + for(i=0,p=0,pa=psys->particles; i<res; i++){ + for(j=0; j<res; j++){ + for(k=0; k<res; k++,p++,pa++){ + if(j%2) + pa->fuv[0] += d/2.f; + + if(k%2) { + pa->fuv[0] += d/2.f; + pa->fuv[1] += d/2.f; + } + } + } + } + } + if(psys->part->flag & PART_GRID_INVERT){ - for(i=0,pa=psys->particles; i<size[0]; i++){ + for(i=0; i<size[0]; i++){ for(j=0; j<size[1]; j++){ pa=psys->particles + res*(i*res + j); for(k=0; k<size[2]; k++, pa++){ @@ -510,6 +575,18 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) } } } + + if(psys->part->grid_rand > 0.f) { + float rfac = d * psys->part->grid_rand; + for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++){ + if(pa->flag & PARS_UNEXIST) + continue; + + pa->fuv[0] += rfac * (PSYS_FRAND(p + 31) - 0.5f); + pa->fuv[1] += rfac * (PSYS_FRAND(p + 32) - 0.5f); + pa->fuv[2] += rfac * (PSYS_FRAND(p + 33) - 0.5f); + } + } } /* modified copy from rayshade.c */ @@ -603,15 +680,21 @@ static void psys_uv_to_w(float u, float v, int quad, float *w) } } +/* Find the index in "sum" array before "value" is crossed. */ static int binary_search_distribution(float *sum, int n, float value) { int mid, low=0, high=n; + if(value == 0.f) + return 0; + while(low <= high) { mid= (low + high)/2; - if(sum[mid] <= value && value <= sum[mid+1]) + + if(sum[mid] < value && value <= sum[mid+1]) return mid; - else if(sum[mid] > value) + + if(sum[mid] >= value) high= mid - 1; else if(sum[mid] < value) low= mid + 1; @@ -635,7 +718,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData DerivedMesh *dm= ctx->dm; ParticleData *tpa; /* ParticleSettings *part= ctx->sim.psys->part; */ - float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3], ornor1[3]; + float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3]; float cur_d, min_d, randu, randv; int from= ctx->from; int cfrom= ctx->cfrom; @@ -772,20 +855,17 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData if(ctx->tree){ KDTreeNearest ptn[10]; int w,maxw;//, do_seams; - float maxd,mind,dd,totw=0.0; + float maxd,mind,/*dd,*/totw=0.0; int parent[10]; float pweight[10]; - /*do_seams= (part->flag&PART_CHILD_SEAMS && ctx->seams);*/ - - psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,0,0,orco1,ornor1); + psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL); transform_mesh_orco_verts((Mesh*)ob->data, &orco1, 1, 1); - //maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,orco1,ornor1,ptn); - maxw = BLI_kdtree_find_n_nearest(ctx->tree,4,orco1,ornor1,ptn); + maxw = BLI_kdtree_find_n_nearest(ctx->tree,4,orco1,NULL,ptn); maxd=ptn[maxw-1].dist; mind=ptn[0].dist; - dd=maxd-mind; + /*dd=maxd-mind;*/ /*UNUSED*/ /* the weights here could be done better */ for(w=0; w<maxw; w++){ @@ -796,63 +876,6 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData parent[w]=-1; pweight[w]=0.0f; } - //if(do_seams){ - // ParticleSeam *seam=ctx->seams; - // float temp[3],temp2[3],tan[3]; - // float inp,cur_len,min_len=10000.0f; - // int min_seam=0, near_vert=0; - // /* find closest seam */ - // for(i=0; i<ctx->totseam; i++, seam++){ - // sub_v3_v3v3(temp,co1,seam->v0); - // inp=dot_v3v3(temp,seam->dir)/seam->length2; - // if(inp<0.0f){ - // cur_len=len_v3v3(co1,seam->v0); - // } - // else if(inp>1.0f){ - // cur_len=len_v3v3(co1,seam->v1); - // } - // else{ - // copy_v3_v3(temp2,seam->dir); - // mul_v3_fl(temp2,inp); - // cur_len=len_v3v3(temp,temp2); - // } - // if(cur_len<min_len){ - // min_len=cur_len; - // min_seam=i; - // if(inp<0.0f) near_vert=-1; - // else if(inp>1.0f) near_vert=1; - // else near_vert=0; - // } - // } - // seam=ctx->seams+min_seam; - // - // copy_v3_v3(temp,seam->v0); - // - // if(near_vert){ - // if(near_vert==-1) - // sub_v3_v3v3(tan,co1,seam->v0); - // else{ - // sub_v3_v3v3(tan,co1,seam->v1); - // copy_v3_v3(temp,seam->v1); - // } - - // normalize_v3(tan); - // } - // else{ - // copy_v3_v3(tan,seam->tan); - // sub_v3_v3v3(temp2,co1,temp); - // if(dot_v3v3(tan,temp2)<0.0f) - // negate_v3(tan); - // } - // for(w=0; w<maxw; w++){ - // sub_v3_v3v3(temp2,ptn[w].co,temp); - // if(dot_v3v3(tan,temp2)<0.0f){ - // parent[w]=-1; - // pweight[w]=0.0f; - // } - // } - - //} for(w=0,i=0; w<maxw && i<4; w++){ if(parent[w]>=0){ @@ -963,7 +986,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *dm= NULL; float *jit= NULL; int i, seed, p=0, totthread= threads[0].tot; - int no_distr=0, cfrom=0; + int /*no_distr=0,*/ cfrom=0; int tot=0, totpart, *index=0, children=0, totseam=0; //int *vertpart=0; int jitlevel= 1, distr; @@ -988,6 +1011,8 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, if(from==PART_FROM_CHILD){ distr=PART_DISTR_RAND; + BLI_srandom(31415926 + psys->seed + psys->child_seed); + if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ dm= finaldm; children=1; @@ -1004,50 +1029,6 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, totpart=get_psys_tot_child(scene, psys); cfrom=from=PART_FROM_FACE; - - //if(part->flag&PART_CHILD_SEAMS){ - // MEdge *ed, *medge=dm->getEdgeDataArray(dm,CD_MEDGE); - // MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); - // int totedge=dm->getNumEdges(dm); - - // for(p=0, ed=medge; p<totedge; p++,ed++) - // if(ed->flag&ME_SEAM) - // totseam++; - - // if(totseam){ - // ParticleSeam *cur_seam=seams=MEM_callocN(totseam*sizeof(ParticleSeam),"Child Distribution Seams"); - // float temp[3],temp2[3]; - - // for(p=0, ed=medge; p<totedge; p++,ed++){ - // if(ed->flag&ME_SEAM){ - // copy_v3_v3(cur_seam->v0,(mvert+ed->v1)->co); - // copy_v3_v3(cur_seam->v1,(mvert+ed->v2)->co); - - // sub_v3_v3v3(cur_seam->dir,cur_seam->v1,cur_seam->v0); - - // cur_seam->length2=len_v3(cur_seam->dir); - // cur_seam->length2*=cur_seam->length2; - - // temp[0]=(float)((mvert+ed->v1)->no[0]); - // temp[1]=(float)((mvert+ed->v1)->no[1]); - // temp[2]=(float)((mvert+ed->v1)->no[2]); - // temp2[0]=(float)((mvert+ed->v2)->no[0]); - // temp2[1]=(float)((mvert+ed->v2)->no[1]); - // temp2[2]=(float)((mvert+ed->v2)->no[2]); - - // add_v3_v3v3(cur_seam->nor,temp,temp2); - // normalize_v3(cur_seam->nor); - - // cross_v3_v3v3(cur_seam->tan,cur_seam->dir,cur_seam->nor); - - // normalize_v3(cur_seam->tan); - - // cur_seam++; - // } - // } - // } - // - //} } else{ /* no need to figure out distribution */ @@ -1092,7 +1073,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); distr=part->distr; - pa=psys->particles; + if(from==PART_FROM_VERT){ MVert *mv= dm->getVertDataArray(dm, CD_MVERT); float (*orcodata)[3]= dm->getVertDataArray(dm, CD_ORCO); @@ -1137,7 +1118,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, } if(tot==0){ - no_distr=1; + /*no_distr=1;*/ /*UNUSED*/ if(children){ if(G.f & G_DEBUG) fprintf(stderr,"Particle child distribution error: Nothing to emit from!\n"); @@ -1284,7 +1265,8 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, float pos; for(p=0; p<totpart; p++) { - pos= BLI_frand(); + /* In theory sys[tot] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */ + pos= BLI_frand() * sum[tot]; index[p]= binary_search_distribution(sum, tot, pos); index[p]= MIN2(tot-1, index[p]); jitoff[index[p]]= pos; @@ -1434,7 +1416,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) } /* ready for future use, to emit particles without geometry */ -static void distribute_particles_on_shape(ParticleSimulationData *sim, int from) +static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from)) { ParticleSystem *psys = sim->psys; PARTICLE_P; @@ -1554,113 +1536,77 @@ void psys_threads_free(ParticleThread *threads) /* set particle parameters that don't change during particle's life */ void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p) { - ParticleSettings *part = sim->psys->part; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; ParticleTexture ptex; - Material *ma=0; - //IpoCurve *icu=0; // XXX old animation system - int totpart; - totpart=sim->psys->totpart; + pa->flag &= ~PARS_UNEXIST; - ptex.life=ptex.size=ptex.exist=ptex.length=1.0; - ptex.time=(float)p/(float)totpart; - - BLI_srandom(sim->psys->seed + p + 125); - - if(part->from!=PART_FROM_PARTICLE && part->type!=PART_FLUID){ - ma=give_current_material(sim->ob,part->omat); + if(part->from != PART_FROM_PARTICLE && part->type != PART_FLUID) { + psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f); + + if(ptex.exist < PSYS_FRAND(p+125)) + pa->flag |= PARS_UNEXIST; - /* TODO: needs some work to make most blendtypes generally usefull */ - psys_get_texture(sim,ma,pa,&ptex,MAP_PA_INIT); + pa->time = (part->type == PART_HAIR) ? 0.f : part->sta + (part->end - part->sta)*ptex.time; } - if(part->type==PART_HAIR) - pa->time= 0.0f; - //else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0) - // pa->time= 300000.0f; /* max frame */ - else{ - //icu=find_ipocurve(psys->part->ipo,PART_EMIT_TIME); - //if(icu){ - // calc_icu(icu,100*ptex.time); - // ptex.time=icu->curval; - //} - - pa->time= part->sta + (part->end - part->sta)*ptex.time; - } - - if(part->type!=PART_HAIR && part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){ - if(ptex.exist < BLI_frand()) - pa->flag |= PARS_UNEXIST; - else - pa->flag &= ~PARS_UNEXIST; - } - - pa->hair_index=0; + pa->hair_index = 0; /* we can't reset to -1 anymore since we've figured out correct index in distribute_particles */ /* usage other than straight after distribute has to handle this index by itself - jahka*/ //pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we dont have a derived mesh face */ } static void initialize_all_particles(ParticleSimulationData *sim) { - //IpoCurve *icu=0; // XXX old animation system ParticleSystem *psys = sim->psys; PARTICLE_P; - LOOP_PARTICLES - initialize_particle(sim, pa, p); - - if(psys->part->type != PART_FLUID) { -#if 0 // XXX old animation system - icu=find_ipocurve(psys->part->ipo,PART_EMIT_FREQ); - if(icu){ - float time=psys->part->sta, end=psys->part->end; - float v1, v2, a=0.0f, t1,t2, d; - - p=0; - pa=psys->particles; - - - calc_icu(icu,time); - v1=icu->curval; - if(v1<0.0f) v1=0.0f; - - calc_icu(icu,time+1.0f); - v2=icu->curval; - if(v2<0.0f) v2=0.0f; - - for(p=0, pa=psys->particles; p<totpart && time<end; p++, pa++){ - while(a+0.5f*(v1+v2) < (float)(p+1) && time<end){ - a+=0.5f*(v1+v2); - v1=v2; - time++; - calc_icu(icu,time+1.0f); - v2=icu->curval; - } - if(time<end){ - if(v1==v2){ - pa->time=time+((float)(p+1)-a)/v1; - } - else{ - d=(float)sqrt(v1*v1-2.0f*(v2-v1)*(a-(float)(p+1))); - t1=(-v1+d)/(v2-v1); - t2=(-v1-d)/(v2-v1); - - /* the root between 0-1 is the correct one */ - if(t1>0.0f && t1<=1.0f) - pa->time=time+t1; - else - pa->time=time+t2; - } - } + psys->totunexist = 0; + + LOOP_PARTICLES { + if((pa->flag & PARS_UNEXIST)==0) + initialize_particle(sim, pa, p); + + if(pa->flag & PARS_UNEXIST) + psys->totunexist++; + } + + /* Free unexisting particles. */ + if(psys->totpart && psys->totunexist == psys->totpart) { + if(psys->particles->boid) + MEM_freeN(psys->particles->boid); + + MEM_freeN(psys->particles); + psys->particles = NULL; + psys->totpart = psys->totunexist = 0; + } + + if(psys->totunexist) { + int newtotpart = psys->totpart - psys->totunexist; + ParticleData *npa, *newpars; + + npa = newpars = MEM_callocN(newtotpart * sizeof(ParticleData), "particles"); + + for(p=0, pa=psys->particles; p<newtotpart; p++, pa++, npa++) { + while(pa->flag & PARS_UNEXIST) + pa++; + + memcpy(npa, pa, sizeof(ParticleData)); + } + + if(psys->particles->boid) + MEM_freeN(psys->particles->boid); + MEM_freeN(psys->particles); + psys->particles = newpars; + psys->totpart -= psys->totunexist; + + if(psys->particles->boid) { + BoidParticle *newboids = MEM_callocN(psys->totpart * sizeof(BoidParticle), "boid particles"); + + LOOP_PARTICLES + pa->boid = newboids++; - pa->dietime = pa->time+pa->lifetime; - pa->flag &= ~PARS_UNEXIST; - } - for(; p<totpart; p++, pa++){ - pa->flag |= PARS_UNEXIST; - } } -#endif // XXX old animation system } } /* sets particle to the emitter surface with initial velocity & rotation */ @@ -1670,39 +1616,19 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, ParticleSystem *psys = sim->psys; ParticleSettings *part; ParticleTexture ptex; - ParticleKey state; - //IpoCurve *icu=0; // XXX old animation system float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3]={0.0,0.0,0.0}; float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; - float q_phase[4], r_phase; + float q_phase[4]; int p = pa - psys->particles; part=psys->part; - ptex.ivel=1.0; - ptex.life=1.0; - - /* we need to get every random even if they're not used so that they don't effect eachother */ - r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f); - r_vel[1] = 2.0f * (PSYS_FRAND(p + 11) - 0.5f); - r_vel[2] = 2.0f * (PSYS_FRAND(p + 12) - 0.5f); - - r_ave[0] = 2.0f * (PSYS_FRAND(p + 13) - 0.5f); - r_ave[1] = 2.0f * (PSYS_FRAND(p + 14) - 0.5f); - r_ave[2] = 2.0f * (PSYS_FRAND(p + 15) - 0.5f); - - r_rot[0] = 2.0f * (PSYS_FRAND(p + 16) - 0.5f); - r_rot[1] = 2.0f * (PSYS_FRAND(p + 17) - 0.5f); - r_rot[2] = 2.0f * (PSYS_FRAND(p + 18) - 0.5f); - r_rot[3] = 2.0f * (PSYS_FRAND(p + 19) - 0.5f); - normalize_qt(r_rot); - - r_phase = PSYS_FRAND(p + 20); - +#if 0 /* deprecated code */ if(part->from==PART_FROM_PARTICLE){ - ParticleSimulationData tsim = {sim->scene, psys->target_ob ? psys->target_ob : ob, NULL, NULL}; float speed; - + ParticleSimulationData tsim= {0}; + tsim.scene= sim->scene; + tsim.ob= psys->target_ob ? psys->target_ob : ob; tsim.psys = BLI_findlink(&tsim.ob->particlesystem, sim->psys->target_psys-1); state.time = pa->time; @@ -1724,79 +1650,93 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, VECCOPY(pa->fuv, loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */ } else{ - /* get precise emitter matrix if particle is born */ - if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) { - /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */ - BKE_animsys_evaluate_animdata(&sim->ob->id, sim->ob->adt, pa->time, ADT_RECALC_ANIM); - where_is_object_time(sim->scene, sim->ob, pa->time); - } +#endif + /* get precise emitter matrix if particle is born */ + if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) { + /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */ + BKE_animsys_evaluate_animdata(&sim->ob->id, sim->ob->adt, pa->time, ADT_RECALC_ANIM); + where_is_object_time(sim->scene, sim->ob, pa->time); + } - /* get birth location from object */ - if(part->tanfac!=0.0) - psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); - else - psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); + /* get birth location from object */ + if(part->tanfac != 0.f) + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); + else + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); - /* get possible textural influence */ - psys_get_texture(sim, give_current_material(sim->ob,part->omat), pa, &ptex, MAP_PA_IVEL|MAP_PA_LIFE); + /* get possible textural influence */ + psys_get_texture(sim, pa, &ptex, PAMAP_IVEL|PAMAP_LIFE, cfra); - //if(vg_vel && pa->num != -1) - // ptex.ivel*=psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_vel); - - /* particles live in global space so */ - /* let's convert: */ - /* -location */ - mul_m4_v3(ob->obmat,loc); + /* particles live in global space so */ + /* let's convert: */ + /* -location */ + mul_m4_v3(ob->obmat, loc); - /* -normal */ - mul_mat3_m4_v3(ob->obmat,nor); - normalize_v3(nor); - - /* -tangent */ - if(part->tanfac!=0.0){ - //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; - float phase=0.0f; - mul_v3_fl(vtan,-(float)cos(M_PI*(part->tanphase+phase))); - fac=-(float)sin(M_PI*(part->tanphase+phase)); - VECADDFAC(vtan,vtan,utan,fac); - - mul_mat3_m4_v3(ob->obmat,vtan); - - VECCOPY(utan,nor); - mul_v3_fl(utan,dot_v3v3(vtan,nor)); - VECSUB(vtan,vtan,utan); + /* -normal */ + mul_mat3_m4_v3(ob->obmat, nor); + normalize_v3(nor); + + /* -tangent */ + if(part->tanfac!=0.0){ + //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; + float phase=0.0f; + mul_v3_fl(vtan,-(float)cos(M_PI*(part->tanphase+phase))); + fac=-(float)sin(M_PI*(part->tanphase+phase)); + VECADDFAC(vtan,vtan,utan,fac); + + mul_mat3_m4_v3(ob->obmat,vtan); + + VECCOPY(utan,nor); + mul_v3_fl(utan,dot_v3v3(vtan,nor)); + VECSUB(vtan,vtan,utan); - normalize_v3(vtan); - } + normalize_v3(vtan); + } - /* -velocity */ - if(part->randfac!=0.0){ - mul_mat3_m4_v3(ob->obmat,r_vel); - normalize_v3(r_vel); - } + /* -velocity */ + if(part->randfac!=0.0){ + r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f); + r_vel[1] = 2.0f * (PSYS_FRAND(p + 11) - 0.5f); + r_vel[2] = 2.0f * (PSYS_FRAND(p + 12) - 0.5f); - /* -angular velocity */ - if(part->avemode==PART_AVE_RAND){ - mul_mat3_m4_v3(ob->obmat,r_ave); - normalize_v3(r_ave); - } + mul_mat3_m4_v3(ob->obmat, r_vel); + normalize_v3(r_vel); + } + + /* -angular velocity */ + if(part->avemode==PART_AVE_RAND){ + r_ave[0] = 2.0f * (PSYS_FRAND(p + 13) - 0.5f); + r_ave[1] = 2.0f * (PSYS_FRAND(p + 14) - 0.5f); + r_ave[2] = 2.0f * (PSYS_FRAND(p + 15) - 0.5f); + + mul_mat3_m4_v3(ob->obmat,r_ave); + normalize_v3(r_ave); + } - /* -rotation */ - if(part->randrotfac != 0.0f){ - mat4_to_quat(rot,ob->obmat); - mul_qt_qtqt(r_rot,r_rot,rot); - } + /* -rotation */ + if(part->randrotfac != 0.0f){ + r_rot[0] = 2.0f * (PSYS_FRAND(p + 16) - 0.5f); + r_rot[1] = 2.0f * (PSYS_FRAND(p + 17) - 0.5f); + r_rot[2] = 2.0f * (PSYS_FRAND(p + 18) - 0.5f); + r_rot[3] = 2.0f * (PSYS_FRAND(p + 19) - 0.5f); + normalize_qt(r_rot); + + mat4_to_quat(rot,ob->obmat); + mul_qt_qtqt(r_rot,r_rot,rot); + } +#if 0 } +#endif if(part->phystype==PART_PHYS_BOIDS && pa->boid) { BoidParticle *bpa = pa->boid; float dvec[3], q[4], mat[3][3]; - VECCOPY(pa->state.co,loc); + copy_v3_v3(pa->state.co,loc); /* boids don't get any initial velocity */ - pa->state.vel[0]=pa->state.vel[1]=pa->state.vel[2]=0.0f; + zero_v3(pa->state.vel); /* boids store direction in ave */ if(fabs(nor[2])==1.0f) { @@ -1835,66 +1775,56 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, /* -velocity from: */ /* *reactions */ - if(dtime>0.0f){ - VECSUB(vel,pa->state.vel,pa->prev_state.vel); + if(dtime > 0.f){ + sub_v3_v3v3(vel, pa->state.vel, pa->prev_state.vel); } /* *emitter velocity */ - if(dtime!=0.0 && part->obfac!=0.0){ - VECSUB(vel,loc,pa->state.co); - mul_v3_fl(vel,part->obfac/dtime); + if(dtime != 0.f && part->obfac != 0.f){ + sub_v3_v3v3(vel, loc, pa->state.co); + mul_v3_fl(vel, part->obfac/dtime); } /* *emitter normal */ - if(part->normfac!=0.0) - VECADDFAC(vel,vel,nor,part->normfac); + if(part->normfac != 0.f) + madd_v3_v3fl(vel, nor, part->normfac); /* *emitter tangent */ - if(sim->psmd && part->tanfac!=0.0) - VECADDFAC(vel,vel,vtan,part->tanfac); - //VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_tan):1.0f)); + if(sim->psmd && part->tanfac != 0.f) + madd_v3_v3fl(vel, vtan, part->tanfac); /* *emitter object orientation */ - if(part->ob_vel[0]!=0.0) { + if(part->ob_vel[0] != 0.f) { normalize_v3_v3(vec, ob->obmat[0]); - VECADDFAC(vel, vel, vec, part->ob_vel[0]); + madd_v3_v3fl(vel, vec, part->ob_vel[0]); } - if(part->ob_vel[1]!=0.0) { + if(part->ob_vel[1] != 0.f) { normalize_v3_v3(vec, ob->obmat[1]); - VECADDFAC(vel, vel, vec, part->ob_vel[1]); + madd_v3_v3fl(vel, vec, part->ob_vel[1]); } - if(part->ob_vel[2]!=0.0) { + if(part->ob_vel[2] != 0.f) { normalize_v3_v3(vec, ob->obmat[2]); - VECADDFAC(vel, vel, vec, part->ob_vel[2]); + madd_v3_v3fl(vel, vec, part->ob_vel[2]); } /* *texture */ /* TODO */ /* *random */ - if(part->randfac!=0.0) - VECADDFAC(vel,vel,r_vel,part->randfac); + if(part->randfac != 0.f) + madd_v3_v3fl(vel, r_vel, part->randfac); /* *particle */ - if(part->partfac!=0.0) - VECADDFAC(vel,vel,p_vel,part->partfac); - - //icu=find_ipocurve(psys->part->ipo,PART_EMIT_VEL); - //if(icu){ - // calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta))); - // ptex.ivel*=icu->curval; - //} - - mul_v3_fl(vel,ptex.ivel); + if(part->partfac != 0.f) + madd_v3_v3fl(vel, p_vel, part->partfac); - VECCOPY(pa->state.vel,vel); + mul_v3_v3fl(pa->state.vel, vel, ptex.ivel); /* -location from emitter */ - VECCOPY(pa->state.co,loc); + copy_v3_v3(pa->state.co,loc); /* -rotation */ - pa->state.rot[0]=1.0; - pa->state.rot[1]=pa->state.rot[2]=pa->state.rot[3]=0.0; + unit_qt(pa->state.rot); if(part->rotmode){ /* create vector into which rotation is aligned */ @@ -1930,7 +1860,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, /* rotation phase */ phasefac = part->phasefac; if(part->randphasefac != 0.0f) - phasefac += part->randphasefac * r_phase; + phasefac += part->randphasefac * PSYS_FRAND(p + 20); axis_angle_to_quat( q_phase,x_vec, phasefac*(float)M_PI); /* combine base rotation & phase */ @@ -1939,34 +1869,27 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, /* -angular velocity */ - pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0; + zero_v3(pa->state.ave); if(part->avemode){ switch(part->avemode){ case PART_AVE_SPIN: - VECCOPY(pa->state.ave,vel); + copy_v3_v3(pa->state.ave, vel); break; case PART_AVE_RAND: - VECCOPY(pa->state.ave,r_ave); + copy_v3_v3(pa->state.ave, r_ave); break; } normalize_v3(pa->state.ave); mul_v3_fl(pa->state.ave,part->avefac); - - //icu=find_ipocurve(psys->part->ipo,PART_EMIT_AVE); - //if(icu){ - // calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta))); - // mul_v3_fl(pa->state.ave,icu->curval); - //} } } - if(part->type == PART_HAIR){ pa->lifetime = 100.0f; } else{ - pa->lifetime = part->lifetime*ptex.life; + pa->lifetime = part->lifetime * ptex.life; if(part->randlife != 0.0) pa->lifetime *= 1.0f - part->randlife * PSYS_FRAND(p + 21); @@ -1993,15 +1916,9 @@ static void reset_all_particles(ParticleSimulationData *sim, float dtime, float { ParticleData *pa; int p, totpart=sim->psys->totpart; - //float *vg_vel=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_VEL); - //float *vg_tan=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_TAN); - //float *vg_rot=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_ROT); for(p=from, pa=sim->psys->particles+from; p<totpart; p++, pa++) reset_particle(sim, pa, dtime, cfra); - - //if(vg_vel) - // MEM_freeN(vg_vel); } /************************************************/ /* Particle targets */ @@ -2052,12 +1969,14 @@ void psys_count_keyed_targets(ParticleSimulationData *sim) static void set_keyed_keys(ParticleSimulationData *sim) { ParticleSystem *psys = sim->psys; - ParticleSimulationData ksim = {sim->scene, NULL, NULL, NULL}; + ParticleSimulationData ksim= {0}; ParticleTarget *pt; PARTICLE_P; ParticleKey *key; int totpart = psys->totpart, k, totkeys = psys->totkeyed; + ksim.scene= sim->scene; + /* no proper targets so let's clear and bail out */ if(psys->totkeyed==0) { free_keyed_keys(psys); @@ -2228,7 +2147,9 @@ void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys) if(cache->flag & PTCACHE_DISK_CACHE && cache->mem_cache.first == NULL) { PTCacheID pid; BKE_ptcache_id_from_particles(&pid, ob, psys); + cache->flag &= ~PTCACHE_DISK_CACHE; BKE_ptcache_disk_to_mem(&pid); + cache->flag |= PTCACHE_DISK_CACHE; } } static void psys_clear_temp_pointcache(ParticleSystem *psys) @@ -2280,136 +2201,249 @@ static void psys_update_effectors(ParticleSimulationData *sim) precalc_guides(sim, sim->psys->effectors); } -/************************************************* +/********************************************************************************************************* SPH fluid physics - In theory, there could be unlimited implementation - of SPH simulators -**************************************************/ -void particle_fluidsim(ParticleSystem *psys, ParticleData *pa, ParticleSettings *part, ParticleSimulationData *sim, float dfra, float cfra, float mass){ -/**************************************************************************************************************** -* This code uses in some parts adapted algorithms from the pseduo code as outlined in the Research paper -* Titled: Particle-based Viscoelastic Fluid Simulation. -* Authors: Simon Clavet, Philippe Beaudoin and Pierre Poulin -* -* Website: http://www.iro.umontreal.ca/labs/infographie/papers/Clavet-2005-PVFS/ -* Presented at Siggraph, (2005) -* -*****************************************************************************************************************/ - KDTree *tree = psys->tree; - KDTreeNearest *ptn = NULL; - - SPHFluidSettings *fluid = part->fluid; - ParticleData *second_particle; + In theory, there could be unlimited implementation of SPH simulators - float start[3], end[3], v[3]; - float temp[3]; - float q, radius, D; - float p, pnear, pressure_near, pressure; - float dtime = dfra * psys_get_timestep(sim); - float omega = fluid->viscosity_omega; - float beta = fluid->viscosity_omega; - float massfactor = 1.0f/mass; - int n, neighbours; + This code uses in some parts adapted algorithms from the pseudo code as outlined in the Research paper: - - radius = fluid->radius; + Titled: Particle-based Viscoelastic Fluid Simulation. + Authors: Simon Clavet, Philippe Beaudoin and Pierre Poulin + Website: http://www.iro.umontreal.ca/labs/infographie/papers/Clavet-2005-PVFS/ - VECCOPY(start, pa->prev_state.co); - VECCOPY(end, pa->state.co); + Presented at Siggraph, (2005) - VECCOPY(v, pa->state.vel); +***********************************************************************************************************/ +#define PSYS_FLUID_SPRINGS_INITIAL_SIZE 256 +static ParticleSpring *add_fluid_spring(ParticleSystem *psys, ParticleSpring *spring) +{ + /* Are more refs required? */ + if(psys->alloc_fluidsprings == 0 || psys->fluid_springs == NULL) { + psys->alloc_fluidsprings = PSYS_FLUID_SPRINGS_INITIAL_SIZE; + psys->fluid_springs = (ParticleSpring*)MEM_callocN(psys->alloc_fluidsprings * sizeof(ParticleSpring), "Particle Fluid Springs"); + } + else if(psys->tot_fluidsprings == psys->alloc_fluidsprings) { + /* Double the number of refs allocated */ + psys->alloc_fluidsprings *= 2; + psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring)); + } - neighbours = BLI_kdtree_range_search(tree, radius, start, NULL, &ptn); + memcpy(psys->fluid_springs + psys->tot_fluidsprings, spring, sizeof(ParticleSpring)); + psys->tot_fluidsprings++; - /* use ptn[n].co to store relative direction */ - for(n=1; n<neighbours; n++) { - sub_v3_v3(ptn[n].co, start); - normalize_v3(ptn[n].co); - } - - /* Viscosity - Algorithm 5 */ - if (omega > 0.f || beta > 0.f) { - float u, I; + return psys->fluid_springs + psys->tot_fluidsprings - 1; +} - for(n=1; n<neighbours; n++) { - second_particle = psys->particles + ptn[n].index; - q = ptn[n].dist/radius; - - sub_v3_v3v3(temp, v, second_particle->prev_state.vel); - - u = dot_v3v3(ptn[n].co, temp); +static void delete_fluid_spring(ParticleSystem *psys, int j) +{ + if (j != psys->tot_fluidsprings - 1) + psys->fluid_springs[j] = psys->fluid_springs[psys->tot_fluidsprings - 1]; + + psys->tot_fluidsprings--; - if (u > 0){ - I = dtime * ((1-q) * (omega * u + beta * u*u)) * 0.5f; - madd_v3_v3fl(v, ptn[n].co, -I * massfactor); - } - } + if (psys->tot_fluidsprings < psys->alloc_fluidsprings/2 && psys->alloc_fluidsprings > PSYS_FLUID_SPRINGS_INITIAL_SIZE){ + psys->alloc_fluidsprings /= 2; + psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring)); } +} + +static EdgeHash *build_fluid_springhash(ParticleSystem *psys) +{ + EdgeHash *springhash = NULL; + ParticleSpring *spring; + int i = 0; - /* Hooke's spring force */ - if (fluid->spring_k > 0.f) { - float D, L = fluid->rest_length; - for(n=1; n<neighbours; n++) { - /* L is a factor of radius */ - D = dtime * 10.f * fluid->spring_k * (1.f - L) * (L - ptn[n].dist/radius); - madd_v3_v3fl(v, ptn[n].co, -D * massfactor); + springhash = BLI_edgehash_new(); + + for(i=0, spring=psys->fluid_springs; i<psys->tot_fluidsprings; i++, spring++) + BLI_edgehash_insert(springhash, spring->particle_index[0], spring->particle_index[1], SET_INT_IN_POINTER(i+1)); + + return springhash; +} +static void particle_fluidsim(ParticleSystem *psys, int own_psys, ParticleData *pa, float dtime, float mass, float *gravity, EdgeHash *springhash) +{ + SPHFluidSettings *fluid = psys->part->fluid; + KDTreeNearest *ptn = NULL; + ParticleData *npa; + ParticleSpring *spring = NULL; + + float temp[3]; + float q, q1, u, I, D, rij, d, Lij; + float pressure_near, pressure; + float p=0, pnear=0; + + float omega = fluid->viscosity_omega; + float beta = fluid->viscosity_beta; + float massfactor = 1.0f/mass; + float spring_k = fluid->spring_k; + float h = fluid->radius; + float L = fluid->rest_length * fluid->radius; + + int n, neighbours = BLI_kdtree_range_search(psys->tree, h, pa->prev_state.co, NULL, &ptn); + int spring_index = 0, index = own_psys ? pa - psys->particles : -1; + + /* pressure and near pressure */ + for(n=own_psys?1:0; n<neighbours; n++) { + /* disregard particles at the exact same location */ + if(ptn[n].dist < FLT_EPSILON) + continue; + + sub_v3_v3(ptn[n].co, pa->prev_state.co); + mul_v3_fl(ptn[n].co, 1.f/ptn[n].dist); + q = ptn[n].dist/h; + + if(q < 1.f) { + q1 = 1.f - q; + + p += q1*q1; + pnear += q1*q1*q1; } } - /* Update particle position */ - VECADDFAC(end, start, v, dtime); - /* Double Density Relaxation - Algorithm 2 */ - p = 0; - pnear = 0; - for(n=1; n<neighbours; n++) { - q = ptn[n].dist/radius; - p += ((1-q)*(1-q)); - pnear += ((1-q)*(1-q)*(1-q)); - } - p *= part->mass; - pnear *= part->mass; + p *= mass; + pnear *= mass; pressure = fluid->stiffness_k * (p - fluid->rest_density); pressure_near = fluid->stiffness_knear * pnear; - for(n=1; n<neighbours; n++) { - q = ptn[n].dist/radius; + /* main calculations */ + for(n=own_psys?1:0; n<neighbours; n++) { + /* disregard particles at the exact same location */ + if(ptn[n].dist < FLT_EPSILON) + continue; + + npa = psys->particles + ptn[n].index; + + rij = ptn[n].dist; + q = rij/h; + q1 = 1.f-q; + + /* Double Density Relaxation - Algorithm 2 (can't be thread safe!)*/ + D = dtime * dtime * (pressure + pressure_near*q1)*q1 * 0.5f; + madd_v3_v3fl(pa->state.co, ptn[n].co, -D * massfactor); + if(own_psys) + madd_v3_v3fl(npa->state.co, ptn[n].co, D * massfactor); + + if(index < ptn[n].index) { + /* Viscosity - Algorithm 5 */ + if(omega > 0.f || beta > 0.f) { + sub_v3_v3v3(temp, pa->state.vel, npa->state.vel); + u = dot_v3v3(ptn[n].co, temp); + + if (u > 0){ + I = dtime * (q1 * (omega * u + beta * u*u)) * 0.5f; + madd_v3_v3fl(pa->state.vel, ptn[n].co, -I * massfactor); + + if(own_psys) + madd_v3_v3fl(npa->state.vel, ptn[n].co, I * massfactor); + } + } + + if(spring_k > 0.f) { + /* Viscoelastic spring force - Algorithm 4*/ + if (fluid->flag & SPH_VISCOELASTIC_SPRINGS && springhash){ + spring_index = GET_INT_FROM_POINTER(BLI_edgehash_lookup(springhash, index, ptn[n].index)); + + if(spring_index) { + spring = psys->fluid_springs + spring_index - 1; + } + else { + ParticleSpring temp_spring; + temp_spring.particle_index[0] = index; + temp_spring.particle_index[1] = ptn[n].index; + temp_spring.rest_length = (fluid->flag & SPH_CURRENT_REST_LENGTH) ? rij : L; + temp_spring.delete_flag = 0; + + spring = add_fluid_spring(psys, &temp_spring); + } - D = dtime * dtime * (pressure*(1-q) + pressure_near*(1-q)*(1-q))* 0.5f; - madd_v3_v3fl(end, ptn[n].co, -D * massfactor); - } + Lij = spring->rest_length; + d = fluid->yield_ratio * Lij; + + if (rij > Lij + d) // Stretch, 25 is just a multiplier for plasticity_constant value to counter default dtime of 1/25 + spring->rest_length += dtime * 25.f * fluid->plasticity_constant * (rij - Lij - d); + else if(rij < Lij - d) // Compress + spring->rest_length -= dtime * 25.f * fluid->plasticity_constant * (Lij - d - rij); + } + else { /* PART_SPRING_HOOKES - Hooke's spring force */ + /* L is a factor of radius */ + D = 0.5 * dtime * dtime * 10.f * fluid->spring_k * (1.f - L/h) * (L - rij); + + madd_v3_v3fl(pa->state.co, ptn[n].co, -D * massfactor); + if(own_psys) + madd_v3_v3fl(npa->state.co, ptn[n].co, D * massfactor); + } + } + } + } /* Artificial buoyancy force in negative gravity direction */ - if (fluid->buoyancy >= 0.f && psys_uses_gravity(sim)) { + if (fluid->buoyancy >= 0.f && gravity) { float B = -dtime * dtime * fluid->buoyancy * (p - fluid->rest_density) * 0.5f; - madd_v3_v3fl(end, sim->scene->physics_settings.gravity, -B * massfactor); + madd_v3_v3fl(pa->state.co, gravity, -B * massfactor); } - /* apply final result and recalculate velocity */ - VECCOPY(pa->state.co, end); - sub_v3_v3v3(pa->state.vel, end, start); - mul_v3_fl(pa->state.vel, 1.f/dtime); - - if(ptn){ MEM_freeN(ptn); ptn=NULL;} + if(ptn) + MEM_freeN(ptn); } -static void apply_particle_fluidsim(ParticleSystem *psys, ParticleData *pa, ParticleSettings *part, ParticleSimulationData *sim, float dfra, float cfra){ +static void apply_particle_fluidsim(Object *ob, ParticleSystem *psys, ParticleData *pa, float dtime, float *gravity, EdgeHash *springhash){ ParticleTarget *pt; -// float dtime = dfra*psys_get_timestep(sim); - float particle_mass = part->mass; - particle_fluidsim(psys, pa, part, sim, dfra, cfra, particle_mass); + particle_fluidsim(psys, 1, pa, dtime, psys->part->mass, gravity, springhash); /*----check other SPH systems (Multifluids) , each fluid has its own parameters---*/ - for(pt=sim->psys->targets.first; pt; pt=pt->next) { - ParticleSystem *epsys = psys_get_target_system(sim->ob, pt); + for(pt=psys->targets.first; pt; pt=pt->next) { + ParticleSystem *epsys = psys_get_target_system(ob, pt); if(epsys) - particle_fluidsim(epsys, pa, epsys->part, sim, dfra, cfra, particle_mass); + particle_fluidsim(epsys, 0, pa, dtime, psys->part->mass, gravity, NULL); } /*----------------------------------------------------------------*/ } +static void apply_fluid_springs(ParticleSystem *psys, float timestep){ + SPHFluidSettings *fluid = psys->part->fluid; + ParticleData *pa1, *pa2; + ParticleSpring *spring = psys->fluid_springs; + + float h = fluid->radius; + float massfactor = 1.0f/psys->part->mass; + float D, Rij[3], rij, Lij; + int i; + + if((fluid->flag & SPH_VISCOELASTIC_SPRINGS)==0 || fluid->spring_k == 0.f) + return; + + /* Loop through the springs */ + for(i=0; i<psys->tot_fluidsprings; i++, spring++) { + Lij = spring->rest_length; + + if (Lij > h) { + spring->delete_flag = 1; + } + else { + pa1 = psys->particles + spring->particle_index[0]; + pa2 = psys->particles + spring->particle_index[1]; + + sub_v3_v3v3(Rij, pa2->prev_state.co, pa1->prev_state.co); + rij = normalize_v3(Rij); + + /* Calculate displacement and apply value */ + D = 0.5f * timestep * timestep * 10.f * fluid->spring_k * (1.f - Lij/h) * (Lij - rij); + + madd_v3_v3fl(pa1->state.co, Rij, -D * pa1->state.time * pa1->state.time * massfactor); + madd_v3_v3fl(pa2->state.co, Rij, D * pa2->state.time * pa2->state.time * massfactor); + } + } + + /* Loop through springs backwaqrds - for efficient delete function */ + for (i=psys->tot_fluidsprings-1; i >= 0; i--) { + if(psys->fluid_springs[i].delete_flag) + delete_fluid_spring(psys, i); + } +} + /************************************************/ /* Newtonian physics */ /************************************************/ @@ -2422,8 +2456,11 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra ParticleKey states[5], tkey; float timestep = psys_get_timestep(sim); float force[3],impulse[3],dx[4][3],dv[4][3],oldpos[3]; - float dtime=dfra*timestep, time, pa_mass=part->mass, fac, fra=sim->psys->cfra; + float dtime=dfra*timestep, time, pa_mass=part->mass, fac /*, fra=sim->psys->cfra*/; int i, steps=1; + ParticleTexture ptex; + + psys_get_texture(sim, pa, &ptex, PAMAP_PHYSICS, cfra); /* maintain angular velocity */ VECCOPY(pa->state.ave,pa->prev_state.ave); @@ -2457,6 +2494,9 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra if(part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR) pdDoEffectors(sim->psys->effectors, sim->colliders, part->effector_weights, &epoint, force, impulse); + mul_v3_fl(force, ptex.field); + mul_v3_fl(impulse, ptex.field); + /* calculate air-particle interaction */ if(part->dragfac!=0.0f){ fac=-part->dragfac*pa->size*pa->size*len_v3(states[i].vel); @@ -2477,10 +2517,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra if(psys_uses_gravity(sim) /* normal gravity is too strong for hair so it's disabled by default */ && (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)) { - float gravity[3]; - VECCOPY(gravity, sim->scene->physics_settings.gravity); - mul_v3_fl(gravity, part->effector_weights->global_gravity); - VECADD(force,force,gravity); + madd_v3_v3fl(force, sim->scene->physics_settings.gravity, part->effector_weights->global_gravity * ptex.gravity); } /* calculate next state */ @@ -2495,7 +2532,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra if(i==0){ VECADDFAC(states[1].co,states->co,states->vel,dtime*0.5f); VECADDFAC(states[1].vel,states->vel,force,dtime*0.5f); - fra=sim->psys->cfra+0.5f*dfra; + /*fra=sim->psys->cfra+0.5f*dfra;*/ } else{ VECADDFAC(pa->state.co,states->co,states[1].vel,dtime); @@ -2512,7 +2549,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra VECADDFAC(states[1].co,states->co,dx[0],0.5f); VECADDFAC(states[1].vel,states->vel,dv[0],0.5f); - fra=sim->psys->cfra+0.5f*dfra; + /*fra=sim->psys->cfra+0.5f*dfra;*/ break; case 1: VECADDFAC(dx[1],states->vel,dv[0],0.5f); @@ -2531,7 +2568,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra VECADD(states[3].co,states->co,dx[2]); VECADD(states[3].vel,states->vel,dv[2]); - fra=cfra; + /*fra=cfra;*/ break; case 3: VECADD(dx[3],states->vel,dv[2]); @@ -2561,8 +2598,8 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra } /* damp affects final velocity */ - if(part->dampfac!=0.0) - mul_v3_fl(pa->state.vel,1.0f-part->dampfac); + if(part->dampfac != 0.f) + mul_v3_fl(pa->state.vel, 1.f - part->dampfac * ptex.damp); VECCOPY(pa->state.ave, states->ave); @@ -2772,23 +2809,26 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B MVert *x = col->md->x; MVert *v = col->md->current_v; float vel[3], co1[3], co2[3], uv[2], ipoint[3], temp[3], t; + float x0[3], x1[3], x2[3], x3[3]; + float *t0=x0, *t1=x1, *t2=x2, *t3=(face->v4 ? x3 : NULL); - float *t0, *t1, *t2, *t3; - t0 = x[ face->v1 ].co; - t1 = x[ face->v2 ].co; - t2 = x[ face->v3 ].co; - t3 = face->v4 ? x[ face->v4].co : NULL; + /* move collision face to start of timestep */ + madd_v3_v3v3fl(t0, x[face->v1].co, v[face->v1].co, col->cfra); + madd_v3_v3v3fl(t1, x[face->v2].co, v[face->v2].co, col->cfra); + madd_v3_v3v3fl(t2, x[face->v3].co, v[face->v3].co, col->cfra); + if(t3) + madd_v3_v3v3fl(t3, x[face->v4].co, v[face->v4].co, col->cfra); /* calculate average velocity of face */ - VECCOPY(vel, v[ face->v1 ].co); - VECADD(vel, vel, v[ face->v2 ].co); - VECADD(vel, vel, v[ face->v3 ].co); - mul_v3_fl(vel, 0.33334f); + copy_v3_v3(vel, v[ face->v1 ].co); + add_v3_v3(vel, v[ face->v2 ].co); + add_v3_v3(vel, v[ face->v3 ].co); + mul_v3_fl(vel, 0.33334f*col->dfra); /* substract face velocity, in other words convert to a coordinate system where only the particle moves */ - VECADDFAC(co1, col->co1, vel, -col->t); - VECSUB(co2, col->co2, vel); + madd_v3_v3v3fl(co1, col->co1, vel, -col->f); + sub_v3_v3v3(co2, col->co2, vel); do { @@ -2836,11 +2876,18 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B } while(t2); } -/* particle - mesh collision code */ -/* in addition to basic point to surface collisions handles friction & damping,*/ -/* angular momentum <-> linear momentum and swept sphere - mesh collisions */ -/* 1. check for all possible deflectors for closest intersection on particle path */ -/* 2. if deflection was found kill the particle or calculate new coordinates */ +/* Particle - Mesh collision code + * Features: + * - point and swept sphere to mesh surface collisions + * - moving colliders (but not yet rotating or deforming colliders) + * - friction & damping + * - angular momentum <-> linear momentum + * - high accuracy by re-applying particle acceleration after collision + * - behaves relatively well even if limit of 10 collisions per simulation step is exceeded + * Main parts: + * 1. check for all possible deflectors for closest intersection on particle path + * 2. if deflection was found calculate new coordinates or kill the particle + */ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, float cfra){ Object *ground_ob = NULL; ParticleSettings *part = sim->psys->part; @@ -2848,20 +2895,22 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo ParticleCollision col; ColliderCache *coll; BVHTreeRayHit hit; - float ray_dir[3], zerovec[3]={0.0,0.0,0.0}; + float ray_dir[3], acc[3]; float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f), boid_z = 0.0f; - float timestep = psys_get_timestep(sim); + float timestep = psys_get_timestep(sim) * dfra; + float inv_timestep = 1.0f/timestep; int deflections=0, max_deflections=10; - VECCOPY(col.co1, pa->prev_state.co); - VECCOPY(col.co2, pa->state.co); - - VECCOPY(col.ve1, pa->prev_state.vel); - VECCOPY(col.ve2, pa->state.vel); - mul_v3_fl(col.ve1, timestep * dfra); - mul_v3_fl(col.ve2, timestep * dfra); - - col.t = 0.0f; + /* get acceleration (from gravity, forcefields etc. to be re-applied after collision) */ + sub_v3_v3v3(acc, pa->state.vel, pa->prev_state.vel); + mul_v3_fl(acc, inv_timestep); + + /* set values for first iteration */ + copy_v3_v3(col.co1, pa->prev_state.co); + copy_v3_v3(col.co2, pa->state.co); + copy_v3_v3(col.ve1, pa->prev_state.vel); + copy_v3_v3(col.ve2, pa->state.vel); + col.f = 0.0f; /* override for boids */ if(part->phystype == PART_PHYS_BOIDS) { @@ -2875,10 +2924,13 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo if(sim->colliders) while(deflections < max_deflections){ /* 1. */ - VECSUB(ray_dir, col.co2, col.co1); + sub_v3_v3v3(ray_dir, col.co2, col.co1); hit.index = -1; hit.dist = col.ray_len = len_v3(ray_dir); + col.cfra = fmod(cfra-dfra, 1.0f); + col.dfra = dfra; + /* even if particle is stationary we want to check for moving colliders */ /* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */ if(hit.dist == 0.0f) @@ -2903,45 +2955,49 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo /* 2. */ if(hit.index>=0) { PartDeflect *pd = col.hit_ob->pd; - int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; - float co[3]; /* point of collision */ - float vec[3]; /* movement through collision */ - float acc[3]; /* acceleration */ - - float x = hit.dist/col.ray_len; /* location of collision between this iteration */ - float le = len_v3(col.ve1)/col.ray_len; - float ac = len_v3(col.ve2)/col.ray_len - le; /* (taking acceleration into account) */ - float t = (-le + sqrt(le*le + 2*ac*x))/ac; /* time of collision between this iteration */ - float dt = col.t + x * (1.0f - col.t); /* time of collision between frame change*/ - float it = 1.0 - t; + float co[3]; /* point of collision */ + float x = hit.dist/col.ray_len; /* location factor of collision between this iteration */ + float f = col.f + x * (1.0f - col.f); /* time factor of collision between timestep */ + float dt1 = (f - col.f) * timestep; /* time since previous collision (in seconds) */ + float dt2 = (1.0f - f) * timestep; /* time left after collision (in seconds) */ + int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */ + + deflections++; interp_v3_v3v3(co, col.co1, col.co2, x); - VECSUB(vec, col.co2, col.co1); - - VECSUB(acc, col.ve2, col.ve1); - mul_v3_fl(col.vel, 1.0f-col.t); + /* make sure we don't hit the current face again */ + /* TODO: could/should this be proportional to pa->size? */ + madd_v3_v3fl(co, col.nor, (through ? -0.0001f : 0.0001f)); /* particle dies in collision */ if(through == 0 && (part->flag & PART_DIE_ON_COL || pd->flag & PDEFLE_KILL_PART)) { pa->alive = PARS_DYING; - pa->dietime = pa->state.time + (cfra - pa->state.time) * dt; - - /* we have to add this for dying particles too so that reactors work correctly */ - VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); + pa->dietime = sim->psys->cfra + (cfra - sim->psys->cfra) * f; - VECCOPY(pa->state.co, co); - interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, dt); - interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, dt); - interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, dt); + copy_v3_v3(pa->state.co, co); + interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, f); + interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, f); + interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, f); /* particle is dead so we don't need to calculate further */ - deflections=max_deflections; + return; } + /* figure out velocity and other data after collision */ else { - float nor_vec[3], tan_vec[3], tan_vel[3]; + float v0[3]; /* velocity directly before collision to be modified into velocity directly after collision */ + float v0_nor[3];/* normal component of v0 */ + float v0_tan[3];/* tangential component of v0 */ + float vc_tan[3];/* tangential component of collision surface velocity */ + float check[3]; + float v0_dot, vc_dot, check_dot; float damp, frict; - float inp, inp_v; + + /* get exact velocity right before collision */ + madd_v3_v3v3fl(v0, col.ve1, acc, dt1); + + /* convert collider velocity from 1/framestep to 1/s */ + mul_v3_fl(col.vel, inv_timestep); /* get damping & friction factors */ damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f); @@ -2951,119 +3007,118 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo CLAMP(frict,0.0,1.0); /* treat normal & tangent components separately */ - inp = dot_v3v3(col.nor, vec); - inp_v = dot_v3v3(col.nor, col.vel); - - VECADDFAC(tan_vec, vec, col.nor, -inp); - VECADDFAC(tan_vel, col.vel, col.nor, -inp_v); - if((part->flag & PART_ROT_DYN)==0) - interp_v3_v3v3(tan_vec, tan_vec, tan_vel, frict); - - VECCOPY(nor_vec, col.nor); - inp *= 1.0f - damp; + v0_dot = dot_v3v3(col.nor, v0); + madd_v3_v3v3fl(v0_tan, v0, col.nor, -v0_dot); - if(through) - inp_v *= damp; + vc_dot = dot_v3v3(col.nor, col.vel); + madd_v3_v3v3fl(vc_tan, col.vel, col.nor, -vc_dot); - /* special case for object hitting the particle from behind */ - if(through==0 && ((inp_v>0 && inp>0 && inp_v>inp) || (inp_v<0 && inp<0 && inp_v<inp))) - mul_v3_fl(nor_vec, inp_v); - else - mul_v3_fl(nor_vec, inp_v + (through ? 1.0f : -1.0f) * inp); - - /* angular <-> linear velocity - slightly more physical and looks even nicer than before */ - if(part->flag & PART_ROT_DYN) { - float surface_vel[3], rot_vel[3], friction[3], dave[3], dvel[3]; - - /* apparent velocity along collision surface */ - VECSUB(surface_vel, tan_vec, tan_vel); + /* handle friction effects (tangential and angular velocity) */ + if(frict > 0.0f) { + /* angular <-> linear velocity */ + if(part->flag & PART_ROT_DYN) { + float vr_tan[3], v1_tan[3], ave[3]; + + /* linear velocity of particle surface */ + cross_v3_v3v3(vr_tan, col.nor, pa->state.ave); + mul_v3_fl(vr_tan, pa->size); - /* direction of rolling friction */ - cross_v3_v3v3(rot_vel, pa->state.ave, col.nor); - /* convert to current dt */ - mul_v3_fl(rot_vel, (timestep*dfra) * (1.0f - col.t)); - mul_v3_fl(rot_vel, pa->size); + /* change to coordinates that move with the collision plane */ + sub_v3_v3v3(v1_tan, v0_tan, vc_tan); + + /* The resulting velocity is a weighted average of particle cm & surface + * velocity. This weight (related to particle's moment of inertia) could + * be made a parameter for angular <-> linear conversion. + */ + madd_v3_v3fl(v1_tan, vr_tan, -0.4); + mul_v3_fl(v1_tan, 1.0f/1.4f); /* 1/(1+0.4) */ - /* apply sliding friction */ - VECSUB(surface_vel, surface_vel, rot_vel); - VECCOPY(friction, surface_vel); + /* rolling friction is around 0.01 of sliding friction (could be made a parameter) */ + mul_v3_fl(v1_tan, 1.0f - 0.01f * frict); - mul_v3_fl(surface_vel, 1.0 - frict); - mul_v3_fl(friction, frict); + /* surface_velocity is opposite to cm velocity */ + mul_v3_v3fl(vr_tan, v1_tan, -1.0f); - /* sliding changes angular velocity */ - cross_v3_v3v3(dave, col.nor, friction); - mul_v3_fl(dave, 1.0f/MAX2(pa->size, 0.001)); + /* get back to global coordinates */ + add_v3_v3(v1_tan, vc_tan); - /* we assume rolling friction is around 0.01 of sliding friction */ - mul_v3_fl(rot_vel, 1.0 - frict*0.01); + /* convert to angular velocity*/ + cross_v3_v3v3(ave, vr_tan, col.nor); + mul_v3_fl(ave, 1.0f/MAX2(pa->size, 0.001)); - /* change in angular velocity has to be added to the linear velocity too */ - cross_v3_v3v3(dvel, dave, col.nor); - mul_v3_fl(dvel, pa->size); - VECADD(rot_vel, rot_vel, dvel); + /* only friction will cause change in linear & angular velocity */ + interp_v3_v3v3(pa->state.ave, pa->state.ave, ave, frict); + interp_v3_v3v3(v0_tan, v0_tan, v1_tan, frict); + } + else { + /* just basic friction (unphysical due to the friction model used in Blender) */ + interp_v3_v3v3(v0_tan, v0_tan, vc_tan, frict); + } + } - VECADD(surface_vel, surface_vel, rot_vel); - VECADD(tan_vec, surface_vel, tan_vel); + /* stickness was possibly added before, so cancel that before calculating new normal velocity */ + /* otherwise particles go flying out of the surface because of high reversed sticky velocity */ + if(v0_dot < 0.0f) { + v0_dot += pd->pdef_stickness; + if(v0_dot > 0.0f) + v0_dot = 0.0f; + } - /* convert back to normal time */ - mul_v3_fl(dave, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); + /* damping and flipping of velocity around normal */ + v0_dot *= 1.0f - damp; + vc_dot *= through ? damp : 1.0f; - mul_v3_fl(pa->state.ave, 1.0 - frict*0.01); - VECADD(pa->state.ave, pa->state.ave, dave); - } + /* special case for object hitting the particle from behind */ + if(through==0 && ((vc_dot>0.0f && v0_dot>0.0f && vc_dot>v0_dot) || (vc_dot<0.0f && v0_dot<0.0f && vc_dot<v0_dot))) + mul_v3_v3fl(v0_nor, col.nor, vc_dot); + else + mul_v3_v3fl(v0_nor, col.nor, vc_dot + (through ? 1.0f : -1.0f) * v0_dot); /* combine components together again */ - VECADD(vec, nor_vec, tan_vec); - - /* make sure we don't hit the current face again */ - VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); + add_v3_v3v3(v0, v0_nor, v0_tan); + /* keep boids above ground */ if(part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) { BoidParticle *bpa = pa->boid; if(bpa->data.mode == eBoidMode_OnLand || co[2] <= boid_z) { co[2] = boid_z; - vec[2] = 0.0f; + v0[2] = 0.0f; } } - - /* set coordinates for next iteration */ - /* apply acceleration to final position, but make sure particle stays above surface */ - madd_v3_v3v3fl(acc, vec, acc, it); - ac = dot_v3v3(acc, col.nor); - if((!through && ac < 0.0f) || (through && ac > 0.0f)) - madd_v3_v3fl(acc, col.nor, -ac); - - VECCOPY(col.co1, co); - VECADDFAC(col.co2, co, acc, it); - - VECCOPY(col.ve1, vec); - VECCOPY(col.ve2, acc); - - if(len_v3(vec) < 0.001 && len_v3v3(pa->state.co, pa->prev_state.co) < 0.001) { - /* kill speed to stop slipping */ - VECCOPY(pa->state.vel,zerovec); - VECCOPY(pa->state.co, co); - if(part->flag & PART_ROT_DYN) { - VECCOPY(pa->state.ave,zerovec); - } - } - else { - VECCOPY(pa->state.co, col.co2); - mul_v3_v3fl(pa->state.vel, acc, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); - + if(deflections < max_deflections) { + /* re-apply acceleration to final velocity and location */ + madd_v3_v3v3fl(pa->state.vel, v0, acc, dt2); + madd_v3_v3v3fl(pa->state.co, co, v0, dt2); + madd_v3_v3fl(pa->state.co, acc, 0.5f*dt2*dt2); + + /* make sure particle stays on the right side of the surface */ + sub_v3_v3v3(check, pa->state.co, co); + /* (collision surface has moved during the time too) */ + madd_v3_v3fl(check, col.vel, -dt2); + + check_dot = dot_v3v3(check, col.nor); + if((!through && check_dot < 0.0f) || (through && check_dot > 0.0f)) + madd_v3_v3fl(pa->state.co, col.nor, (through ? -0.0001f : 0.0001f) - check_dot); + /* Stickness to surface */ - normalize_v3(nor_vec); madd_v3_v3fl(pa->state.vel, col.nor, -pd->pdef_stickness); - } - col.t = dt; - } - deflections++; + /* set coordinates for next iteration */ + copy_v3_v3(col.co1, co); + copy_v3_v3(col.co2, pa->state.co); - //reaction_state.time = cfra - (1.0f - dt) * dfra; - //push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); + copy_v3_v3(col.ve1, v0); + copy_v3_v3(col.ve2, pa->state.vel); + + col.f = f; + } + else { + /* final chance to prevent failure, so stick to the surface and hope for the best */ + madd_v3_v3v3fl(pa->state.co, co, col.vel, dt2); + copy_v3_v3(pa->state.vel, v0); + } + } } else return; @@ -3244,7 +3299,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) psys->clmd->point_cache = psys->pointcache; psys->clmd->sim_parms->effector_weights = psys->part->effector_weights; - psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, 0, 0); + psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm); psys->clmd->sim_parms->effector_weights = NULL; } @@ -3269,11 +3324,11 @@ static void hair_step(ParticleSimulationData *sim, float cfra) psys_calc_dmcache(sim->ob, sim->psmd->dm, psys); if(psys->clmd) - cloth_free_modifier(sim->ob, psys->clmd); + cloth_free_modifier(psys->clmd); } - /* dynamics with cloth simulation */ - if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) + /* dynamics with cloth simulation, psys->particles can be NULL with 0 particles [#25519] */ + if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS && psys->particles) do_hair_dynamics(sim); /* following lines were removed r29079 but cause bug [#22811], see report for details */ @@ -3283,20 +3338,17 @@ static void hair_step(ParticleSimulationData *sim, float cfra) psys->flag |= PSYS_HAIR_UPDATED; } -static void save_hair(ParticleSimulationData *sim, float cfra){ +static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)){ Object *ob = sim->ob; ParticleSystem *psys = sim->psys; HairKey *key, *root; PARTICLE_P; - int totpart; invert_m4_m4(ob->imat, ob->obmat); psys->lattice= psys_get_lattice(sim); if(psys->totpart==0) return; - - totpart=psys->totpart; /* save new keys for elements if needed */ LOOP_PARTICLES { @@ -3338,12 +3390,11 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) ParticleSystem *psys = sim->psys; ParticleSettings *part=psys->part; BoidBrainData bbd; + ParticleTexture ptex; PARTICLE_P; float timestep; - /* current time */ - float ctime; /* frame & time changes */ - float dfra, dtime, pa_dtime, pa_dfra=0.0; + float dfra, dtime; float birthtime, dietime; /* where have we gone in time since last time */ @@ -3351,11 +3402,11 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) timestep = psys_get_timestep(sim); dtime= dfra*timestep; - ctime= cfra*timestep; if(dfra<0.0){ LOOP_EXISTING_PARTICLES { - pa->size = part->size; + psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); + pa->size = part->size*ptex.size; if(part->randsize > 0.0) pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); @@ -3369,65 +3420,67 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) psys_update_effectors(sim); if(part->type != PART_HAIR) - sim->colliders = get_collider_cache(sim->scene, NULL, NULL); + sim->colliders = get_collider_cache(sim->scene, sim->ob, NULL); - if(part->phystype==PART_PHYS_BOIDS){ - ParticleTarget *pt = psys->targets.first; - bbd.sim = sim; - bbd.part = part; - bbd.cfra = cfra; - bbd.dfra = dfra; - bbd.timestep = timestep; + /* initialize physics type specific stuff */ + switch(part->phystype) { + case PART_PHYS_BOIDS: + { + ParticleTarget *pt = psys->targets.first; + bbd.sim = sim; + bbd.part = part; + bbd.cfra = cfra; + bbd.dfra = dfra; + bbd.timestep = timestep; - psys_update_particle_tree(psys, cfra); + psys_update_particle_tree(psys, cfra); - boids_precalc_rules(part, cfra); + boids_precalc_rules(part, cfra); - for(; pt; pt=pt->next) { - if(pt->ob) - psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra); + for(; pt; pt=pt->next) { + if(pt->ob) + psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra); + } + break; } - } - else if(part->phystype==PART_PHYS_FLUID){ - ParticleTarget *pt = psys->targets.first; - psys_update_particle_tree(psys, cfra); - - for(; pt; pt=pt->next) { /* Updating others systems particle tree for fluid-fluid interaction */ - if(pt->ob) psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra); + case PART_PHYS_FLUID: + { + ParticleTarget *pt = psys->targets.first; + psys_update_particle_tree(psys, cfra); + + for(; pt; pt=pt->next) { /* Updating others systems particle tree for fluid-fluid interaction */ + if(pt->ob) + psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra); + } + break; } } - - /* main loop: calculate physics for all particles */ + /* initialize all particles for dynamics */ LOOP_SHOWN_PARTICLES { copy_particle_key(&pa->prev_state,&pa->state,1); - pa->size = part->size; + psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); + + pa->size = part->size*ptex.size; if(part->randsize > 0.0) pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); - ///* reactions can change birth time so they need to be checked first */ - //if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) - // react_to_events(psys,p); - birthtime = pa->time; dietime = birthtime + pa->lifetime; - pa_dfra = dfra; - pa_dtime = dtime; - + /* store this, so we can do multiple loops over particles */ + pa->state.time = dfra; if(dietime <= cfra && psys->cfra < dietime){ /* particle dies some time between this and last step */ - pa_dfra = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra); - pa_dtime = pa_dfra * timestep; + pa->state.time = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra); pa->alive = PARS_DYING; } else if(birthtime <= cfra && birthtime >= psys->cfra){ /* particle is born some time between this and last step*/ - reset_particle(sim, pa, dtime, cfra); + reset_particle(sim, pa, dfra*timestep, cfra); pa->alive = PARS_ALIVE; - pa_dfra = cfra - birthtime; - pa_dtime = pa_dfra*timestep; + pa->state.time = cfra - birthtime; } else if(dietime < cfra){ /* nothing to be done when particle is dead */ @@ -3440,63 +3493,100 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) else if(part->phystype == PART_PHYS_NO) reset_particle(sim, pa, dtime, cfra); - if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ - switch(part->phystype){ - case PART_PHYS_NEWTON: - /* do global forces & effectors */ - apply_particle_forces(sim, p, pa_dfra, cfra); - + if(ELEM(pa->alive, PARS_ALIVE, PARS_DYING)==0 || (pa->flag & (PARS_UNEXIST|PARS_NO_DISP))) + pa->state.time = -1.f; + } + + switch(part->phystype) { + case PART_PHYS_NEWTON: + { + LOOP_DYNAMIC_PARTICLES { + /* do global forces & effectors */ + apply_particle_forces(sim, p, pa->state.time, cfra); + + /* deflection */ + if(sim->colliders) + deflect_particle(sim, p, pa->state.time, cfra); + + /* rotations */ + rotate_particle(part, pa, pa->state.time, timestep); + } + break; + } + case PART_PHYS_BOIDS: + { + LOOP_DYNAMIC_PARTICLES { + bbd.goal_ob = NULL; + + boid_brain(&bbd, p, pa); + + if(pa->alive != PARS_DYING) { + boid_body(&bbd, pa); + /* deflection */ if(sim->colliders) - deflect_particle(sim, p, pa_dfra, cfra); - - /* rotations */ - rotate_particle(part, pa, pa_dfra, timestep); - break; - case PART_PHYS_BOIDS: - { - bbd.goal_ob = NULL; - boid_brain(&bbd, p, pa); - if(pa->alive != PARS_DYING) { - boid_body(&bbd, pa); - - /* deflection */ - if(sim->colliders) - deflect_particle(sim, p, pa_dfra, cfra); - } - break; + deflect_particle(sim, p, pa->state.time, cfra); } - case PART_PHYS_FLUID: - { - /* do global forces & effectors */ - apply_particle_forces(sim, p, pa_dfra, cfra); + } + break; + } + case PART_PHYS_FLUID: + { + EdgeHash *springhash = build_fluid_springhash(psys); + float *gravity = NULL; - /* do fluid sim */ - apply_particle_fluidsim(psys, pa, part, sim, pa_dfra, cfra); + if(psys_uses_gravity(sim)) + gravity = sim->scene->physics_settings.gravity; - /* deflection */ - if(sim->colliders) - deflect_particle(sim, p, pa_dfra, cfra); - - /* rotations, SPH particles are not physical particles, just interpolation particles, thus rotation has not a direct sense for them */ - rotate_particle(part, pa, pa_dfra, timestep); - break; - } + /* do global forces & effectors */ + LOOP_DYNAMIC_PARTICLES { + apply_particle_forces(sim, p, pa->state.time, cfra); + /* in fluids forces only effect velocity */ + copy_v3_v3(pa->state.co, pa->prev_state.co); + } + + /* actual fluids calculations (not threadsafe!) */ + LOOP_DYNAMIC_PARTICLES { + apply_particle_fluidsim(sim->ob, psys, pa, pa->state.time*timestep, gravity, springhash); } - if(pa->alive == PARS_DYING){ - //push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state); + /* Apply springs to particles */ + apply_fluid_springs(psys, timestep); + + /* apply velocity, collisions and rotation */ + LOOP_DYNAMIC_PARTICLES { + /* velocity holds forces and viscosity, so apply them before collisions */ + madd_v3_v3fl(pa->state.co, pa->state.vel, pa->state.time*timestep); + + /* calculate new velocity based on new-old location */ + sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co); + mul_v3_fl(pa->state.vel, 1.f/(pa->state.time*timestep)); - pa->alive=PARS_DEAD; - pa->state.time=pa->dietime; + if(sim->colliders) + deflect_particle(sim, p, pa->state.time, cfra); + + /* SPH particles are not physical particles, just interpolation particles, thus rotation has not a direct sense for them */ + rotate_particle(part, pa, pa->state.time, timestep); } - else - pa->state.time=cfra; - //push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state); + if(springhash) { + BLI_edgehash_free(springhash, NULL); + springhash = NULL; + } + break; } } + /* finalize particle state and time after dynamics */ + LOOP_DYNAMIC_PARTICLES { + if(pa->alive == PARS_DYING){ + pa->alive=PARS_DEAD; + pa->state.time=pa->dietime; + } + else + pa->state.time=cfra; + } + free_collider_cache(&sim->colliders); } static void update_children(ParticleSimulationData *sim) @@ -3504,8 +3594,12 @@ static void update_children(ParticleSimulationData *sim) if((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0) /* don't generate children while growing hair - waste of time */ psys_free_children(sim->psys); - else if(sim->psys->part->childtype && sim->psys->totchild != get_psys_tot_child(sim->scene, sim->psys)) - distribute_particles(sim, PART_FROM_CHILD); + else if(sim->psys->part->childtype) { + if(sim->psys->totchild != get_psys_tot_child(sim->scene, sim->psys)) + distribute_particles(sim, PART_FROM_CHILD); + else + ; /* Children are up to date, nothing to do. */ + } else psys_free_children(sim->psys); } @@ -3514,8 +3608,9 @@ static void cached_step(ParticleSimulationData *sim, float cfra) { ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; + ParticleTexture ptex; PARTICLE_P; - float disp, birthtime, dietime; + float disp, dietime; BLI_srandom(psys->seed); @@ -3524,13 +3619,13 @@ static void cached_step(ParticleSimulationData *sim, float cfra) disp= (float)psys_get_current_display_percentage(psys)/100.0f; LOOP_PARTICLES { - pa->size = part->size; + psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); + pa->size = part->size*ptex.size; if(part->randsize > 0.0) pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); psys->lattice= psys_get_lattice(sim); - birthtime = pa->time; dietime = pa->dietime; /* update alive status and push events */ @@ -3556,7 +3651,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra) } } -static void particles_fluid_step(ParticleSimulationData *sim, int cfra) +static void particles_fluid_step(ParticleSimulationData *sim, int UNUSED(cfra)) { ParticleSystem *psys = sim->psys; if(psys->particles){ @@ -3573,26 +3668,23 @@ static void particles_fluid_step(ParticleSimulationData *sim, int cfra) if( fluidmd && fluidmd->fss) { FluidsimSettings *fss= fluidmd->fss; ParticleSettings *part = psys->part; - ParticleData *pa=0; - char *suffix = "fluidsurface_particles_####"; - char *suffix2 = ".gz"; + ParticleData *pa=NULL; char filename[256]; char debugStrBuffer[256]; int curFrame = sim->scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading - int p, j, numFileParts, totpart; + int p, j, totpart; int readMask, activeParts = 0, fileParts = 0; gzFile gzf; // XXX if(ob==G.obedit) // off... // return; - + // ok, start loading - strcpy(filename, fss->surfdataPath); - strcat(filename, suffix); - BLI_path_abs(filename, G.sce); + BLI_snprintf(filename, sizeof(filename), "%sfluidsurface_particles_####.gz", fss->surfdataPath); + + BLI_path_abs(filename, G.main->name); BLI_path_frame(filename, curFrame, 0); // fixed #frame-no - strcat(filename, suffix2); - + gzf = gzopen(filename, "rb"); if (!gzf) { snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename); @@ -3601,16 +3693,14 @@ static void particles_fluid_step(ParticleSimulationData *sim, int cfra) } gzread(gzf, &totpart, sizeof(totpart)); - numFileParts = totpart; totpart = (G.rendering)?totpart:(part->disp*totpart)/100; part->totpart= totpart; part->sta=part->end = 1.0f; part->lifetime = sim->scene->r.efra + 1; - /* initialize particles */ + /* allocate particles */ realloc_particles(sim, part->totpart); - initialize_all_particles(sim); // set up reading mask readMask = fss->typeFlags; @@ -3642,6 +3732,9 @@ static void particles_fluid_step(ParticleSimulationData *sim, int cfra) pa->state.rot[0] = 1.0; pa->state.rot[1] = pa->state.rot[2] = pa->state.rot[3] = 0.0; + pa->time = 1.f; + pa->dietime = sim->scene->r.efra + 1; + pa->lifetime = sim->scene->r.efra; pa->alive = PARS_ALIVE; //if(a<25) fprintf(stderr,"FSPARTICLE debug set %s , a%d = %f,%f,%f , life=%f \n", filename, a, pa->co[0],pa->co[1],pa->co[2], pa->lifetime ); } else { @@ -3664,19 +3757,11 @@ static void particles_fluid_step(ParticleSimulationData *sim, int cfra) #endif // DISABLE_ELBEEM } -static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float cfra) +static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float UNUSED(cfra)) { ParticleSystem *psys = sim->psys; - ParticleSettings *part = psys->part; int oldtotpart = psys->totpart; - int totpart = oldtotpart; - - if(pid && psys->pointcache->flag & PTCACHE_EXTERNAL) - totpart = pid->cache->totpoint; - else if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT) - totpart = part->grid_res*part->grid_res*part->grid_res; - else - totpart = psys->part->totpart; + int totpart = tot_particles(psys, pid); if(totpart != oldtotpart) realloc_particles(sim, totpart); @@ -3694,94 +3779,84 @@ static void system_step(ParticleSimulationData *sim, float cfra) ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; PointCache *cache = psys->pointcache; - PTCacheID pid, *use_cache = NULL; + PTCacheID ptcacheid, *pid = NULL; PARTICLE_P; - int oldtotpart; - float disp; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */ - int init= 0, emit= 0; //, only_children_changed= 0; - int framenr, framedelta, startframe = 0, endframe = 100; - - framenr= (int)sim->scene->r.cfra; - framedelta= framenr - cache->simframe; + float disp, cache_cfra = cfra; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */ + int startframe = 0, endframe = 100, oldtotpart = 0; /* cache shouldn't be used for hair or "continue physics" */ if(part->type != PART_HAIR && BKE_ptcache_get_continue_physics() == 0) { - BKE_ptcache_id_from_particles(&pid, sim->ob, psys); - use_cache = &pid; - } - - if(use_cache) { - psys_clear_temp_pointcache(sim->psys); + psys_clear_temp_pointcache(psys); /* set suitable cache range automatically */ if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0) - psys_get_pointcache_start_end(sim->scene, sim->psys, &cache->startframe, &cache->endframe); - - BKE_ptcache_id_time(&pid, sim->scene, 0.0f, &startframe, &endframe, NULL); + psys_get_pointcache_start_end(sim->scene, psys, &cache->startframe, &cache->endframe); - /* simulation is only active during a specific period */ - if(framenr < startframe) { - psys_reset(psys, PSYS_RESET_CACHE_MISS); - return; - } - else if(framenr > endframe) { - framenr= endframe; - } + pid = &ptcacheid; + BKE_ptcache_id_from_particles(pid, sim->ob, psys); - if(framenr == startframe) { - BKE_ptcache_id_reset(sim->scene, use_cache, PTCACHE_RESET_OUTDATED); - BKE_ptcache_validate(cache, framenr); + BKE_ptcache_id_time(pid, sim->scene, 0.0f, &startframe, &endframe, NULL); + + /* clear everythin on start frame */ + if((int)cfra == startframe) { + BKE_ptcache_id_reset(sim->scene, pid, PTCACHE_RESET_OUTDATED); + BKE_ptcache_validate(cache, startframe); cache->flag &= ~PTCACHE_REDO_NEEDED; } + + CLAMP(cache_cfra, startframe, endframe); } -/* 1. emit particles */ - - /* verify if we need to reallocate */ +/* 1. emit particles and redo particles if needed */ oldtotpart = psys->totpart; - - emit = emit_particles(sim, use_cache, cfra); - if(use_cache && emit > 0) - BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, cfra); - init = emit*emit + (psys->recalc & PSYS_RECALC_RESET); - - if(init) { + if(emit_particles(sim, pid, cfra) || psys->recalc & PSYS_RECALC_RESET) { distribute_particles(sim, part->from); initialize_all_particles(sim); + /* reset only just created particles (on startframe all particles are recreated) */ reset_all_particles(sim, 0.0, cfra, oldtotpart); + if (psys->fluid_springs) { + MEM_freeN(psys->fluid_springs); + psys->fluid_springs = NULL; + } + + psys->tot_fluidsprings = psys->alloc_fluidsprings = 0; + /* flag for possible explode modifiers after this system */ sim->psmd->flag |= eParticleSystemFlag_Pars; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra); } /* 2. try to read from the cache */ - if(use_cache) { - int cache_result = BKE_ptcache_read_cache(use_cache, cfra, sim->scene->r.frs_sec); + if(pid) { + int cache_result = BKE_ptcache_read(pid, cache_cfra); if(ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) { cached_step(sim, cfra); update_children(sim); psys_update_path_cache(sim, cfra); - BKE_ptcache_validate(cache, framenr); + BKE_ptcache_validate(cache, (int)cache_cfra); if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) - BKE_ptcache_write_cache(use_cache, framenr); + BKE_ptcache_write(pid, (int)cache_cfra); return; } + /* Cache is supposed to be baked, but no data was found so bail out */ + else if(cache->flag & PTCACHE_BAKED) { + psys_reset(psys, PSYS_RESET_CACHE_MISS); + return; + } else if(cache_result == PTCACHE_READ_OLD) { psys->cfra = (float)cache->simframe; cached_step(sim, psys->cfra); } - else if(cfra != startframe && ( /*sim->ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED))) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */ - psys_reset(psys, PSYS_RESET_CACHE_MISS); - return; - } /* if on second frame, write cache for first frame */ if(psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - BKE_ptcache_write_cache(use_cache, startframe); + BKE_ptcache_write(pid, startframe); } else BKE_ptcache_invalidate(cache); @@ -3804,7 +3879,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) /* handle negative frame start at the first frame by doing * all the steps before the first frame */ - if(framenr == startframe && part->sta < startframe) + if((int)cfra == startframe && part->sta < startframe) totframesback = (startframe - (int)part->sta); for(dframe=-totframesback; dframe<=0; dframe++) { @@ -3819,14 +3894,13 @@ static void system_step(ParticleSimulationData *sim, float cfra) } /* 4. only write cache starting from second frame */ - if(use_cache) { - BKE_ptcache_validate(cache, framenr); - if(framenr != startframe) - BKE_ptcache_write_cache(use_cache, framenr); + if(pid) { + BKE_ptcache_validate(cache, (int)cache_cfra); + if((int)cache_cfra != startframe) + BKE_ptcache_write(pid, (int)cache_cfra); } - if(init) - update_children(sim); + update_children(sim); /* cleanup */ if(psys->lattice){ @@ -3904,6 +3978,8 @@ static void fluid_default_settings(ParticleSettings *part){ fluid->radius = 0.5f; fluid->spring_k = 0.f; + fluid->plasticity_constant = 0.1f; + fluid->yield_ratio = 0.1f; fluid->rest_length = 0.5f; fluid->viscosity_omega = 2.f; fluid->viscosity_beta = 0.f; @@ -3913,7 +3989,7 @@ static void fluid_default_settings(ParticleSettings *part){ fluid->buoyancy = 0.f; } -static void psys_changed_physics(ParticleSimulationData *sim) +static void psys_prepare_physics(ParticleSimulationData *sim) { ParticleSettings *part = sim->psys->part; @@ -3952,7 +4028,7 @@ static void psys_changed_physics(ParticleSimulationData *sim) static int hair_needs_recalc(ParticleSystem *psys) { if(!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) && - ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET)) { + ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET || (psys->part->flag & PART_HAIR_REGROW && !psys->edit))) { return 1; } @@ -3963,7 +4039,7 @@ static int hair_needs_recalc(ParticleSystem *psys) * then advances in to actual particle calculations depending on particle type */ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) { - ParticleSimulationData sim = {scene, ob, psys, NULL, NULL}; + ParticleSimulationData sim= {0}; ParticleSettings *part = psys->part; float cfra; @@ -3974,6 +4050,10 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) return; cfra= BKE_curframe(scene); + + sim.scene= scene; + sim.ob= ob; + sim.psys= psys; sim.psmd= psys_get_modifier(ob, psys); /* system was already updated from modifier stack */ @@ -3992,19 +4072,34 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) if(psys->recalc & PSYS_RECALC_TYPE) psys_changed_type(&sim); - else if(psys->recalc & PSYS_RECALC_PHYS) - psys_changed_physics(&sim); + + if(psys->recalc & PSYS_RECALC_RESET) + psys->totunexist = 0; + + /* setup necessary physics type dependent additional data if it doesn't yet exist */ + psys_prepare_physics(&sim); switch(part->type) { case PART_HAIR: { + /* nothing to do so bail out early */ + if(psys->totpart == 0 && part->totpart == 0) { + psys_free_path_cache(psys, NULL); + free_hair(ob, psys, 0); + } /* (re-)create hair */ - if(hair_needs_recalc(psys)) { + else if(hair_needs_recalc(psys)) { float hcfra=0.0f; int i, recalc = psys->recalc; free_hair(ob, psys, 0); + if(psys->edit && psys->free_edit) { + psys->free_edit(psys->edit); + psys->edit = NULL; + psys->free_edit = NULL; + } + /* first step is negative so particles get killed and reset */ psys->cfra= 1.0f; @@ -4020,6 +4115,8 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) psys->flag |= PSYS_HAIR_DONE; psys->recalc = recalc; } + else if(psys->flag & PSYS_EDITED) + psys->flag |= PSYS_HAIR_DONE; if(psys->flag & PSYS_HAIR_DONE) hair_step(&sim, cfra); @@ -4037,12 +4134,13 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) case PART_PHYS_KEYED: { PARTICLE_P; + float disp = (float)psys_get_current_display_percentage(psys)/100.0f; /* Particles without dynamics haven't been reset yet because they don't use pointcache */ if(psys->recalc & PSYS_RECALC_RESET) psys_reset(psys, PSYS_RESET_ALL); - if(emit_particles(&sim, NULL, cfra)) { + if(emit_particles(&sim, NULL, cfra) || (psys->recalc & PSYS_RECALC_RESET)) { free_keyed_keys(psys); distribute_particles(&sim, part->from); initialize_all_particles(&sim); @@ -4054,6 +4152,11 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); reset_particle(&sim, pa, 0.0, cfra); + + if(PSYS_FRAND(p) > disp) + pa->flag |= PARS_NO_DISP; + else + pa->flag &= ~PARS_NO_DISP; } if(part->phystype == PART_PHYS_KEYED) { @@ -4077,7 +4180,8 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) psys->cfra = cfra; psys->recalc = 0; - /* save matrix for duplicators */ - invert_m4_m4(psys->imat, ob->obmat); + /* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */ + if(psys->renderdata==0) + invert_m4_m4(psys->imat, ob->obmat); } diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index a35e40d7cf7..6ea14606660 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1,4 +1,5 @@ -/** +/* + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -19,7 +20,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * -* Contributor(s): Campbell Barton <ideasman42@gmail.com> + * Contributor(s): Campbell Barton <ideasman42@gmail.com> * * ***** END GPL LICENSE BLOCK ***** */ @@ -44,6 +45,7 @@ #include "BLI_blenlib.h" #include "BLI_threads.h" #include "BLI_math.h" +#include "BLI_utildefines.h" #include "PIL_time.h" @@ -63,6 +65,7 @@ #include "BKE_smoke.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" + #include "BIK_api.h" /* both in intern */ @@ -95,44 +98,55 @@ /* could be made into a pointcache option */ #define DURIAN_POINTCACHE_LIB_OK 1 -int ptcache_data_size[] = { - sizeof(int), // BPHYS_DATA_INDEX - 3 * sizeof(float), // BPHYS_DATA_LOCATION: - 3 * sizeof(float), // BPHYS_DATA_VELOCITY: - 4 * sizeof(float), // BPHYS_DATA_ROTATION: - 3 * sizeof(float), // BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */ - sizeof(float), // BPHYS_DATA_SIZE: - 3 * sizeof(float), // BPHYS_DATA_TIMES: - sizeof(BoidData) // case BPHYS_DATA_BOIDS: +static int ptcache_data_size[] = { + sizeof(unsigned int), // BPHYS_DATA_INDEX + 3 * sizeof(float), // BPHYS_DATA_LOCATION + 3 * sizeof(float), // BPHYS_DATA_VELOCITY + 4 * sizeof(float), // BPHYS_DATA_ROTATION + 3 * sizeof(float), // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST + sizeof(float), // BPHYS_DATA_SIZE + 3 * sizeof(float), // BPHYS_DATA_TIMES + sizeof(BoidData) // case BPHYS_DATA_BOIDS +}; + +static int ptcache_extra_datasize[] = { + 0, + sizeof(ParticleSpring) }; +/* forward declerations */ +static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len); +static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode); +static int ptcache_file_write(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size); +static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size); + /* Common functions */ -static int ptcache_read_basic_header(PTCacheFile *pf) +static int ptcache_basic_header_read(PTCacheFile *pf) { int error=0; /* Custom functions should read these basic elements too! */ - if(!error && !fread(&pf->totpoint, sizeof(int), 1, pf->fp)) + if(!error && !fread(&pf->totpoint, sizeof(unsigned int), 1, pf->fp)) error = 1; - if(!error && !fread(&pf->data_types, sizeof(int), 1, pf->fp)) + if(!error && !fread(&pf->data_types, sizeof(unsigned int), 1, pf->fp)) error = 1; return !error; } -static int ptcache_write_basic_header(PTCacheFile *pf) +static int ptcache_basic_header_write(PTCacheFile *pf) { /* Custom functions should write these basic elements too! */ - if(!fwrite(&pf->totpoint, sizeof(int), 1, pf->fp)) + if(!fwrite(&pf->totpoint, sizeof(unsigned int), 1, pf->fp)) return 0; - if(!fwrite(&pf->data_types, sizeof(int), 1, pf->fp)) + if(!fwrite(&pf->data_types, sizeof(unsigned int), 1, pf->fp)) return 0; return 1; } /* Softbody functions */ -static int ptcache_write_softbody(int index, void *soft_v, void **data, int cfra) +static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra)) { SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; @@ -142,7 +156,7 @@ static int ptcache_write_softbody(int index, void *soft_v, void **data, int cfra return 1; } -static void ptcache_read_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float *old_data) +static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data) { SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; @@ -156,7 +170,7 @@ static void ptcache_read_softbody(int index, void *soft_v, void **data, float fr PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec); } } -static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) { SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; @@ -188,24 +202,44 @@ static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, f VECCOPY(bp->pos, keys->co); VECCOPY(bp->vec, keys->vel); } -static int ptcache_totpoint_softbody(void *soft_v, int cfra) +static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra)) { SoftBody *soft= soft_v; return soft->totpoint; } /* Particle functions */ -static int ptcache_write_particle(int index, void *psys_v, void **data, int cfra) +void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time) +{ + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co); + PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel); + + /* no rotation info, so make something nice up */ + if(data[BPHYS_DATA_ROTATION]==NULL) { + vec_to_quat( key->rot, key->vel, OB_NEGX, OB_POSZ); + } + else { + PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot); + } + + PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave); + key->time = time; +} +static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra) { ParticleSystem *psys= psys_v; ParticleData *pa = psys->particles + index; BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; - float times[3] = {pa->time, pa->dietime, pa->lifetime}; + float times[3]; int step = psys->pointcache->step; /* No need to store unborn or died particles outside cache step bounds */ if(data[BPHYS_DATA_INDEX] && (cfra < pa->time - step || cfra > pa->dietime + step)) return 0; - + + times[0]= pa->time; + times[1]= pa->dietime; + times[2]= pa->lifetime; + PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index); PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co); PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel); @@ -220,19 +254,12 @@ static int ptcache_write_particle(int index, void *psys_v, void **data, int cfra /* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */ return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time); } -void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time) -{ - PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co); - PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel); - PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot); - PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave); - key->time = time; -} -static void ptcache_read_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) +static void ptcache_particle_read(int index, void *psys_v, void **data, float cfra, float *old_data) { ParticleSystem *psys= psys_v; ParticleData *pa; BoidParticle *boid; + float timestep = 0.04f*psys->part->timetweak; if(index >= psys->totpart) return; @@ -254,6 +281,8 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr /* set frames cached before birth to birth time */ if(cfra < pa->time) pa->state.time = pa->time; + else if(cfra > pa->dietime) + pa->state.time = pa->dietime; if(data[BPHYS_DATA_SIZE]) PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); @@ -273,11 +302,11 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { if(cfra > pa->prev_state.time) { sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co); - mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec); + mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep); } else { sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co); - mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec); + mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep); } } @@ -286,12 +315,12 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr vec_to_quat( pa->state.rot,pa->state.vel, OB_NEGX, OB_POSZ); } } -static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) { ParticleSystem *psys= psys_v; ParticleData *pa; ParticleKey keys[4]; - float dfra; + float dfra, timestep = 0.04f*psys->part->timetweak; if(index >= psys->totpart) return; @@ -319,11 +348,11 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { if(keys[1].time > keys[2].time) { sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co); - mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) / frs_sec); + mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep); } else { sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co); - mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) / frs_sec); + mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep); } } @@ -337,163 +366,81 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f dfra = cfra2 - cfra1; - mul_v3_fl(keys[1].vel, dfra / frs_sec); - mul_v3_fl(keys[2].vel, dfra / frs_sec); + mul_v3_fl(keys[1].vel, dfra * timestep); + mul_v3_fl(keys[2].vel, dfra * timestep); psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); - mul_v3_fl(pa->state.vel, frs_sec / dfra); + mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep)); pa->state.time = cfra; } -static int ptcache_totpoint_particle(void *psys_v, int cfra) +static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra)) { ParticleSystem *psys = psys_v; return psys->totpart; } -static int ptcache_totwrite_particle(void *psys_v, int cfra) +static int ptcache_particle_totwrite(void *psys_v, int cfra) { ParticleSystem *psys = psys_v; ParticleData *pa= psys->particles; int p, step = psys->pointcache->step; int totwrite = 0; + if(cfra == 0) + return psys->totpart; + for(p=0; p<psys->totpart; p++,pa++) totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step); return totwrite; } -//static int ptcache_write_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v) -//{ -// ParticleSystem *psys= psys_v; -// ParticleData *pa = psys->particles; -// BoidParticle *boid = NULL; -// float times[3]; -// int i = 0; -// -// if(!pf && !pm) -// return 0; -// -// for(i=0; i<psys->totpart; i++, pa++) { -// -// if(data[BPHYS_DATA_INDEX]) { -// int step = psys->pointcache->step; -// /* No need to store unborn or died particles */ -// if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time) -// continue; -// } -// -// times[0] = pa->time; -// times[1] = pa->dietime; -// times[2] = pa->lifetime; -// -// PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index); -// PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co); -// PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel); -// PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot); -// PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave); -// PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size); -// PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times); -// -// boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; -// if(boid) -// PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); -// -// if(pf && !ptcache_file_write_data(pf)) -// return 0; -// -// if(pm) -// BKE_ptcache_mem_incr_pointers(pm); -// } -// -// return 1; -//} -//static void ptcache_read_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) -//{ -// ParticleSystem *psys= psys_v; -// ParticleData *pa = psys->particles + index; -// BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; -// -// if(cfra > pa->state.time) -// memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey)); -// -// if(old_data){ -// /* old format cache */ -// memcpy(&pa->state, old_data, sizeof(ParticleKey)); -// return; -// } -// -// BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); -// -// if(data[BPHYS_DATA_SIZE]) -// PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); -// -// if(data[BPHYS_DATA_TIMES]) { -// float times[3]; -// PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×); -// pa->time = times[0]; -// pa->dietime = times[1]; -// pa->lifetime = times[2]; -// } -// -// if(boid) -// PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); -// -// /* determine velocity from previous location */ -// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { -// if(cfra > pa->prev_state.time) { -// sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co); -// mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec); -// } -// else { -// sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co); -// mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec); -// } -// } -// -// /* determine rotation from velocity */ -// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { -// vec_to_quat( pa->state.rot,pa->state.vel, OB_POSX, OB_POSZ); -// } -//} -//static void ptcache_interpolate_particle_stream(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) -//{ -// ParticleSystem *psys= psys_v; -// ParticleData *pa = psys->particles + index; -// ParticleKey keys[4]; -// float dfra; -// -// cfra = MIN2(cfra, pa->dietime); -// cfra1 = MIN2(cfra1, pa->dietime); -// cfra2 = MIN2(cfra2, pa->dietime); -// -// if(cfra1 == cfra2) -// return; -// -// memcpy(keys+1, &pa->state, sizeof(ParticleKey)); -// if(old_data) -// memcpy(keys+2, old_data, sizeof(ParticleKey)); -// else -// BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); -// -// dfra = cfra2 - cfra1; -// -// mul_v3_fl(keys[1].vel, dfra / frs_sec); -// mul_v3_fl(keys[2].vel, dfra / frs_sec); -// -// psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); -// interp_qt_qtqt(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra); -// -// mul_v3_fl(pa->state.vel, frs_sec / dfra); -// -// pa->state.time = cfra; -//} -// +static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra)) +{ + ParticleSystem *psys = psys_v; + PTCacheExtra *extra = NULL; + + if(psys->part->phystype == PART_PHYS_FLUID && + psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS && + psys->tot_fluidsprings && psys->fluid_springs) { + + extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: fluid extra data"); + + extra->type = BPHYS_EXTRA_FLUID_SPRINGS; + extra->totdata = psys->tot_fluidsprings; + + extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Point cache: extra data"); + memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]); + + BLI_addtail(&pm->extradata, extra); + } +} + +static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra)) +{ + ParticleSystem *psys = psys_v; + PTCacheExtra *extra = pm->extradata.first; + + for(; extra; extra=extra->next) { + switch(extra->type) { + case BPHYS_EXTRA_FLUID_SPRINGS: + { + if(psys->fluid_springs) + MEM_freeN(psys->fluid_springs); + + psys->fluid_springs = MEM_dupallocN(extra->data); + psys->tot_fluidsprings = psys->alloc_fluidsprings = extra->totdata; + break; + } + } + } +} + /* Cloth functions */ -static int ptcache_write_cloth(int index, void *cloth_v, void **data, int cfra) +static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra)) { ClothModifierData *clmd= cloth_v; Cloth *cloth= clmd->clothObject; @@ -505,7 +452,7 @@ static int ptcache_write_cloth(int index, void *cloth_v, void **data, int cfra) return 1; } -static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float *old_data) +static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data) { ClothModifierData *clmd= cloth_v; Cloth *cloth= clmd->clothObject; @@ -522,7 +469,7 @@ static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_ PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst); } } -static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) { ClothModifierData *clmd= cloth_v; Cloth *cloth= clmd->clothObject; @@ -558,84 +505,14 @@ static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, flo /* should vert->xconst be interpolated somehow too? - jahka */ } -static int ptcache_totpoint_cloth(void *cloth_v, int cfra) +static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra)) { ClothModifierData *clmd= cloth_v; return clmd->clothObject ? clmd->clothObject->numverts : 0; } -/* Creating ID's */ -void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) -{ - memset(pid, 0, sizeof(PTCacheID)); - - pid->ob= ob; - pid->calldata= sb; - pid->type= PTCACHE_TYPE_SOFTBODY; - pid->cache= sb->pointcache; - pid->cache_ptr= &sb->pointcache; - pid->ptcaches= &sb->ptcaches; - pid->totpoint= pid->totwrite= ptcache_totpoint_softbody; - - pid->write_elem= ptcache_write_softbody; - pid->write_stream = NULL; - pid->read_stream = NULL; - pid->read_elem= ptcache_read_softbody; - pid->interpolate_elem= ptcache_interpolate_softbody; - - pid->write_header= ptcache_write_basic_header; - pid->read_header= ptcache_read_basic_header; - - pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY); - pid->info_types= 0; - - pid->stack_index = pid->cache->index; -} - -void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys) -{ - memset(pid, 0, sizeof(PTCacheID)); - - pid->ob= ob; - pid->calldata= psys; - pid->type= PTCACHE_TYPE_PARTICLES; - pid->stack_index= psys->pointcache->index; - pid->cache= psys->pointcache; - pid->cache_ptr= &psys->pointcache; - pid->ptcaches= &psys->ptcaches; - - if(psys->part->type != PART_HAIR) - pid->flag |= PTCACHE_VEL_PER_SEC; - - pid->write_elem= ptcache_write_particle; - pid->write_stream = NULL; - pid->read_stream = NULL; - pid->read_elem= ptcache_read_particle; - pid->interpolate_elem= ptcache_interpolate_particle; - - pid->totpoint= ptcache_totpoint_particle; - pid->totwrite= ptcache_totwrite_particle; - - pid->write_header= ptcache_write_basic_header; - pid->read_header= ptcache_read_basic_header; - - pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX); - - if(psys->part->phystype == PART_PHYS_BOIDS) - pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS); - - if(psys->part->rotmode!=PART_ROT_VEL - || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f) - pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION); - - if(psys->part->flag & PART_ROT_DYN) - pid->data_types|= (1<<BPHYS_DATA_ROTATION); - - pid->info_types= (1<<BPHYS_DATA_TIMES); -} - /* Smoke functions */ -static int ptcache_totpoint_smoke(void *smoke_v, int cfra) +static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra)) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; @@ -646,79 +523,11 @@ static int ptcache_totpoint_smoke(void *smoke_v, int cfra) else return 0; } - -/* Smoke functions */ -static int ptcache_totpoint_smoke_turbulence(void *smoke_v, int cfra) -{ - SmokeModifierData *smd= (SmokeModifierData *)smoke_v; - SmokeDomainSettings *sds = smd->domain; - - if(sds->wt) { - return sds->res_wt[0]*sds->res_wt[1]*sds->res_wt[2]; - } - else - return 0; -} - -// forward decleration -static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size); - -static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode) -{ - int r = 0; - unsigned char compressed = 0; - unsigned int out_len= 0; - unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); - size_t sizeOfIt = 5; - -#ifdef WITH_LZO - out_len= LZO_OUT_LEN(in_len); - if(mode == 1) { - LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); - - r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); - if (!(r == LZO_E_OK) || (out_len >= in_len)) - compressed = 0; - else - compressed = 1; - } -#endif -#ifdef WITH_LZMA - if(mode == 2) { - - r = LzmaCompress(out, (size_t *)&out_len, in, in_len,//assume sizeof(char)==1.... - props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); - - if(!(r == SZ_OK) || (out_len >= in_len)) - compressed = 0; - else - compressed = 2; - } -#endif - - ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); - if(compressed) { - ptcache_file_write(pf, &out_len, 1, sizeof(unsigned int)); - ptcache_file_write(pf, out, out_len, sizeof(unsigned char)); - } - else - ptcache_file_write(pf, in, in_len, sizeof(unsigned char)); - - if(compressed == 2) - { - ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int)); - ptcache_file_write(pf, props, sizeOfIt, sizeof(unsigned char)); - } - - MEM_freeN(props); - - return r; -} - -static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v) +static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; + int ret = 0; if(sds->fluid) { size_t res = sds->res[0]*sds->res[1]*sds->res[2]; @@ -732,33 +541,26 @@ static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v) smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); - ptcache_compress_write(pf, (unsigned char *)sds->shadow, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)dens, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)densold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)heat, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)heatold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vx, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vy, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vz, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vxold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vyold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vzold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vxold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vyold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vzold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode); ptcache_file_write(pf, &dt, 1, sizeof(float)); ptcache_file_write(pf, &dx, 1, sizeof(float)); MEM_freeN(out); - return 1; + ret = 1; } - return 0; -} -static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v) -{ - SmokeModifierData *smd= (SmokeModifierData *)smoke_v; - SmokeDomainSettings *sds = smd->domain; - if(sds->wt) { int res_big_array[3]; int res_big; @@ -780,71 +582,22 @@ static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v) smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer"); - ptcache_compress_write(pf, (unsigned char *)dens, in_len_big, out, mode); - ptcache_compress_write(pf, (unsigned char *)densold, in_len_big, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len_big, out, mode); MEM_freeN(out); out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer"); - ptcache_compress_write(pf, (unsigned char *)tcu, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)tcv, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)tcw, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)tcu, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)tcv, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)tcw, in_len, out, mode); MEM_freeN(out); - return 1; + ret = 1; } - return 0; -} -// forward decleration -static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size); - -static int ptcache_compress_read(PTCacheFile *pf, unsigned char *result, unsigned int len) -{ - int r = 0; - unsigned char compressed = 0; - unsigned int in_len; -#ifdef WITH_LZO - unsigned int out_len = len; - size_t sizeOfIt = 5; -#endif - unsigned char *in; - unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); - - ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char)); - if(compressed) { - ptcache_file_read(pf, &in_len, 1, sizeof(unsigned int)); - if(in_len==0) { - /* do nothing */ - } - else { - in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); - ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); -#ifdef WITH_LZO - if(compressed == 1) - r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); -#endif -#ifdef WITH_LZMA - if(compressed == 2) - { - size_t leni = in_len, leno = out_len; - ptcache_file_read(pf, &sizeOfIt, 1, sizeof(unsigned int)); - ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); - r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); - } -#endif - MEM_freeN(in); - } - } - else { - ptcache_file_read(pf, result, len, sizeof(unsigned char)); - } - - MEM_freeN(props); - - return r; + return ret; } - -static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v) +static void ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; @@ -857,116 +610,126 @@ static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v) smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); - ptcache_compress_read(pf, (unsigned char *)sds->shadow, out_len); - ptcache_compress_read(pf, (unsigned char*)dens, out_len); - ptcache_compress_read(pf, (unsigned char*)densold, out_len); - ptcache_compress_read(pf, (unsigned char*)heat, out_len); - ptcache_compress_read(pf, (unsigned char*)heatold, out_len); - ptcache_compress_read(pf, (unsigned char*)vx, out_len); - ptcache_compress_read(pf, (unsigned char*)vy, out_len); - ptcache_compress_read(pf, (unsigned char*)vz, out_len); - ptcache_compress_read(pf, (unsigned char*)vxold, out_len); - ptcache_compress_read(pf, (unsigned char*)vyold, out_len); - ptcache_compress_read(pf, (unsigned char*)vzold, out_len); - ptcache_compress_read(pf, (unsigned char*)obstacles, (unsigned int)res); + ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vxold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vyold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vzold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res); ptcache_file_read(pf, &dt, 1, sizeof(float)); ptcache_file_read(pf, &dx, 1, sizeof(float)); - } -} -static void ptcache_read_smoke_turbulence(PTCacheFile *pf, void *smoke_v) -{ - SmokeModifierData *smd= (SmokeModifierData *)smoke_v; - SmokeDomainSettings *sds = smd->domain; - - if(sds->fluid) { - int res = sds->res[0]*sds->res[1]*sds->res[2]; - int res_big, res_big_array[3]; - float *dens, *densold, *tcu, *tcv, *tcw; - unsigned int out_len = sizeof(float)*(unsigned int)res; - unsigned int out_len_big; + if(pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) { + int res = sds->res[0]*sds->res[1]*sds->res[2]; + int res_big, res_big_array[3]; + float *dens, *densold, *tcu, *tcv, *tcw; + unsigned int out_len = sizeof(float)*(unsigned int)res; + unsigned int out_len_big; - smoke_turbulence_get_res(sds->wt, res_big_array); - res_big = res_big_array[0]*res_big_array[1]*res_big_array[2]; - out_len_big = sizeof(float) * (unsigned int)res_big; + smoke_turbulence_get_res(sds->wt, res_big_array); + res_big = res_big_array[0]*res_big_array[1]*res_big_array[2]; + out_len_big = sizeof(float) * (unsigned int)res_big; - smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); + smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); - ptcache_compress_read(pf, (unsigned char*)dens, out_len_big); - ptcache_compress_read(pf, (unsigned char*)densold, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len_big); - ptcache_compress_read(pf, (unsigned char*)tcu, out_len); - ptcache_compress_read(pf, (unsigned char*)tcv, out_len); - ptcache_compress_read(pf, (unsigned char*)tcw, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len); + } } } -void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) +/* Creating ID's */ +void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) { - SmokeDomainSettings *sds = smd->domain; - memset(pid, 0, sizeof(PTCacheID)); pid->ob= ob; - pid->calldata= smd; - - pid->type= PTCACHE_TYPE_SMOKE_DOMAIN; - pid->stack_index= sds->point_cache[0]->index; - - pid->cache= sds->point_cache[0]; - pid->cache_ptr= &(sds->point_cache[0]); - pid->ptcaches= &(sds->ptcaches[0]); + pid->calldata= sb; + pid->type= PTCACHE_TYPE_SOFTBODY; + pid->cache= sb->pointcache; + pid->cache_ptr= &sb->pointcache; + pid->ptcaches= &sb->ptcaches; + pid->totpoint= pid->totwrite= ptcache_softbody_totpoint; - pid->totpoint= pid->totwrite= ptcache_totpoint_smoke; + pid->write_point = ptcache_softbody_write; + pid->read_point = ptcache_softbody_read; + pid->interpolate_point = ptcache_softbody_interpolate; - pid->write_elem= NULL; - pid->read_elem= NULL; + pid->write_stream = NULL; + pid->read_stream = NULL; - pid->read_stream = ptcache_read_smoke; - pid->write_stream = ptcache_write_smoke; - - pid->interpolate_elem= NULL; + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; - pid->write_header= ptcache_write_basic_header; - pid->read_header= ptcache_read_basic_header; + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; - pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values to make pointcache happy + pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY); pid->info_types= 0; -} -void BKE_ptcache_id_from_smoke_turbulence(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) + pid->stack_index = pid->cache->index; +} +void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys) { - SmokeDomainSettings *sds = smd->domain; - memset(pid, 0, sizeof(PTCacheID)); pid->ob= ob; - pid->calldata= smd; - - pid->type= PTCACHE_TYPE_SMOKE_HIGHRES; - pid->stack_index= sds->point_cache[1]->index; + pid->calldata= psys; + pid->type= PTCACHE_TYPE_PARTICLES; + pid->stack_index= psys->pointcache->index; + pid->cache= psys->pointcache; + pid->cache_ptr= &psys->pointcache; + pid->ptcaches= &psys->ptcaches; - pid->cache= sds->point_cache[1]; - pid->cache_ptr= &sds->point_cache[1]; - pid->ptcaches= &sds->ptcaches[1]; + if(psys->part->type != PART_HAIR) + pid->flag |= PTCACHE_VEL_PER_SEC; - pid->totpoint= pid->totwrite= ptcache_totpoint_smoke_turbulence; + pid->totpoint = ptcache_particle_totpoint; + pid->totwrite = ptcache_particle_totwrite; - pid->write_elem= NULL; - pid->read_elem= NULL; + pid->write_point = ptcache_particle_write; + pid->read_point = ptcache_particle_read; + pid->interpolate_point = ptcache_particle_interpolate; - pid->read_stream = ptcache_read_smoke_turbulence; - pid->write_stream = ptcache_write_smoke_turbulence; - - pid->interpolate_elem= NULL; + pid->write_stream = NULL; + pid->read_stream = NULL; - pid->write_header= ptcache_write_basic_header; - pid->read_header= ptcache_read_basic_header; + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; - pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values tot make pointcache happy - pid->info_types= 0; -} + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; + + pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX); + + if(psys->part->phystype == PART_PHYS_BOIDS) + pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS); + else if(psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) { + pid->write_extra_data = ptcache_particle_extra_write; + pid->read_extra_data = ptcache_particle_extra_read; + } + if(psys->part->rotmode!=PART_ROT_VEL + || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f) + pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION); + + if(psys->part->flag & PART_ROT_DYN) + pid->data_types|= (1<<BPHYS_DATA_ROTATION); + + pid->info_types= (1<<BPHYS_DATA_TIMES); +} void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd) { memset(pid, 0, sizeof(PTCacheID)); @@ -978,21 +741,65 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl pid->cache= clmd->point_cache; pid->cache_ptr= &clmd->point_cache; pid->ptcaches= &clmd->ptcaches; - pid->totpoint= pid->totwrite= ptcache_totpoint_cloth; + pid->totpoint= pid->totwrite= ptcache_cloth_totpoint; + + pid->write_point = ptcache_cloth_write; + pid->read_point = ptcache_cloth_read; + pid->interpolate_point = ptcache_cloth_interpolate; + + pid->write_stream = NULL; + pid->read_stream = NULL; - pid->write_elem= ptcache_write_cloth; - pid->write_stream = NULL; - pid->read_stream = NULL; - pid->read_elem= ptcache_read_cloth; - pid->interpolate_elem= ptcache_interpolate_cloth; + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; - pid->write_header= ptcache_write_basic_header; - pid->read_header= ptcache_read_basic_header; + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST); pid->info_types= 0; } +void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) +{ + SmokeDomainSettings *sds = smd->domain; + + memset(pid, 0, sizeof(PTCacheID)); + + pid->ob= ob; + pid->calldata= smd; + + pid->type= PTCACHE_TYPE_SMOKE_DOMAIN; + pid->stack_index= sds->point_cache[0]->index; + + pid->cache= sds->point_cache[0]; + pid->cache_ptr= &(sds->point_cache[0]); + pid->ptcaches= &(sds->ptcaches[0]); + + pid->totpoint= pid->totwrite= ptcache_smoke_totpoint; + pid->write_point = NULL; + pid->read_point = NULL; + pid->interpolate_point = NULL; + + pid->read_stream = ptcache_smoke_read; + pid->write_stream = ptcache_smoke_write; + + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; + + pid->data_types= 0; + pid->info_types= 0; + + if(sds->fluid) + pid->data_types |= (1<<BPHYS_DATA_SMOKE_LOW); + if(sds->wt) + pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH); +} void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis) { PTCacheID *pid; @@ -1008,11 +815,23 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - if(psys->part) { - pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); - BKE_ptcache_id_from_particles(pid, ob, psys); - BLI_addtail(lb, pid); - } + if(psys->part==NULL) + continue; + + /* check to make sure point cache is actually used by the particles */ + if(ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) + continue; + + /* hair needs to be included in id-list for cache edit mode to work */ + /* if(psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) */ + /* continue; */ + + if(psys->part->type == PART_FLUID) + continue; + + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_particles(pid, ob, psys); + BLI_addtail(lb, pid); } for(md=ob->modifiers.first; md; md=md->next) { @@ -1028,10 +847,6 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md); BLI_addtail(lb, pid); - - pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); - BKE_ptcache_id_from_smoke_turbulence(pid, ob, (SmokeModifierData*)md); - BLI_addtail(lb, pid); } } } @@ -1045,7 +860,7 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup if(dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */ ListBase lb_dupli_pid; BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis); - addlisttolist(lb, &lb_dupli_pid); + BLI_movelisttolist(lb, &lb_dupli_pid); if(lb_dupli_pid.first) printf("Adding Dupli\n"); } @@ -1056,7 +871,6 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup } } - /* File handling */ /* Takes an Object ID and returns a unique name @@ -1070,8 +884,8 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup static int ptcache_path(PTCacheID *pid, char *filename) { - Library *lib= (pid)? pid->ob->id.lib: NULL; - const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.sce; + Library *lib= (pid->ob)? pid->ob->id.lib: NULL; + const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.main->name; size_t i; if(pid->cache->flag & PTCACHE_EXTERNAL) { @@ -1104,7 +918,7 @@ static int ptcache_path(PTCacheID *pid, char *filename) return BLI_add_slash(filename); /* new strlen() */ } -static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext) +static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext) { int len=0; char *idname; @@ -1169,7 +983,7 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) #endif if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */ - BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); + ptcache_filename(pid, filename, cfra, 1, 1); if (mode==PTCACHE_FILE_READ) { if (!BLI_exists(filename)) { @@ -1189,48 +1003,155 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile"); pf->fp= fp; + pf->old_format = 0; + pf->frame = cfra; return pf; } - static void ptcache_file_close(PTCacheFile *pf) { - fclose(pf->fp); - MEM_freeN(pf); + if(pf) { + fclose(pf->fp); + MEM_freeN(pf); + } +} + +static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len) +{ + int r = 0; + unsigned char compressed = 0; + size_t in_len; +#ifdef WITH_LZO + size_t out_len = len; + size_t sizeOfIt = 5; +#endif + unsigned char *in; + unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); + + ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char)); + if(compressed) { + unsigned int size; + ptcache_file_read(pf, &size, 1, sizeof(unsigned int)); + in_len = (size_t)size; + if(in_len==0) { + /* do nothing */ + } + else { + in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); + ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); +#ifdef WITH_LZO + if(compressed == 1) + r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); +#endif +#ifdef WITH_LZMA + if(compressed == 2) + { + size_t leni = in_len, leno = out_len; + ptcache_file_read(pf, &size, 1, sizeof(unsigned int)); + sizeOfIt = (size_t)size; + ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); + r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); + } +#endif + MEM_freeN(in); + } + } + else { + ptcache_file_read(pf, result, len, sizeof(unsigned char)); + } + + MEM_freeN(props); + + return r; } +static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode) +{ + int r = 0; + unsigned char compressed = 0; + size_t out_len= 0; + unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); + size_t sizeOfIt = 5; -static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size) + (void)mode; /* unused when building w/o compression */ + +#ifdef WITH_LZO + out_len= LZO_OUT_LEN(in_len); + if(mode == 1) { + LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); + + r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); + if (!(r == LZO_E_OK) || (out_len >= in_len)) + compressed = 0; + else + compressed = 1; + } +#endif +#ifdef WITH_LZMA + if(mode == 2) { + + r = LzmaCompress(out, &out_len, in, in_len,//assume sizeof(char)==1.... + props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); + + if(!(r == SZ_OK) || (out_len >= in_len)) + compressed = 0; + else + compressed = 2; + } +#endif + + ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); + if(compressed) { + unsigned int size = out_len; + ptcache_file_write(pf, &size, 1, sizeof(unsigned int)); + ptcache_file_write(pf, out, out_len, sizeof(unsigned char)); + } + else + ptcache_file_write(pf, in, in_len, sizeof(unsigned char)); + + if(compressed == 2) + { + unsigned int size = sizeOfIt; + ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int)); + ptcache_file_write(pf, props, size, sizeof(unsigned char)); + } + + MEM_freeN(props); + + return r; +} +static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size) { return (fread(f, size, tot, pf->fp) == tot); } -static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size) +static int ptcache_file_write(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size) { return (fwrite(f, size, tot, pf->fp) == tot); } -static int ptcache_file_read_data(PTCacheFile *pf) +static int ptcache_file_data_read(PTCacheFile *pf) { int i; for(i=0; i<BPHYS_TOT_DATA; i++) { - if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i])) + if((pf->data_types & (1<<i)) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i])) return 0; } return 1; } -static int ptcache_file_write_data(PTCacheFile *pf) +static int ptcache_file_data_write(PTCacheFile *pf) { int i; for(i=0; i<BPHYS_TOT_DATA; i++) { - if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i])) + if((pf->data_types & (1<<i)) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i])) return 0; } return 1; } -static int ptcache_file_read_header_begin(PTCacheFile *pf) +static int ptcache_file_header_begin_read(PTCacheFile *pf) { + unsigned int typeflag=0; int error=0; char bphysics[8]; @@ -1242,8 +1163,11 @@ static int ptcache_file_read_header_begin(PTCacheFile *pf) if(!error && strncmp(bphysics, "BPHYSICS", 8)) error = 1; - if(!error && !fread(&pf->type, sizeof(int), 1, pf->fp)) + if(!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp)) error = 1; + + pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK); + pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK); /* if there was an error set file as it was */ if(error) @@ -1251,84 +1175,82 @@ static int ptcache_file_read_header_begin(PTCacheFile *pf) return !error; } - - -static int ptcache_file_write_header_begin(PTCacheFile *pf) +static int ptcache_file_header_begin_write(PTCacheFile *pf) { - char *bphysics = "BPHYSICS"; + const char *bphysics = "BPHYSICS"; + unsigned int typeflag = pf->type + pf->flag; if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8) return 0; - if(!fwrite(&pf->type, sizeof(int), 1, pf->fp)) + if(!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp)) return 0; return 1; } - /* Data pointer handling */ int BKE_ptcache_data_size(int data_type) { return ptcache_data_size[data_type]; } -static void ptcache_file_init_pointers(PTCacheFile *pf) +static void ptcache_file_pointers_init(PTCacheFile *pf) { int data_types = pf->data_types; - pf->cur[BPHYS_DATA_INDEX] = data_types & (1<<BPHYS_DATA_INDEX) ? &pf->data.index : NULL; - pf->cur[BPHYS_DATA_LOCATION] = data_types & (1<<BPHYS_DATA_LOCATION) ? &pf->data.loc : NULL; - pf->cur[BPHYS_DATA_VELOCITY] = data_types & (1<<BPHYS_DATA_VELOCITY) ? &pf->data.vel : NULL; - pf->cur[BPHYS_DATA_ROTATION] = data_types & (1<<BPHYS_DATA_ROTATION) ? &pf->data.rot : NULL; - pf->cur[BPHYS_DATA_AVELOCITY] = data_types & (1<<BPHYS_DATA_AVELOCITY) ? &pf->data.ave : NULL; - pf->cur[BPHYS_DATA_SIZE] = data_types & (1<<BPHYS_DATA_SIZE) ? &pf->data.size : NULL; - pf->cur[BPHYS_DATA_TIMES] = data_types & (1<<BPHYS_DATA_TIMES) ? &pf->data.times : NULL; - pf->cur[BPHYS_DATA_BOIDS] = data_types & (1<<BPHYS_DATA_BOIDS) ? &pf->data.boids : NULL; + pf->cur[BPHYS_DATA_INDEX] = (data_types & (1<<BPHYS_DATA_INDEX)) ? &pf->data.index : NULL; + pf->cur[BPHYS_DATA_LOCATION] = (data_types & (1<<BPHYS_DATA_LOCATION)) ? &pf->data.loc : NULL; + pf->cur[BPHYS_DATA_VELOCITY] = (data_types & (1<<BPHYS_DATA_VELOCITY)) ? &pf->data.vel : NULL; + pf->cur[BPHYS_DATA_ROTATION] = (data_types & (1<<BPHYS_DATA_ROTATION)) ? &pf->data.rot : NULL; + pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1<<BPHYS_DATA_AVELOCITY))? &pf->data.ave : NULL; + pf->cur[BPHYS_DATA_SIZE] = (data_types & (1<<BPHYS_DATA_SIZE)) ? &pf->data.size : NULL; + pf->cur[BPHYS_DATA_TIMES] = (data_types & (1<<BPHYS_DATA_TIMES)) ? &pf->data.times : NULL; + pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1<<BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL; } -static void ptcache_file_seek_pointers(int index, PTCacheFile *pf) +/* Check to see if point number "index" is in pm, uses binary search for index data. */ +int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index) { - int i, size=0; - int data_types = pf->data_types; + if(pm->data[BPHYS_DATA_INDEX]) { + unsigned int *data = pm->data[BPHYS_DATA_INDEX]; + unsigned int mid, low = 0, high = pm->totpoint - 1; - if(data_types & (1<<BPHYS_DATA_INDEX)) { - int totpoint; - /* The simplest solution is to just write to the very end. This may cause - * some data duplication, but since it's on disk it's not so bad. The correct - * thing would be to search through the file for the correct index and only - * write to the end if it's not found, but this could be quite slow. - */ - fseek(pf->fp, 8 + sizeof(int), SEEK_SET); - fread(&totpoint, sizeof(int), 1, pf->fp); - - totpoint++; + if(index < *data || index > *(data+high)) + return -1; - fseek(pf->fp, 8 + sizeof(int), SEEK_SET); - fwrite(&totpoint, sizeof(int), 1, pf->fp); + /* check simple case for continuous indexes first */ + if(index-*data < high && data[index-*data] == index) + return index-*data; + + while(low <= high) { + mid= (low + high)/2; + + if(data[mid] > index) + high = mid - 1; + else if(data[mid] < index) + low = mid + 1; + else + return mid; + } - fseek(pf->fp, 0, SEEK_END); + return -1; } else { - for(i=0; i<BPHYS_TOT_DATA; i++) - size += pf->data_types & (1<<i) ? ptcache_data_size[i] : 0; - - /* size of default header + data up to index */ - fseek(pf->fp, 8 + 3*sizeof(int) + index * size, SEEK_SET); + return (index < pm->totpoint ? index : -1); } - - ptcache_file_init_pointers(pf); } -void BKE_ptcache_mem_init_pointers(PTCacheMem *pm) + +void BKE_ptcache_mem_pointers_init(PTCacheMem *pm) { int data_types = pm->data_types; int i; for(i=0; i<BPHYS_TOT_DATA; i++) - pm->cur[i] = data_types & (1<<i) ? pm->data[i] : NULL; + pm->cur[i] = ((data_types & (1<<i)) ? pm->data[i] : NULL); } -void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm) +void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm) { int i; @@ -1337,10 +1259,10 @@ void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm) pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i]; } } -int BKE_ptcache_mem_seek_pointers(int point_index, PTCacheMem *pm) +int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm) { int data_types = pm->data_types; - int i, index = pm->index_array ? pm->index_array[point_index] - 1 : point_index; + int i, index = BKE_ptcache_mem_index_find(pm, point_index); if(index < 0) { /* Can't give proper location without reallocation, so don't give any location. @@ -1356,7 +1278,7 @@ int BKE_ptcache_mem_seek_pointers(int point_index, PTCacheMem *pm) return 1; } -static void ptcache_alloc_data(PTCacheMem *pm) +static void ptcache_data_alloc(PTCacheMem *pm) { int data_types = pm->data_types; int totpoint = pm->totpoint; @@ -1367,7 +1289,7 @@ static void ptcache_alloc_data(PTCacheMem *pm) pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data"); } } -static void ptcache_free_data(PTCacheMem *pm) +static void ptcache_data_free(PTCacheMem *pm) { void **data = pm->data; int i; @@ -1376,13 +1298,8 @@ static void ptcache_free_data(PTCacheMem *pm) if(data[i]) MEM_freeN(data[i]); } - - if(pm->index_array) { - MEM_freeN(pm->index_array); - pm->index_array = NULL; - } } -static void ptcache_copy_data(void *from[], void *to[]) +static void ptcache_data_copy(void *from[], void *to[]) { int i; for(i=0; i<BPHYS_TOT_DATA; i++) { @@ -1393,9 +1310,20 @@ static void ptcache_copy_data(void *from[], void *to[]) } } +static void ptcache_extra_free(PTCacheMem *pm) +{ + PTCacheExtra *extra = pm->extradata.first; + if(extra) { + for(; extra; extra=extra->next) { + if(extra->data) + MEM_freeN(extra->data); + } -static int ptcache_pid_old_elemsize(PTCacheID *pid) + BLI_freelistN(&pm->extradata); + } +} +static int ptcache_old_elemsize(PTCacheID *pid) { if(pid->type==PTCACHE_TYPE_SOFTBODY) return 6 * sizeof(float); @@ -1407,268 +1335,408 @@ static int ptcache_pid_old_elemsize(PTCacheID *pid) return 0; } -/* reads cache from disk or memory */ -/* possible to get old or interpolated result */ -int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) +static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2) { - PTCacheFile *pf=NULL, *pf2=NULL; - PTCacheMem *pm=NULL, *pm2=NULL; - float old_data1[14], old_data2[14]; - int cfrai = (int)cfra; - int old_elemsize = ptcache_pid_old_elemsize(pid); - int i; + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + int cfra1=frame-1, cfra2=frame+1; - int cfra1 = 0, cfra2 = 0; - int totpoint = 0, totpoint2 = 0; - int *index = &i, *index2 = &i; - int use_old = 0, old_frame = 0; + while(cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1)) + cfra1--; - int ret = 0, error = 0; + if(cfra1 < pid->cache->startframe) + cfra1 = 0; - /* nothing to read to */ - if(pid->totpoint(pid->calldata, (int)cfra) == 0) - return 0; + while(cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2)) + cfra2++; - if(pid->cache->flag & PTCACHE_READ_INFO) { - pid->cache->flag &= ~PTCACHE_READ_INFO; - BKE_ptcache_read_cache(pid, 0, frs_sec); + if(cfra2 > pid->cache->endframe) + cfra2 = 0; + + if(cfra1 && !cfra2) { + *fra1 = 0; + *fra2 = cfra1; + } + else { + *fra1 = cfra1; + *fra2 = cfra2; + } } + else if(pid->cache->mem_cache.first) { + PTCacheMem *pm = pid->cache->mem_cache.first; + PTCacheMem *pm2 = pid->cache->mem_cache.last; + while(pm->next && pm->next->frame < frame) + pm= pm->next; - /* first check if we have the actual frame cached */ - if(cfra == (float)cfrai) { - if(pid->cache->flag & PTCACHE_DISK_CACHE) { - pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - } + if(pm2 && pm2->frame < frame) + pm2 = NULL; else { - pm = pid->cache->mem_cache.first; + while(pm2->prev && pm2->prev->frame > frame) + pm2= pm2->prev; + } - for(; pm; pm=pm->next) { - if(pm->frame == cfrai) - break; - } + if(pm && !pm2) { + *fra1 = 0; + *fra2 = pm->frame; + } + else { + *fra1 = pm->frame; + *fra2 = pm2->frame; } } +} - /* no exact cache frame found so try to find cached frames around cfra */ - if(!pm && !pf) { - if(pid->cache->flag & PTCACHE_DISK_CACHE) { - pf=NULL; - while(cfrai > pid->cache->startframe && !pf) { - cfrai--; - pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - cfra1 = cfrai; - } +static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra) +{ + PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); + PTCacheMem *pm = NULL; + unsigned int i, error = 0; + + if(pf == NULL) + return 0; - old_frame = cfrai; + if(!ptcache_file_header_begin_read(pf)) + error = 1; + + if(!error && (pf->type != pid->type || !pid->read_header(pf))) + error = 1; + + if(!error) { + pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - cfrai = (int)cfra; - while(cfrai < pid->cache->endframe && !pf2) { - cfrai++; - pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - cfra2 = cfrai; + pm->totpoint = pf->totpoint; + pm->data_types = pf->data_types; + pm->frame = pf->frame; + + ptcache_data_alloc(pm); + + if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) { + for(i=0; i<BPHYS_TOT_DATA; i++) { + unsigned int out_len = pm->totpoint*ptcache_data_size[i]; + if(pf->data_types & (1<<i)) + ptcache_file_compressed_read(pf, (unsigned char*)(pm->data[i]), out_len); } + } + else { + BKE_ptcache_mem_pointers_init(pm); + ptcache_file_pointers_init(pf); - if(pf && !pf2) { - pf2 = pf; - pf = NULL; + for(i=0; i<pm->totpoint; i++) { + if(!ptcache_file_data_read(pf)) { + error = 1; + break; + } + ptcache_data_copy(pf->cur, pm->cur); + BKE_ptcache_mem_pointers_incr(pm); } } - else if(pid->cache->mem_cache.first){ - pm = pid->cache->mem_cache.first; + } - while(pm->next && pm->next->frame < cfra) - pm= pm->next; + if(!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) { + unsigned int extratype = 0; - if(pm) { - old_frame = pm->frame; - cfra1 = pm->frame; - } + while(ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) { + PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata"); - pm2 = pid->cache->mem_cache.last; + extra->type = extratype; - if(pm2 && pm2->frame < cfra) - pm2 = NULL; - else { - while(pm2->prev && pm2->prev->frame > cfra) - pm2= pm2->prev; + ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int)); - if(pm2) - cfra2 = pm2->frame; - } + extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Pointcache extradata->data"); - if(pm && !pm2) { - pm2 = pm; - pm = NULL; - } + if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) + ptcache_file_compressed_read(pf, (unsigned char*)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]); + else + ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]); + + BLI_addtail(&pm->extradata, extra); } } - if(!pm && !pm2 && !pf && !pf2) - return 0; - - if(pm) { - BKE_ptcache_mem_init_pointers(pm); - totpoint = pm->totpoint; - index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i; + if(error && pm) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); + pm = NULL; } - if(pm2) { - BKE_ptcache_mem_init_pointers(pm2); - totpoint2 = pm2->totpoint; - index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i; + + ptcache_file_close(pf); + + if (error && G.f & G_DEBUG) + printf("Error reading from disk cache\n"); + + return pm; +} +static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm) +{ + PTCacheFile *pf = NULL; + unsigned int i, error = 0; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame); + + pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); + + if(pf==NULL) { + if (G.f & G_DEBUG) + printf("Error opening disk cache file for writing\n"); + return 0; } - if(pf) { - if(ptcache_file_read_header_begin(pf)) { - if(pf->type != pid->type) { - /* todo report error */ - ptcache_file_close(pf); - pf = NULL; - } - else if(pid->read_header(pf)) { - ptcache_file_init_pointers(pf); - totpoint = pf->totpoint; - index = pf->data_types & (1<<BPHYS_DATA_INDEX) ? &pf->data.index : &i; + + pf->data_types = pm->data_types; + pf->totpoint = pm->totpoint; + pf->type = pid->type; + pf->flag = 0; + + if(pm->extradata.first) + pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA; + + if(pid->cache->compression) + pf->flag |= PTCACHE_TYPEFLAG_COMPRESS; + + if(!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)) + error = 1; + + if(!error) { + if(pid->cache->compression) { + for(i=0; i<BPHYS_TOT_DATA; i++) { + if(pm->data[i]) { + unsigned int in_len = pm->totpoint*ptcache_data_size[i]; + unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); + ptcache_file_compressed_write(pf, (unsigned char*)(pm->data[i]), in_len, out, pid->cache->compression); + MEM_freeN(out); + } } } else { - /* fall back to old cache file format */ - use_old = 1; - totpoint = pid->totpoint(pid->calldata, (int) cfra); + BKE_ptcache_mem_pointers_init(pm); + ptcache_file_pointers_init(pf); + + for(i=0; i<pm->totpoint; i++) { + ptcache_data_copy(pm->cur, pf->cur); + if(!ptcache_file_data_write(pf)) { + error = 1; + break; + } + BKE_ptcache_mem_pointers_incr(pm); + } } } - if(pf2) { - if(ptcache_file_read_header_begin(pf2)) { - if(pf2->type != pid->type) { - /* todo report error */ - ptcache_file_close(pf2); - pf2 = NULL; + + if(!error && pm->extradata.first) { + PTCacheExtra *extra = pm->extradata.first; + + for(; extra; extra=extra->next) { + if(extra->data == NULL || extra->totdata == 0) + continue; + + ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int)); + ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int)); + + if(pid->cache->compression) { + unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type]; + unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); + ptcache_file_compressed_write(pf, (unsigned char*)(extra->data), in_len, out, pid->cache->compression); + MEM_freeN(out); } - else if(pid->read_header(pf2)) { - ptcache_file_init_pointers(pf2); - totpoint2 = pf2->totpoint; - index2 = pf2->data_types & (1<<BPHYS_DATA_INDEX) ? &pf2->data.index : &i; + else { + ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]); } } - else { - /* fall back to old cache file format */ - use_old = 1; - totpoint2 = pid->totpoint(pid->calldata, (int) cfra); - } } - /* don't read old cache if already simulated past cached frame */ - if(!pm && !pf && cfra1 && cfra1 <= pid->cache->simframe) + ptcache_file_close(pf); + + if (error && G.f & G_DEBUG) + printf("Error writing to disk cache\n"); + + return error==0; +} + +static int ptcache_read_stream(PTCacheID *pid, int cfra) +{ + PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); + int error = 0; + + if(pid->read_stream == NULL) + return 0; + + if(pf == NULL) { + if (G.f & G_DEBUG) + printf("Error opening disk cache file for reading\n"); + return 0; + } + + if(!ptcache_file_header_begin_read(pf)) error = 1; - if(cfra1 && cfra1==cfra2) + + if(!error && (pf->type != pid->type || !pid->read_header(pf))) error = 1; - if(!error) - { - if(pf && pid->read_stream) { - if(totpoint != pid->totpoint(pid->calldata, (int) cfra)) - error = 1; - else - { - // we have stream writing here - pid->read_stream(pf, pid->calldata); - } - } + if(!error && pf->totpoint != pid->totpoint(pid->calldata, cfra)) + error = 1; + + if(!error) { + ptcache_file_pointers_init(pf); + + // we have stream reading here + pid->read_stream(pf, pid->calldata); + } + + ptcache_file_close(pf); + + return error == 0; +} +static int ptcache_read(PTCacheID *pid, int cfra) +{ + PTCacheMem *pm = NULL; + int i; + int *index = &i; + + /* get a memory cache to read from */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + pm = ptcache_disk_frame_to_mem(pid, cfra); + } + else { + pm = pid->cache->mem_cache.first; + + while(pm && pm->frame != cfra) + pm = pm->next; } - if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) - totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int) cfra)); + /* read the cache */ + if(pm) { + int totpoint = pm->totpoint; + + if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) + totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra)); + + BKE_ptcache_mem_pointers_init(pm); - if(!error) - { for(i=0; i<totpoint; i++) { - /* read old cache file format */ - if(use_old) { - if(pid->read_elem && ptcache_file_read(pf, (void*)old_data1, 1, old_elemsize)) - pid->read_elem(i, pid->calldata, NULL, frs_sec, cfra, old_data1); - else if(pid->read_elem) - { error = 1; break; } - } - else { - if(pid->read_elem && (pm || ptcache_file_read_data(pf))) - pid->read_elem(*index, pid->calldata, pm ? pm->cur : pf->cur, frs_sec, cfra1 ? (float)cfra1 : (float)cfrai, NULL); - else if(pid->read_elem) - { error = 1; break; } - } + if(pm->data_types & (1<<BPHYS_DATA_INDEX)) + index = pm->cur[BPHYS_DATA_INDEX]; - if(pm) { - BKE_ptcache_mem_incr_pointers(pm); - index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i; - } + pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL); + + BKE_ptcache_mem_pointers_incr(pm); } - } - if(!error) - { - if(pf2 && pid->read_stream) { - if(totpoint2 != pid->totpoint(pid->calldata, (int) cfra)) - error = 1; - else - { - // we have stream writing here - pid->read_stream(pf2, pid->calldata); - } + if(pid->read_extra_data && pm->extradata.first) + pid->read_extra_data(pid->calldata, pm, (float)pm->frame); + + /* clean up temporary memory cache */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); } } - if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) - totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata, (int) cfra)); + return 1; +} +static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) +{ + PTCacheMem *pm = NULL; + int i; + int *index = &i; - if(!error) - { - for(i=0; i<totpoint2; i++) { - /* read old cache file format */ - if(use_old) { - if(pid->read_elem && ptcache_file_read(pf2, (void*)old_data2, 1, old_elemsize)) { - if(!pf && pf2) - pid->read_elem(i, pid->calldata, NULL, frs_sec, (float)cfra2, old_data2); - else if(pid->interpolate_elem) - pid->interpolate_elem(i, pid->calldata, NULL, frs_sec, cfra, (float)cfra1, (float)cfra2, old_data2); - else - { error = 1; break; } - } - else if(pid->read_elem) - { error = 1; break; } - } - else { - if(pid->read_elem && (pm2 || ptcache_file_read_data(pf2))) { - if((!pf && pf2) || (!pm && pm2)) - pid->read_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, (float)cfra2, NULL); - else if(pid->interpolate_elem) - pid->interpolate_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, cfra, (float)cfra1, (float)cfra2, NULL); - else - { error = 1; break; } - } - else if(pid->read_elem) - { error = 1; break; } - } + /* get a memory cache to read from */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + pm = ptcache_disk_frame_to_mem(pid, cfra2); + } + else { + pm = pid->cache->mem_cache.first; + + while(pm && pm->frame != cfra2) + pm = pm->next; + } - if(pm2) { - BKE_ptcache_mem_incr_pointers(pm2); - index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i; - } + /* read the cache */ + if(pm) { + int totpoint = pm->totpoint; + + if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) + totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra)); + + BKE_ptcache_mem_pointers_init(pm); + + for(i=0; i<totpoint; i++) { + if(pm->data_types & (1<<BPHYS_DATA_INDEX)) + index = pm->cur[BPHYS_DATA_INDEX]; + + pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL); + BKE_ptcache_mem_pointers_incr(pm); + } + + if(pid->interpolate_extra_data && pm->extradata.first) + pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2); + + /* clean up temporary memory cache */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); } } - if(pm || pf) - ret = (pm2 || pf2) ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT; - else if(pm2 || pf2) { - ret = PTCACHE_READ_OLD; - pid->cache->simframe = old_frame; + return 1; +} +/* reads cache from disk or memory */ +/* possible to get old or interpolated result */ +int BKE_ptcache_read(PTCacheID *pid, float cfra) +{ + int cfrai = (int)cfra, cfra1=0, cfra2=0; + int ret = 0; + + /* nothing to read to */ + if(pid->totpoint(pid->calldata, cfrai) == 0) + return 0; + + if(pid->cache->flag & PTCACHE_READ_INFO) { + pid->cache->flag &= ~PTCACHE_READ_INFO; + ptcache_read(pid, 0); } - if(pf) { - ptcache_file_close(pf); - pf = NULL; + /* first check if we have the actual frame cached */ + if(cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai)) + cfra1 = cfrai; + + /* no exact cache frame found so try to find cached frames around cfra */ + if(cfra1 == 0) + ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2); + + if(cfra1 == 0 && cfra2 == 0) + return 0; + + /* don't read old cache if already simulated past cached frame */ + if(cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe) + return 0; + if(cfra1 && cfra1 == cfra2) + return 0; + + if(cfra1) { + if(pid->read_stream) + ptcache_read_stream(pid, cfra1); + else if(pid->read_point) + ptcache_read(pid, cfra1); } - if(pf2) { - ptcache_file_close(pf2); - pf = NULL; + if(cfra2) { + if(pid->read_stream) + ptcache_read_stream(pid, cfra2); + else if(pid->read_point) { + if(cfra1 && cfra2 && pid->interpolate_point) + ptcache_interpolate(pid, cfra, cfra1, cfra2); + else + ptcache_read(pid, cfra2); + } + } + + if(cfra1) + ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT); + else if(cfra2) { + ret = PTCACHE_READ_OLD; + pid->cache->simframe = cfra2; } if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) { @@ -1681,218 +1749,208 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) if(cfra <= pid->cache->last_exact) pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai,pid->cache->last_exact)); + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact)); } } - return (error ? 0 : ret); + return ret; } -/* TODO for later */ -static void ptcache_make_index_array(PTCacheMem *pm, int totpoint) +static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint) { - int i, *index; + PTCacheFile *pf = NULL; + int error = 0; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra); + + pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra); - if(pm->index_array) { - MEM_freeN(pm->index_array); - pm->index_array = NULL; + if(pf==NULL) { + if (G.f & G_DEBUG) + printf("Error opening disk cache file for writing\n"); + return 0; } - if(!pm->data[BPHYS_DATA_INDEX]) - return; + pf->data_types = pid->data_types; + pf->totpoint = totpoint; + pf->type = pid->type; + pf->flag = 0; + + if(!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))) + error = 1; - pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array"); - index = pm->data[BPHYS_DATA_INDEX]; + if(!error && pid->write_stream) + pid->write_stream(pf, pid->calldata); - for(i=0; i<pm->totpoint; i++, index++) - pm->index_array[*index] = i + 1; + ptcache_file_close(pf); + + if (error && G.f & G_DEBUG) + printf("Error writing to disk cache\n"); + + return error == 0; } -/* writes cache to disk or memory */ -int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) +static int ptcache_write(PTCacheID *pid, int cfra, int overwrite) { PointCache *cache = pid->cache; - PTCacheFile *pf= NULL, *pf2= NULL; - int i; + PTCacheMem *pm=NULL, *pm2=NULL; int totpoint = pid->totpoint(pid->calldata, cfra); - int add = 0, overwrite = 0; + int i, error = 0; - if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) - return 0; + pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - if(cache->flag & PTCACHE_DISK_CACHE) { - int ofra=0, efra = cache->endframe; + pm->totpoint = pid->totwrite(pid->calldata, cfra); + pm->data_types = cfra ? pid->data_types : pid->info_types; - if(cfra==0 && cache->startframe > 0) - add = 1; - /* allways start from scratch on the first frame */ - else if(cfra == cache->startframe) { - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); - cache->flag &= ~PTCACHE_REDO_NEEDED; - add = 1; + ptcache_data_alloc(pm); + BKE_ptcache_mem_pointers_init(pm); + + if(overwrite) { + if(cache->flag & PTCACHE_DISK_CACHE) { + int fra = cfra-1; + + while(fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra)) + fra--; + + pm2 = ptcache_disk_frame_to_mem(pid, fra); } - else { - /* find last cached frame */ - while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) - efra--; - - /* find second last cached frame */ - ofra = efra-1; - while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) - ofra--; - - if(efra >= cache->startframe && cfra > efra) { - if(ofra >= cache->startframe && efra - ofra < cache->step) - overwrite = 1; - else - add = 1; + else + pm2 = cache->mem_cache.last; + } + + if(pid->write_point) { + for(i=0; i<totpoint; i++) { + int write = pid->write_point(i, pid->calldata, pm->cur, cfra); + if(write) { + BKE_ptcache_mem_pointers_incr(pm); + + /* newly born particles have to be copied to previous cached frame */ + if(overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2)) + pid->write_point(i, pid->calldata, pm2->cur, cfra); } } + } - if(add || overwrite) { - if(overwrite) - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra); - - pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra); - if(!pf) - return 0; + if(pid->write_extra_data) + pid->write_extra_data(pid->calldata, pm, cfra); - pf->type = pid->type; - pf->totpoint = cfra ? pid->totwrite(pid->calldata, cfra) : totpoint; - pf->data_types = cfra ? pid->data_types : pid->info_types; + pm->frame = cfra; - if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) { - ptcache_file_close(pf); - return 0; - } + if(cache->flag & PTCACHE_DISK_CACHE) { + error += !ptcache_mem_frame_to_disk(pid, pm); - ptcache_file_init_pointers(pf); + if(pm) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); + } - if(pf && pid->write_stream) { - // we have stream writing here - pid->write_stream(pf, pid->calldata); - } - else - for(i=0; i<totpoint; i++) { - if(pid->write_elem) { - int write = pid->write_elem(i, pid->calldata, pf->cur, cfra); - if(write) { - if(!ptcache_file_write_data(pf)) { - ptcache_file_close(pf); - if(pf2) ptcache_file_close(pf2); - return 0; - } - /* newly born particles have to be copied to previous cached frame */ - else if(overwrite && write == 2) { - if(!pf2) { - pf2 = ptcache_file_open(pid, PTCACHE_FILE_UPDATE, ofra); - if(!pf2) { - ptcache_file_close(pf); - return 0; - } - pf2->type = pid->type; - pf2->totpoint = totpoint; - pf2->data_types = pid->data_types; - } - ptcache_file_seek_pointers(i, pf2); - pid->write_elem(i, pid->calldata, pf2->cur, cfra); - if(!ptcache_file_write_data(pf2)) { - ptcache_file_close(pf); - ptcache_file_close(pf2); - return 0; - } - } - } - } - } + if(pm2) { + error += !ptcache_mem_frame_to_disk(pid, pm2); + ptcache_data_free(pm2); + ptcache_extra_free(pm2); + MEM_freeN(pm2); } } else { - PTCacheMem *pm; - PTCacheMem *pm2; + BLI_addtail(&cache->mem_cache, pm); + } - pm2 = cache->mem_cache.first; - - /* don't write info file in memory */ - if(cfra==0) + return error; +} +static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite) +{ + PointCache *cache = pid->cache; + int ofra = 0, efra = cache->endframe; + + /* allways start from scratch on the first frame */ + if(cfra && cfra == cache->startframe) { + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); + cache->flag &= ~PTCACHE_REDO_NEEDED; + return 1; + } + + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + if(cfra==0 && cache->startframe > 0) return 1; - /* allways start from scratch on the first frame */ - if(cfra == cache->startframe) { - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); - cache->flag &= ~PTCACHE_REDO_NEEDED; - add = 1; - } - else if (cache->mem_cache.last) { - pm2 = cache->mem_cache.last; - if(pm2 && cfra > pm2->frame) { - if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step) - overwrite = 1; - else - add = 1; - } - } - else - add = 1; + /* find last cached frame */ + while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) + efra--; - if(add || overwrite) { - if(overwrite) - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm2->frame); + /* find second last cached frame */ + ofra = efra-1; + while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) + ofra--; + } + else { + PTCacheMem *pm = cache->mem_cache.last; + /* don't write info file in memory */ + if(cfra == 0) + return 0; - pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); + if(pm == NULL) + return 1; - pm->totpoint = pid->totwrite(pid->calldata, cfra); - pm->data_types = cfra ? pid->data_types : pid->info_types; + efra = pm->frame; + ofra = (pm->prev ? pm->prev->frame : efra - cache->step); + } - ptcache_alloc_data(pm); - BKE_ptcache_mem_init_pointers(pm); + if(efra >= cache->startframe && cfra > efra) { + if(ofra >= cache->startframe && efra - ofra < cache->step) { + /* overwrite previous frame */ + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra); + *overwrite = 1; + } + return 1; + } - for(i=0; i<totpoint; i++) { - if(pid->write_elem) { - int write = pid->write_elem(i, pid->calldata, pm->cur, cfra); - if(write) { - BKE_ptcache_mem_incr_pointers(pm); + return 0; +} +/* writes cache to disk or memory */ +int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra) +{ + PointCache *cache = pid->cache; + int totpoint = pid->totpoint(pid->calldata, cfra); + int overwrite = 0, error = 0; - /* newly born particles have to be copied to previous cached frame */ - if(overwrite && write == 2) { - pm2 = cache->mem_cache.last; - if(BKE_ptcache_mem_seek_pointers(i, pm2)) - pid->write_elem(i, pid->calldata, pm2->cur, cfra); - } - } - } - } - ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra)); + if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) + return 0; - pm->frame = cfra; - BLI_addtail(&cache->mem_cache, pm); - } + if(ptcache_write_needed(pid, cfra, &overwrite)==0) + return 0; + + if(pid->write_stream) { + ptcache_write_stream(pid, cfra, totpoint); + } + else if(pid->write_point) { + error += ptcache_write(pid, cfra, overwrite); } - if(add || overwrite) { - if(cfra - cache->last_exact == 1 - || cfra == cache->startframe) { - cache->last_exact = cfra; - cache->flag &= ~PTCACHE_FRAMES_SKIPPED; - } - else - cache->flag |= PTCACHE_FRAMES_SKIPPED; + /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */ + if(cfra - cache->last_exact == 1 || cfra == cache->startframe) { + cache->last_exact = cfra; + cache->flag &= ~PTCACHE_FRAMES_SKIPPED; } - - if(pf) ptcache_file_close(pf); + /* Don't mark skipped when writing info file (frame 0) */ + else if(cfra) + cache->flag |= PTCACHE_FRAMES_SKIPPED; - if(pf2) ptcache_file_close(pf2); + /* Update timeline cache display */ + if(cfra && cache->cached_frames) + cache->cached_frames[cfra-cache->startframe] = 1; BKE_ptcache_update_info(pid); - return 1; + return !error; } /* youll need to close yourself after! * mode - PTCACHE_CLEAR_ALL, */ /* Clears & resets */ -void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) +void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) { - int len; /* store the length of the string */ + unsigned int len; /* store the length of the string */ + unsigned int sta, end; /* mode is same as fopen's modes */ DIR *dir; @@ -1902,9 +1960,12 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) char path_full[MAX_PTCACHE_FILE]; char ext[MAX_PTCACHE_PATH]; - if(!pid->cache || pid->cache->flag & PTCACHE_BAKED) + if(!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED) return; + sta = pid->cache->startframe; + end = pid->cache->endframe; + #ifndef DURIAN_POINTCACHE_LIB_OK /* don't allow clearing for linked objects */ if(pid->ob->id.lib) @@ -1921,7 +1982,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) if(pid->cache->flag & PTCACHE_DISK_CACHE) { ptcache_path(pid, path); - len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */ + len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */ dir = opendir(path); if (dir==NULL) @@ -1934,11 +1995,11 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ if (mode == PTCACHE_CLEAR_ALL) { pid->cache->last_exact = MIN2(pid->cache->startframe, 0); - BLI_join_dirfile(path_full, path, de->d_name); + BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); BLI_delete(path_full, 0, 0); } else { /* read the number of the file */ - int frame, len2 = (int)strlen(de->d_name); + unsigned int frame, len2 = (int)strlen(de->d_name); char num[7]; if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ @@ -1948,8 +2009,10 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) || (mode==PTCACHE_CLEAR_AFTER && frame > cfra) ) { - BLI_join_dirfile(path_full, path, de->d_name); + BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); BLI_delete(path_full, 0, 0); + if(pid->cache->cached_frames && frame >=sta && frame <= end) + pid->cache->cached_frames[frame-sta] = 0; } } } @@ -1957,25 +2020,34 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) } } closedir(dir); + + if(mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames) + memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames)); } else { PTCacheMem *pm= pid->cache->mem_cache.first; PTCacheMem *link= NULL; - pm= pid->cache->mem_cache.first; - if(mode == PTCACHE_CLEAR_ALL) { /*we want startframe if the cache starts before zero*/ pid->cache->last_exact = MIN2(pid->cache->startframe, 0); - for(; pm; pm=pm->next) - ptcache_free_data(pm); + for(; pm; pm=pm->next) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + } BLI_freelistN(&pid->cache->mem_cache); + + if(pid->cache->cached_frames) + memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames)); } else { while(pm) { if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) || (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) { link = pm; - ptcache_free_data(pm); + if(pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end) + pid->cache->cached_frames[pm->frame-sta] = 0; + ptcache_data_free(pm); + ptcache_extra_free(pm); pm = pm->next; BLI_freelinkN(&pid->cache->mem_cache, link); } @@ -1989,7 +2061,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) case PTCACHE_CLEAR_FRAME: if(pid->cache->flag & PTCACHE_DISK_CACHE) { if(BKE_ptcache_id_exist(pid, cfra)) { - BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */ + ptcache_filename(pid, filename, cfra, 1, 1); /* no path */ BLI_delete(filename, 0, 0); } } @@ -1998,27 +2070,35 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) for(; pm; pm=pm->next) { if(pm->frame == cfra) { - ptcache_free_data(pm); + ptcache_data_free(pm); + ptcache_extra_free(pm); BLI_freelinkN(&pid->cache->mem_cache, pm); break; } } } + if(pid->cache->cached_frames && cfra>=sta && cfra<=end) + pid->cache->cached_frames[cfra-sta] = 0; break; } BKE_ptcache_update_info(pid); } - -int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) +int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) { if(!pid->cache) return 0; + + if(cfra<pid->cache->startframe || cfra > pid->cache->endframe) + return 0; + + if(pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0) + return 0; if(pid->cache->flag & PTCACHE_DISK_CACHE) { char filename[MAX_PTCACHE_FILE]; - BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); + ptcache_filename(pid, filename, cfra, 1, 1); return BLI_exists(filename); } @@ -2032,7 +2112,6 @@ int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) return 0; } } - void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale) { Object *ob; @@ -2073,9 +2152,71 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra *endframe += (int)(offset+0.5f); } } -} -int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) + /* verify cached_frames array is up to date */ + if(cache->cached_frames) { + if(MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) { + MEM_freeN(cache->cached_frames); + cache->cached_frames = NULL; + } + } + + if(cache->cached_frames==NULL && cache->endframe > cache->startframe) { + unsigned int sta=cache->startframe; + unsigned int end=cache->endframe; + + cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array"); + + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + /* mode is same as fopen's modes */ + DIR *dir; + struct dirent *de; + char path[MAX_PTCACHE_PATH]; + char filename[MAX_PTCACHE_FILE]; + char ext[MAX_PTCACHE_PATH]; + unsigned int len; /* store the length of the string */ + + ptcache_path(pid, path); + + len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */ + + dir = opendir(path); + if (dir==NULL) + return; + + snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); + + while ((de = readdir(dir)) != NULL) { + if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ + if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ + /* read the number of the file */ + unsigned int frame, len2 = (int)strlen(de->d_name); + char num[7]; + + if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ + BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); + frame = atoi(num); + + if(frame >= sta && frame <= end) + cache->cached_frames[frame-sta] = 1; + } + } + } + } + closedir(dir); + } + else { + PTCacheMem *pm= pid->cache->mem_cache.first; + + while(pm) { + if(pm->frame >= sta && pm->frame <= end) + cache->cached_frames[pm->frame-sta] = 1; + pm = pm->next; + } + } + } +} +int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) { PointCache *cache; int reset, clear, after; @@ -2120,7 +2261,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) cache->flag &= ~PTCACHE_REDO_NEEDED; if(pid->type == PTCACHE_TYPE_CLOTH) - cloth_free_modifier(pid->ob, pid->calldata); + cloth_free_modifier(pid->calldata); else if(pid->type == PTCACHE_TYPE_SOFTBODY) sbFreeSimulation(pid->calldata); else if(pid->type == PTCACHE_TYPE_PARTICLES) @@ -2137,8 +2278,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) return (reset || clear || after); } - -int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) +int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) { PTCacheID pid; ParticleSystem *psys; @@ -2154,17 +2294,18 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - /* Baked cloth hair has to be checked first, because we don't want to reset */ + /* children or just redo can be calculated without reseting anything */ + if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD) + skip = 1; + /* Baked cloth hair has to be checked too, because we don't want to reset */ /* particles or cloth in that case -jahka */ - if(psys->clmd) { + else if(psys->clmd) { BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd); if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) reset |= BKE_ptcache_id_reset(scene, &pid, mode); else skip = 1; } - else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD) - skip = 1; if(skip == 0 && psys->part) { BKE_ptcache_id_from_particles(&pid, ob, psys); @@ -2183,9 +2324,6 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) { BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md); reset |= BKE_ptcache_id_reset(scene, &pid, mode); - - BKE_ptcache_id_from_smoke_turbulence(&pid, ob, (SmokeModifierData*)md); - reset |= BKE_ptcache_id_reset(scene, &pid, mode); } } } @@ -2219,7 +2357,7 @@ void BKE_ptcache_remove(void) if( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) { /* do nothing */ } else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/ - BLI_join_dirfile(path_full, path, de->d_name); + BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); BLI_delete(path_full, 0, 0); } else { rmdir = 0; /* unknown file, dont remove the dir */ @@ -2250,12 +2388,12 @@ void BKE_ptcache_set_continue_physics(Main *bmain, Scene *scene, int enable) if(CONTINUE_PHYSICS == 0) { for(ob=bmain->object.first; ob; ob=ob->id.next) if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED)) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } } } -int BKE_ptcache_get_continue_physics() +int BKE_ptcache_get_continue_physics(void) { return CONTINUE_PHYSICS; } @@ -2282,8 +2420,10 @@ void BKE_ptcache_free_mem(ListBase *mem_cache) PTCacheMem *pm = mem_cache->first; if(pm) { - for(; pm; pm=pm->next) - ptcache_free_data(pm); + for(; pm; pm=pm->next) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + } BLI_freelistN(mem_cache); } @@ -2293,6 +2433,8 @@ void BKE_ptcache_free(PointCache *cache) BKE_ptcache_free_mem(&cache->mem_cache); if(cache->edit && cache->free_edit) cache->free_edit(cache->edit); + if(cache->cached_frames) + MEM_freeN(cache->cached_frames); MEM_freeN(cache); } void BKE_ptcache_free_list(ListBase *ptcaches) @@ -2315,6 +2457,8 @@ static PointCache *ptcache_copy(PointCache *cache) /* hmm, should these be copied over instead? */ ncache->mem_cache.first = NULL; ncache->mem_cache.last = NULL; + ncache->cached_frames = NULL; + ncache->edit = NULL; ncache->flag= 0; ncache->simframe= 0; @@ -2353,7 +2497,7 @@ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene) baker.scene=scene; baker.quick_step=scene->physics_settings.quick_cache_step; - BKE_ptcache_make_cache(&baker); + BKE_ptcache_bake(&baker); } /* Simulation thread, no need for interlocks as data written in both threads @@ -2366,10 +2510,10 @@ typedef struct { int *cfra_ptr; Main *main; Scene *scene; -} ptcache_make_cache_data; +} ptcache_bake_data; -static void *ptcache_make_cache_thread(void *ptr) { - ptcache_make_cache_data *data = (ptcache_make_cache_data*)ptr; +static void *ptcache_bake_thread(void *ptr) { + ptcache_bake_data *data = (ptcache_bake_data*)ptr; for(; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) { scene_update_for_newframe(data->main, data->scene, data->scene->lay); @@ -2383,11 +2527,11 @@ static void *ptcache_make_cache_thread(void *ptr) { } /* if bake is not given run simulations to current frame */ -void BKE_ptcache_make_cache(PTCacheBaker* baker) +void BKE_ptcache_bake(PTCacheBaker* baker) { Main *bmain = baker->main; Scene *scene = baker->scene; - Scene *sce; /* SETLOOPER macro only */ + Scene *sce_iter; /* SETLOOPER macro only */ Base *base; ListBase pidlist; PTCacheID *pid = baker->pid; @@ -2398,7 +2542,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) int bake = baker->bake; int render = baker->render; ListBase threads; - ptcache_make_cache_data thread_data; + ptcache_bake_data thread_data; int progress, old_progress; thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA; @@ -2458,7 +2602,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) cache->flag &= ~PTCACHE_BAKED; } } - else for(SETLOOPER(scene, base)) { + else for(SETLOOPER(scene, sce_iter, base)) { /* cache/bake everything in the scene */ BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); @@ -2499,12 +2643,14 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) thread_data.break_operation = FALSE; thread_data.thread_ended = FALSE; old_progress = -1; + + WM_cursor_wait(1); if(G.background) { - ptcache_make_cache_thread((void*)&thread_data); + ptcache_bake_thread((void*)&thread_data); } else { - BLI_init_threads(&threads, ptcache_make_cache_thread, 1); + BLI_init_threads(&threads, ptcache_bake_thread, 1); BLI_insert_thread(&threads, (void*)&thread_data); while (thread_data.thread_ended == FALSE) { @@ -2542,10 +2688,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) cache->flag |= PTCACHE_BAKED; /* write info file */ if(cache->flag & PTCACHE_DISK_CACHE) - BKE_ptcache_write_cache(pid, 0); + BKE_ptcache_write(pid, 0); } } - else for(SETLOOPER(scene, base)) { + else for(SETLOOPER(scene, sce_iter, base)) { BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); for(pid=pidlist.first; pid; pid=pid->next) { @@ -2565,7 +2711,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if(bake) { cache->flag |= PTCACHE_BAKED; if(cache->flag & PTCACHE_DISK_CACHE) - BKE_ptcache_write_cache(pid, 0); + BKE_ptcache_write(pid, 0); } } BLI_freelistN(&pidlist); @@ -2582,126 +2728,59 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) else if (baker->progressend) baker->progressend(baker->progresscontext); + WM_cursor_wait(0); + /* TODO: call redraw all windows somehow */ } /* Helpers */ void BKE_ptcache_disk_to_mem(PTCacheID *pid) { PointCache *cache = pid->cache; - PTCacheFile *pf; - PTCacheMem *pm; - + PTCacheMem *pm = NULL; + int baked = cache->flag & PTCACHE_BAKED; int cfra, sfra = cache->startframe, efra = cache->endframe; - int i; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + /* Remove possible bake flag to allow clear */ + cache->flag &= ~PTCACHE_BAKED; - for(cfra=sfra; cfra <= efra; cfra++) { - pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); - - if(pf) { - if(!ptcache_file_read_header_begin(pf)) { - printf("Can't yet convert old cache format\n"); - cache->flag |= PTCACHE_DISK_CACHE; - ptcache_file_close(pf); - return; - } - - if(pf->type != pid->type || !pid->read_header(pf)) { - cache->flag |= PTCACHE_DISK_CACHE; - ptcache_file_close(pf); - return; - } - - pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - - pm->totpoint = pf->totpoint; - pm->data_types = pf->data_types; - pm->frame = cfra; - - ptcache_alloc_data(pm); - BKE_ptcache_mem_init_pointers(pm); - ptcache_file_init_pointers(pf); + /* PTCACHE_DISK_CACHE flag was cleared already */ + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - for(i=0; i<pm->totpoint; i++) { - if(!ptcache_file_read_data(pf)) { - printf("Error reading from disk cache\n"); - - cache->flag |= PTCACHE_DISK_CACHE; - - ptcache_free_data(pm); - MEM_freeN(pm); - ptcache_file_close(pf); - - return; - } - ptcache_copy_data(pf->cur, pm->cur); - BKE_ptcache_mem_incr_pointers(pm); - } + /* restore possible bake flag */ + cache->flag |= baked; - ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra)); + for(cfra=sfra; cfra <= efra; cfra++) { + pm = ptcache_disk_frame_to_mem(pid, cfra); + if(pm) BLI_addtail(&pid->cache->mem_cache, pm); - - ptcache_file_close(pf); - } } - } void BKE_ptcache_mem_to_disk(PTCacheID *pid) { PointCache *cache = pid->cache; - PTCacheFile *pf; - PTCacheMem *pm; - int i; + PTCacheMem *pm = cache->mem_cache.first; + int baked = cache->flag & PTCACHE_BAKED; - pm = cache->mem_cache.first; + /* Remove possible bake flag to allow clear */ + cache->flag &= ~PTCACHE_BAKED; + /* PTCACHE_DISK_CACHE flag was set already */ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - for(; pm; pm=pm->next) { - pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); - - if(pf) { - pf->data_types = pm->data_types; - pf->totpoint = pm->totpoint; - pf->type = pid->type; + /* restore possible bake flag */ + cache->flag |= baked; - BKE_ptcache_mem_init_pointers(pm); - ptcache_file_init_pointers(pf); - - if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) { - if (G.f & G_DEBUG) - printf("Error writing to disk cache\n"); - cache->flag &= ~PTCACHE_DISK_CACHE; - - ptcache_file_close(pf); - return; - } - - for(i=0; i<pm->totpoint; i++) { - ptcache_copy_data(pm->cur, pf->cur); - if(!ptcache_file_write_data(pf)) { - if (G.f & G_DEBUG) - printf("Error writing to disk cache\n"); - cache->flag &= ~PTCACHE_DISK_CACHE; - - ptcache_file_close(pf); - return; - } - BKE_ptcache_mem_incr_pointers(pm); - } - - ptcache_file_close(pf); - - /* write info file */ - if(cache->flag & PTCACHE_BAKED) - BKE_ptcache_write_cache(pid, 0); + for(; pm; pm=pm->next) { + if(ptcache_mem_frame_to_disk(pid, pm)==0) { + cache->flag &= ~PTCACHE_DISK_CACHE; + break; } - else - if (G.f & G_DEBUG) - printf("Error creating disk cache file\n"); } + + /* write info file */ + if(cache->flag & PTCACHE_BAKED) + BKE_ptcache_write(pid, 0); } void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { @@ -2715,6 +2794,11 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) return; } + if(cache->cached_frames) { + MEM_freeN(cache->cached_frames); + cache->cached_frames=NULL; + } + if(cache->flag & PTCACHE_DISK_CACHE) BKE_ptcache_mem_to_disk(pid); else @@ -2726,15 +2810,75 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) cache->last_exact = last_exact; + BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL); + BKE_ptcache_update_info(pid); } +void BKE_ptcache_disk_cache_rename(PTCacheID *pid, char *from, char *to) +{ + char old_name[80]; + int len; /* store the length of the string */ + /* mode is same as fopen's modes */ + DIR *dir; + struct dirent *de; + char path[MAX_PTCACHE_PATH]; + char old_filename[MAX_PTCACHE_FILE]; + char new_path_full[MAX_PTCACHE_FILE]; + char old_path_full[MAX_PTCACHE_FILE]; + char ext[MAX_PTCACHE_PATH]; + + /* save old name */ + strcpy(old_name, pid->cache->name); + + /* get "from" filename */ + strcpy(pid->cache->name, from); + + len = ptcache_filename(pid, old_filename, 0, 0, 0); /* no path */ + + ptcache_path(pid, path); + dir = opendir(path); + if(dir==NULL) { + strcpy(pid->cache->name, old_name); + return; + } + + snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); + + /* put new name into cache */ + strcpy(pid->cache->name, to); + + while ((de = readdir(dir)) != NULL) { + if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ + if (strncmp(old_filename, de->d_name, len ) == 0) { /* do we have the right prefix */ + /* read the number of the file */ + int frame, len2 = (int)strlen(de->d_name); + char num[7]; + + if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ + BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); + frame = atoi(num); + + BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name); + ptcache_filename(pid, new_path_full, frame, 1, 1); + BLI_rename(old_path_full, new_path_full); + } + } + } + } + closedir(dir); + + strcpy(pid->cache->name, old_name); +} + void BKE_ptcache_load_external(PTCacheID *pid) { /*todo*/ PointCache *cache = pid->cache; int len; /* store the length of the string */ int info = 0; + int start = MAXFRAME; + int end = -1; /* mode is same as fopen's modes */ DIR *dir; @@ -2746,13 +2890,9 @@ void BKE_ptcache_load_external(PTCacheID *pid) if(!cache) return; - cache->startframe = MAXFRAME; - cache->endframe = -1; - cache->totpoint = 0; - ptcache_path(pid, path); - len = BKE_ptcache_id_filename(pid, filename, 1, 0, 0); /* no path */ + len = ptcache_filename(pid, filename, 1, 0, 0); /* no path */ dir = opendir(path); if (dir==NULL) @@ -2775,8 +2915,8 @@ void BKE_ptcache_load_external(PTCacheID *pid) frame = atoi(num); if(frame) { - cache->startframe = MIN2(cache->startframe, frame); - cache->endframe = MAX2(cache->endframe, frame); + start = MIN2(start, frame); + end = MAX2(end, frame); } else info = 1; @@ -2786,15 +2926,21 @@ void BKE_ptcache_load_external(PTCacheID *pid) } closedir(dir); - if(cache->startframe != MAXFRAME) { + if(start != MAXFRAME) { PTCacheFile *pf; + cache->startframe = start; + cache->endframe = end; + cache->totpoint = 0; + + if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) + ; /*necessary info in every file*/ /* read totpoint from info file (frame 0) */ - if(info) { + else if(info) { pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0); if(pf) { - if(ptcache_file_read_header_begin(pf)) { + if(ptcache_file_header_begin_read(pf)) { if(pf->type == pid->type && pid->read_header(pf)) { cache->totpoint = pf->totpoint; cache->flag |= PTCACHE_READ_INFO; @@ -2809,7 +2955,7 @@ void BKE_ptcache_load_external(PTCacheID *pid) /* or from any old format cache file */ else { float old_data[14]; - int elemsize = ptcache_pid_old_elemsize(pid); + int elemsize = ptcache_old_elemsize(pid); pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe); if(pf) { @@ -2819,16 +2965,17 @@ void BKE_ptcache_load_external(PTCacheID *pid) ptcache_file_close(pf); } } + cache->flag |= (PTCACHE_BAKED|PTCACHE_DISK_CACHE|PTCACHE_SIMULATION_VALID); + cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED); } - cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED); - BKE_ptcache_update_info(pid); } void BKE_ptcache_update_info(PTCacheID *pid) { PointCache *cache = pid->cache; + PTCacheExtra *extra = NULL; int totframes = 0; char mem_info[64]; @@ -2840,7 +2987,10 @@ void BKE_ptcache_update_info(PTCacheID *pid) totframes++; } - if(totframes && cache->totpoint) + /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */ + if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) + sprintf(cache->info, "%i frames found!", totframes); + else if(totframes && cache->totpoint) sprintf(cache->info, "%i points found!", cache->totpoint); else sprintf(cache->info, "No valid data to read!"); @@ -2848,14 +2998,25 @@ void BKE_ptcache_update_info(PTCacheID *pid) } if(cache->flag & PTCACHE_DISK_CACHE) { - int cfra = cache->startframe; + if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) + { + int totpoint = pid->totpoint(pid->calldata, 0); - for(; cfra<=cache->endframe; cfra++) { - if(BKE_ptcache_id_exist(pid, cfra)) - totframes++; + if(cache->totpoint > totpoint) + sprintf(mem_info, "%i cells + High Resolution cached", totpoint); + else + sprintf(mem_info, "%i cells cached", totpoint); } + else { + int cfra = cache->startframe; - sprintf(mem_info, "%i frames on disk", totframes); + for(; cfra<=cache->endframe; cfra++) { + if(BKE_ptcache_id_exist(pid, cfra)) + totframes++; + } + + sprintf(mem_info, "%i frames on disk", totframes); + } } else { PTCacheMem *pm = cache->mem_cache.first; @@ -2864,7 +3025,15 @@ void BKE_ptcache_update_info(PTCacheID *pid) for(; pm; pm=pm->next) { for(i=0; i<BPHYS_TOT_DATA; i++) - bytes += pm->data[i] ? MEM_allocN_len(pm->data[i]) : 0.0f; + bytes += MEM_allocN_len(pm->data[i]); + + for(extra=pm->extradata.first; extra; extra=extra->next) { + bytes += MEM_allocN_len(extra->data); + bytes += sizeof(PTCacheExtra); + } + + bytes += sizeof(PTCacheMem); + totframes++; } @@ -2888,13 +3057,17 @@ void BKE_ptcache_update_info(PTCacheID *pid) void BKE_ptcache_validate(PointCache *cache, int framenr) { - cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe = framenr; + if(cache) { + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe = framenr; + } } void BKE_ptcache_invalidate(PointCache *cache) { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe = 0; - cache->last_exact = MIN2(cache->startframe, 0); + if(cache) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe = 0; + cache->last_exact = MIN2(cache->startframe, 0); + } } diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c index d8001572b4f..e907b628242 100644 --- a/source/blender/blenkernel/intern/property.c +++ b/source/blender/blenkernel/intern/property.c @@ -43,6 +43,8 @@ #include "BLI_blenlib.h" +#include "BKE_property.h" + void free_property(bProperty *prop) { @@ -93,7 +95,7 @@ void init_property(bProperty *prop) /* also use when property changes type */ if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin); - prop->poin= 0; + prop->poin= NULL; prop->data= 0; @@ -179,7 +181,7 @@ void unique_property(bProperty *first, bProperty *prop, int force) } } -bProperty *get_ob_property(Object *ob, char *name) +bProperty *get_ob_property(Object *ob, const char *name) { return BLI_findstring(&ob->prop, name, offsetof(bProperty, name)); } diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index 3773757f5d5..fa2e867d483 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -29,10 +29,11 @@ #include "BLI_blenlib.h" #include "BLI_dynstr.h" +#include "BLI_utildefines.h" #include "BKE_report.h" #include "BKE_global.h" /* G.background only */ -#include "BKE_utildefines.h" + #include <stdarg.h> #include <stdio.h> @@ -44,7 +45,7 @@ #endif #endif -static char *report_type_str(int type) +static const char *report_type_str(int type) { switch(type) { case RPT_DEBUG: return "Debug"; @@ -82,7 +83,7 @@ void BKE_reports_clear(ReportList *reports) while (report) { report_next= report->next; - MEM_freeN(report->message); + MEM_freeN((void *)report->message); MEM_freeN(report); report= report_next; } @@ -95,23 +96,23 @@ void BKE_report(ReportList *reports, ReportType type, const char *message) Report *report; int len; - /* exception, print and return in background, no reason to store a list */ - if(G.background) - reports= NULL; - - if(!reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) { + /* in background mode always print otherwise there are cases the errors wont be displayed, + * but still add to the report list since this is used for python exception handling */ + if(G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) { printf("%s: %s\n", report_type_str(type), message); fflush(stdout); /* this ensures the message is printed before a crash */ } if(reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) { + char *message_alloc; report= MEM_callocN(sizeof(Report), "Report"); report->type= type; report->typestr= report_type_str(type); len= strlen(message); - report->message= MEM_callocN(sizeof(char)*(len+1), "ReportMessage"); - memcpy(report->message, message, sizeof(char)*(len+1)); + message_alloc= MEM_callocN(sizeof(char)*(len+1), "ReportMessage"); + memcpy(message_alloc, message, sizeof(char)*(len+1)); + report->message= message_alloc; report->len= len; BLI_addtail(&reports->list, report); } @@ -123,10 +124,11 @@ void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...) Report *report; va_list args; - if(!reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) { + if(G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) { va_start(args, format); vprintf(format, args); va_end(args); + fprintf(stdout, "\n"); /* otherise each report needs to include a \n */ fflush(stdout); /* this ensures the message is printed before a crash */ } @@ -162,7 +164,7 @@ void BKE_reports_prepend(ReportList *reports, const char *prepend) BLI_dynstr_append(ds, prepend); BLI_dynstr_append(ds, report->message); - MEM_freeN(report->message); + MEM_freeN((void *)report->message); report->message= BLI_dynstr_get_cstring(ds); report->len= BLI_dynstr_get_len(ds); @@ -187,7 +189,7 @@ void BKE_reports_prependf(ReportList *reports, const char *prepend, ...) va_end(args); BLI_dynstr_append(ds, report->message); - MEM_freeN(report->message); + MEM_freeN((void *)report->message); report->message= BLI_dynstr_get_cstring(ds); report->len= BLI_dynstr_get_len(ds); diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 9589b1e4f98..c8a855c8156 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -86,7 +86,7 @@ void copy_sensors(ListBase *lbn, ListBase *lbo) { bSensor *sens, *sensn; - lbn->first= lbn->last= 0; + lbn->first= lbn->last= NULL; sens= lbo->first; while(sens) { sensn= copy_sensor(sens); @@ -253,7 +253,7 @@ void copy_controllers(ListBase *lbn, ListBase *lbo) { bController *cont, *contn; - lbn->first= lbn->last= 0; + lbn->first= lbn->last= NULL; cont= lbo->first; while(cont) { contn= copy_controller(cont); @@ -267,7 +267,7 @@ void init_controller(bController *cont) /* also use when controller changes type, leave actuators... */ if(cont->data) MEM_freeN(cont->data); - cont->data= 0; + cont->data= NULL; switch(cont->type) { case CONT_EXPRESSION: @@ -375,7 +375,7 @@ void copy_actuators(ListBase *lbn, ListBase *lbo) { bActuator *act, *actn; - lbn->first= lbn->last= 0; + lbn->first= lbn->last= NULL; act= lbo->first; while(act) { actn= copy_actuator(act); @@ -393,7 +393,7 @@ void init_actuator(bActuator *act) bSoundActuator *sa; if(act->data) MEM_freeN(act->data); - act->data= 0; + act->data= NULL; switch(act->type) { case ACT_ACTION: @@ -512,7 +512,7 @@ void clear_sca_new_poins_ob(Object *ob) } } -void clear_sca_new_poins() +void clear_sca_new_poins(void) { Object *ob; @@ -579,7 +579,16 @@ void set_sca_new_poins_ob(Object *ob) else if(act->type==ACT_PARENT) { bParentActuator *para = act->data; ID_NEW(para->ob); - } + } + else if(act->type==ACT_ARMATURE) { + bArmatureActuator *aa = act->data; + ID_NEW(aa->target); + ID_NEW(aa->subtarget); + } + else if(act->type==ACT_PROPERTY) { + bPropertyActuator *pa= act->data; + ID_NEW(pa->ob); + } else if(act->type==ACT_ARMATURE) { bArmatureActuator *aa = act->data; ID_NEW(aa->target); @@ -595,7 +604,7 @@ void set_sca_new_poins_ob(Object *ob) } -void set_sca_new_poins() +void set_sca_new_poins(void) { Object *ob; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 8793c412d7d..1611116f0af 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -39,6 +39,8 @@ #include <io.h> #endif +#include "MEM_guardedalloc.h" + #include "DNA_anim_types.h" #include "DNA_group_types.h" #include "DNA_object_types.h" @@ -46,7 +48,9 @@ #include "DNA_screen_types.h" #include "DNA_sequence_types.h" -#include "MEM_guardedalloc.h" +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "BKE_anim.h" #include "BKE_animsys.h" @@ -63,15 +67,12 @@ #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_world.h" -#include "BKE_utildefines.h" + #include "BKE_sound.h" //XXX #include "BIF_previewrender.h" //XXX #include "BIF_editseq.h" -#include "BLI_math.h" -#include "BLI_blenlib.h" - //XXX #include "nla.h" #ifdef WIN32 @@ -106,7 +107,7 @@ void free_qtcodecdata(QuicktimeCodecData *qcd) } } -Scene *copy_scene(Main *bmain, Scene *sce, int type) +Scene *copy_scene(Scene *sce, int type) { Scene *scen; ToolSettings *ts; @@ -128,7 +129,6 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type) id_us_plus((ID *)scen->world); id_us_plus((ID *)scen->set); - id_us_plus((ID *)scen->ima); id_us_plus((ID *)scen->gm.dome.warptext); scen->ed= NULL; @@ -171,7 +171,7 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type) BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets)); if(sce->nodetree) { - scen->nodetree= ntreeCopyTree(sce->nodetree, 0); + scen->nodetree= ntreeCopyTree(sce->nodetree); /* copies actions */ ntreeSwitchID(scen->nodetree, &sce->id, &scen->id); } @@ -210,23 +210,26 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type) if(type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) { ID_NEW(scen->camera); } + + /* before scene copy */ + sound_create_scene(scen); /* world */ if(type == SCE_COPY_FULL) { + BKE_copy_animdata_id_action((ID *)scen); if(scen->world) { id_us_plus((ID *)scen->world); scen->world= copy_world(scen->world); + BKE_copy_animdata_id_action((ID *)scen->world); } if(sce->ed) { scen->ed= MEM_callocN( sizeof(Editing), "addseq"); scen->ed->seqbasep= &scen->ed->seqbase; - seqbase_dupli_recursive(sce, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL); + seqbase_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL); } } - sound_create_scene(scen); - return scen; } @@ -315,7 +318,7 @@ void free_scene(Scene *sce) sound_destroy_scene(sce); } -Scene *add_scene(char *name) +Scene *add_scene(const char *name) { Main *bmain= G.main; Scene *sce; @@ -336,26 +339,42 @@ Scene *add_scene(char *name) sce->r.yasp= 1; sce->r.xparts= 8; sce->r.yparts= 8; - sce->r.size= 25; + sce->r.mblur_samples= 1; + sce->r.filtertype= R_FILTER_MITCH; + sce->r.size= 50; sce->r.planes= 24; + sce->r.imtype= R_PNG; sce->r.quality= 90; + sce->r.displaymode= R_OUTPUT_AREA; sce->r.framapto= 100; sce->r.images= 100; sce->r.framelen= 1.0; - sce->r.frs_sec= 25; + sce->r.blurfac= 0.5; + sce->r.frs_sec= 24; sce->r.frs_sec_base= 1; + sce->r.edgeint= 10; sce->r.ocres = 128; sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT; + sce->r.gauss= 1.0; + + /* deprecated but keep for upwards compat */ + sce->r.postgamma= 1.0; + sce->r.posthue= 0.0; + sce->r.postsat= 1.0; sce->r.bake_mode= 1; /* prevent to include render stuff here */ - sce->r.bake_filter= 8; + sce->r.bake_filter= 2; sce->r.bake_osa= 5; sce->r.bake_flag= R_BAKE_CLEAR; sce->r.bake_normal_space= R_BAKE_SPACE_TANGENT; - sce->r.scemode= R_DOCOMP|R_DOSEQ|R_EXTENSION; - sce->r.stamp= R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_SCENE|R_STAMP_CAMERA|R_STAMP_RENDERTIME; + 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; + sce->r.fg_stamp[0]= sce->r.fg_stamp[1]= sce->r.fg_stamp[2]= 0.8f; + sce->r.fg_stamp[3]= 1.0f; + sce->r.bg_stamp[0]= sce->r.bg_stamp[1]= sce->r.bg_stamp[2]= 0.0f; + sce->r.bg_stamp[3]= 0.25f; + sce->r.raytrace_options = R_RAYTRACE_USE_INSTANCES; sce->r.seq_prev_type= OB_SOLID; sce->r.seq_rend_type= OB_SOLID; @@ -441,9 +460,11 @@ Scene *add_scene(char *name) pset->brush[a].count= 10; } pset->brush[PE_BRUSH_CUT].strength= 100; - - sce->jumpframe = 10; + sce->r.ffcodecdata.audio_mixrate = 44100; + sce->r.ffcodecdata.audio_volume = 1.0f; + + BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine)); sce->audio.distance_model = 2.0; sce->audio.doppler_factor = 1.0; @@ -469,8 +490,8 @@ Scene *add_scene(char *name) sce->gm.dome.resbuf = 1.0f; sce->gm.dome.tilt = 0; - sce->gm.xplay= 800; - sce->gm.yplay= 600; + sce->gm.xplay= 640; + sce->gm.yplay= 480; sce->gm.freqplay= 60; sce->gm.depth= 32; @@ -560,16 +581,16 @@ void set_scene_bg(Main *bmain, Scene *scene) } /* called from creator.c */ -Scene *set_scene_name(Main *bmain, char *name) +Scene *set_scene_name(Main *bmain, const char *name) { Scene *sce= (Scene *)find_id("SC", name); if(sce) { set_scene_bg(bmain, sce); - printf("Scene switch: '%s' in file: '%s'\n", name, G.sce); + printf("Scene switch: '%s' in file: '%s'\n", name, G.main->name); return sce; } - printf("Can't find scene: '%s' in file: '%s'\n", name, G.sce); + printf("Can't find scene: '%s' in file: '%s'\n", name, G.main->name); return NULL; } @@ -840,6 +861,21 @@ int scene_marker_tfm_extend(Scene *scene, int delta, int flag, int frame, char s return tot; } +int scene_marker_tfm_scale(struct Scene *scene, float value, int flag) +{ + TimeMarker *marker; + int tot= 0; + + for (marker= scene->markers.first; marker; marker= marker->next) { + if ((marker->flag & flag) == flag) { + marker->frame= CFRA + (int)floorf(((float)(marker->frame - CFRA) * value) + 0.5f); + tot++; + } + } + + return tot; +} + Base *scene_add_base(Scene *sce, Object *ob) { Base *b= MEM_callocN(sizeof(*b), "scene_add_base"); @@ -909,31 +945,75 @@ float BKE_curframe(Scene *scene) return ctime; } +/* drivers support/hacks + * - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render + * - these are always run since the depsgraph can't handle non-object data + * - these happen after objects are all done so that we can read in their final transform values, + * though this means that objects can't refer to scene info for guidance... + */ +static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene) +{ + float ctime = BKE_curframe(scene); + + /* scene itself */ + if (scene->adt && scene->adt->drivers.first) { + BKE_animsys_evaluate_animdata(&scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS); + } + + /* world */ + // TODO: what about world textures? but then those have nodes too... + if (scene->world) { + ID *wid = (ID *)scene->world; + AnimData *adt= BKE_animdata_from_id(wid); + + if (adt && adt->drivers.first) + BKE_animsys_evaluate_animdata(wid, adt, ctime, ADT_RECALC_DRIVERS); + } + + /* nodes */ + if (scene->nodetree) { + ID *nid = (ID *)scene->nodetree; + AnimData *adt= BKE_animdata_from_id(nid); + + if (adt && adt->drivers.first) + BKE_animsys_evaluate_animdata(nid, adt, ctime, ADT_RECALC_DRIVERS); + } +} + static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent) { Base *base; + + + scene->customdata_mask= scene_parent->customdata_mask; /* sets first, we allow per definition current scene to have dependencies on sets, but not the other way around. */ - if(scene->set) + if (scene->set) scene_update_tagged_recursive(bmain, scene->set, scene_parent); - - for(base= scene->base.first; base; base= base->next) { + + /* scene objects */ + for (base= scene->base.first; base; base= base->next) { Object *ob= base->object; - + object_handle_update(scene_parent, ob); - + if(ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); /* always update layer, so that animating layers works */ base->lay= ob->lay; } + + /* scene drivers... */ + scene_update_drivers(bmain, scene); } /* this is called in main loop, doing tagged updates before redraw */ void scene_update_tagged(Main *bmain, Scene *scene) { + DAG_ids_flush_tagged(bmain); + scene->physics_settings.quick_cache_step= 0; /* update all objects: drivers, matrices, displists, etc. flags set @@ -943,14 +1023,14 @@ void scene_update_tagged(Main *bmain, Scene *scene) /* recalc scene animation data here (for sequencer) */ { - float ctime = BKE_curframe(scene); AnimData *adt= BKE_animdata_from_id(&scene->id); - - if(adt && (adt->recalc & ADT_RECALC_ANIM)) + float ctime = BKE_curframe(scene); + + if (adt && (adt->recalc & ADT_RECALC_ANIM)) BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, 0); } - - if(scene->physics_settings.quick_cache_step) + + if (scene->physics_settings.quick_cache_step) BKE_ptcache_quick_cache_all(bmain, scene); /* in the future this should handle updates for all datablocks, not @@ -974,7 +1054,7 @@ void scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) /* Following 2 functions are recursive * so dont call within 'scene_update_tagged_recursive' */ - DAG_scene_update_flags(bmain, sce, lay); // only stuff that moves or needs display still + DAG_scene_update_flags(bmain, sce, lay, TRUE); // only stuff that moves or needs display still /* All 'standard' (i.e. without any dependencies) animation is handled here, * with an 'local' to 'macro' order of evaluation. This should ensure that @@ -1041,20 +1121,20 @@ float get_render_aosss_error(RenderData *r, float error) } /* helper function for the SETLOOPER macro */ -Base *_setlooper_base_step(Scene **sce, Base *base) +Base *_setlooper_base_step(Scene **sce_iter, Base *base) { if(base && base->next) { /* common case, step to the next */ return base->next; } - else if(base==NULL && (*sce)->base.first) { + else if(base==NULL && (*sce_iter)->base.first) { /* first time looping, return the scenes first base */ - return (Base *)(*sce)->base.first; + return (Base *)(*sce_iter)->base.first; } else { /* reached the end, get the next base in the set */ - while((*sce= (*sce)->set)) { - base= (Base *)(*sce)->base.first; + while((*sce_iter= (*sce_iter)->set)) { + base= (Base *)(*sce_iter)->base.first; if(base) { return base; } diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 6f1d32898f9..58900e603e3 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -109,7 +109,7 @@ ARegionType *BKE_regiontype_from_id(SpaceType *st, int regionid) } -const ListBase *BKE_spacetypes_list() +const ListBase *BKE_spacetypes_list(void) { return &spacetypes; } diff --git a/source/blender/blenkernel/intern/script.c b/source/blender/blenkernel/intern/script.c index c07032f71d7..6ffac09e843 100644 --- a/source/blender/blenkernel/intern/script.c +++ b/source/blender/blenkernel/intern/script.c @@ -36,7 +36,7 @@ /* -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON #include "BPY_extern.h" // Blender Python library #endif */ diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index 37bd3983769..000d08e4df2 100755 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -1,5 +1,5 @@ -/** -* $Id: seqcache.c 30687 2010-07-24 08:47:14Z schlaile $ +/* +* $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -32,6 +32,7 @@ #include "DNA_sequence_types.h" #include "BKE_sequencer.h" +#include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_mempool.h" #include <pthread.h> @@ -42,8 +43,7 @@ typedef struct seqCacheKey { struct Sequence * seq; - int rectx; - int recty; + SeqRenderData context; float cfra; seq_stripelem_ibuf_t type; } seqCacheKey; @@ -54,29 +54,29 @@ typedef struct seqCacheEntry MEM_CacheLimiterHandleC * c_handle; } seqCacheEntry; -static GHash * hash = 0; -static MEM_CacheLimiterC * limitor = 0; -static struct BLI_mempool * entrypool = 0; -static struct BLI_mempool * keypool = 0; +static GHash * hash = NULL; +static MEM_CacheLimiterC * limitor = NULL; +static struct BLI_mempool * entrypool = NULL; +static struct BLI_mempool * keypool = NULL; static int ibufs_in = 0; static int ibufs_rem = 0; -static unsigned int HashHash(void *key_) +static unsigned int HashHash(const void *key_) { - seqCacheKey * key = (seqCacheKey*) key_; - unsigned int rval = key->rectx + key->recty; + const seqCacheKey *key = (seqCacheKey*) key_; + unsigned int rval = seq_hash_render_data(&key->context); rval ^= *(unsigned int*) &key->cfra; rval += key->type; - rval ^= ((unsigned int) key->seq) << 6; + rval ^= ((intptr_t) key->seq) << 6; return rval; } -static int HashCmp(void *a_, void *b_) +static int HashCmp(const void *a_, const void *b_) { - seqCacheKey * a = (seqCacheKey*) a_; - seqCacheKey * b = (seqCacheKey*) b_; + const seqCacheKey * a = (seqCacheKey*) a_; + const seqCacheKey * b = (seqCacheKey*) b_; if (a->seq < b->seq) { return -1; @@ -99,21 +99,7 @@ static int HashCmp(void *a_, void *b_) return 1; } - if (a->rectx < b->rectx) { - return -1; - } - if (a->rectx > b->rectx) { - return 1; - } - - if (a->recty < b->recty) { - return -1; - } - if (a->recty > b->recty) { - return 1; - } - - return 0; + return seq_cmp_render_data(&a->context, &b->context); } static void HashKeyFree(void *key) @@ -133,8 +119,8 @@ static void HashValFree(void *val) ibufs_rem++; } - e->ibuf = 0; - e->c_handle = 0; + e->ibuf = NULL; + e->c_handle = NULL; BLI_mempool_free(entrypool, e); } @@ -149,12 +135,12 @@ static void IMB_seq_cache_destructor(void * p) IMB_freeImBuf(e->ibuf); ibufs_rem++; - e->ibuf = 0; - e->c_handle = 0; + e->ibuf = NULL; + e->c_handle = NULL; } } -void seq_stripelem_cache_init() +void seq_stripelem_cache_init(void) { hash = BLI_ghash_new(HashHash, HashCmp, "seq stripelem cache hash"); limitor = new_MEM_CacheLimiter( IMB_seq_cache_destructor ); @@ -163,7 +149,7 @@ void seq_stripelem_cache_init() keypool = BLI_mempool_create(sizeof(seqCacheKey), 64, 64, 0, 0); } -void seq_stripelem_cache_destruct() +void seq_stripelem_cache_destruct(void) { if (!entrypool) { return; @@ -174,7 +160,7 @@ void seq_stripelem_cache_destruct() BLI_mempool_destroy(keypool); } -void seq_stripelem_cache_cleanup() +void seq_stripelem_cache_cleanup(void) { if (!entrypool) { seq_stripelem_cache_init(); @@ -192,14 +178,14 @@ void seq_stripelem_cache_cleanup() } struct ImBuf * seq_stripelem_cache_get( - struct Sequence * seq, int rectx, int recty, + SeqRenderData context, struct Sequence * seq, float cfra, seq_stripelem_ibuf_t type) { seqCacheKey key; seqCacheEntry * e; if (!seq) { - return 0; + return NULL; } if (!entrypool) { @@ -207,8 +193,7 @@ struct ImBuf * seq_stripelem_cache_get( } key.seq = seq; - key.rectx = rectx; - key.recty = recty; + key.context = context; key.cfra = cfra - seq->start; key.type = type; @@ -220,11 +205,11 @@ struct ImBuf * seq_stripelem_cache_get( MEM_CacheLimiter_touch(e->c_handle); return e->ibuf; } - return 0; + return NULL; } void seq_stripelem_cache_put( - struct Sequence * seq, int rectx, int recty, + SeqRenderData context, struct Sequence * seq, float cfra, seq_stripelem_ibuf_t type, struct ImBuf * i) { seqCacheKey * key; @@ -243,18 +228,18 @@ void seq_stripelem_cache_put( key = (seqCacheKey*) BLI_mempool_alloc(keypool); key->seq = seq; - key->rectx = rectx; - key->recty = recty; + key->context = context; key->cfra = cfra - seq->start; key->type = type; - /* we want our own version */ - IMB_refImBuf(i); + /* Normally we want our own version, but start and end stills are duplicates of the original. */ + if(ELEM(type, SEQ_STRIPELEM_IBUF_STARTSTILL, SEQ_STRIPELEM_IBUF_ENDSTILL)==0) + IMB_refImBuf(i); e = (seqCacheEntry*) BLI_mempool_alloc(entrypool); e->ibuf = i; - e->c_handle = 0; + e->c_handle = NULL; BLI_ghash_remove(hash, key, HashKeyFree, HashValFree); BLI_ghash_insert(hash, key, e); diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 461cb075bb0..7ddd1fbd6bb 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -35,6 +35,7 @@ #include "PIL_dynlib.h" #include "BLI_math.h" /* windows needs for M_PI */ +#include "BLI_utildefines.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" @@ -53,7 +54,7 @@ #include "RNA_access.h" /* **** XXX **** */ -static void error(const char *error, ...) {} +static void error(const char *UNUSED(error), ...) {} #define INT 96 #define FLO 128 @@ -69,23 +70,25 @@ enum { }; static struct ImBuf * prepare_effect_imbufs( - int x, int y, + SeqRenderData context, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { struct ImBuf * out; + int x = context.rectx; + int y = context.recty; if (!ibuf1 && !ibuf2 && !ibuf3) { /* hmmm, global float option ? */ - out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect, 0); + out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect); } else if ((ibuf1 && ibuf1->rect_float) || (ibuf2 && ibuf2->rect_float) || (ibuf3 && ibuf3->rect_float)) { /* if any inputs are rectfloat, output is float too */ - out = IMB_allocImBuf((short)x, (short)y, 32, IB_rectfloat, 0); + out = IMB_allocImBuf((short)x, (short)y, 32, IB_rectfloat); } else { - out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect, 0); + out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect); } if (ibuf1 && !ibuf1->rect_float && out->rect_float) { @@ -117,17 +120,17 @@ static struct ImBuf * prepare_effect_imbufs( static void open_plugin_seq(PluginSeq *pis, const char *seqname) { - int (*version)(); - void* (*alloc_private)(); + int (*version)(void); + void* (*alloc_private)(void); char *cp; /* to be sure: (is tested for) */ - pis->doit= 0; - pis->pname= 0; - pis->varstr= 0; - pis->cfra= 0; + pis->doit= NULL; + pis->pname= NULL; + pis->varstr= NULL; + pis->cfra= NULL; pis->version= 0; - pis->instance_private_data = 0; + pis->instance_private_data = NULL; /* clear the error list */ PIL_dynlib_get_error_as_string(NULL); @@ -139,12 +142,12 @@ static void open_plugin_seq(PluginSeq *pis, const char *seqname) pis->handle= PIL_dynlib_open(pis->name); if(test_dlerr(pis->name, pis->name)) return; - if (pis->handle != 0) { + if (pis->handle != NULL) { /* find the address of the version function */ - version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion"); + version= (int (*)(void))PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion"); if (test_dlerr(pis->name, "plugin_seq_getversion")) return; - if (version != 0) { + if (version != NULL) { pis->version= version(); if (pis->version >= 2 && pis->version <= 6) { int (*info_func)(PluginInfo *); @@ -175,7 +178,7 @@ static void open_plugin_seq(PluginSeq *pis, const char *seqname) return; } } - alloc_private = (void* (*)())PIL_dynlib_find_symbol( + alloc_private = (void* (*)(void))PIL_dynlib_find_symbol( pis->handle, "plugin_seq_alloc_private_data"); if (alloc_private) { pis->instance_private_data = alloc_private(); @@ -198,11 +201,11 @@ static PluginSeq *add_plugin_seq(const char *str, const char *seqname) strncpy(pis->name, str, FILE_MAXDIR+FILE_MAXFILE); open_plugin_seq(pis, seqname); - if(pis->doit==0) { - if(pis->handle==0) error("no plugin: %s", str); + if(pis->doit==NULL) { + if(pis->handle==NULL) error("no plugin: %s", str); else error("in plugin: %s", str); MEM_freeN(pis); - return 0; + return NULL; } /* default values */ @@ -219,7 +222,7 @@ static PluginSeq *add_plugin_seq(const char *str, const char *seqname) static void free_plugin_seq(PluginSeq *pis) { - if(pis==0) return; + if(pis==NULL) return; /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */ @@ -244,7 +247,7 @@ static void init_plugin(Sequence * seq, const char * fname) /* * FIXME: should query plugin! Could be generator, that needs zero inputs... */ -static int num_inputs_plugin() +static int num_inputs_plugin(void) { return 1; } @@ -267,15 +270,14 @@ static void copy_plugin(Sequence * dst, Sequence * src) static ImBuf * IMB_cast_away_list(ImBuf * i) { if (!i) { - return 0; + return NULL; } return (ImBuf*) (((void**) i) + 2); } static struct ImBuf * do_plugin_effect( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, Sequence *seq, float cfra, + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { @@ -285,7 +287,9 @@ static struct ImBuf * do_plugin_effect( old plugins) do very bad stuff with imbuf-internals */ - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); + int x = context.rectx; + int y = context.recty; if(seq->plugin && seq->plugin->doit) { @@ -370,8 +374,8 @@ static struct ImBuf * do_plugin_effect( return out; } -static int do_plugin_early_out(struct Sequence *seq, - float facf0, float facf1) +static int do_plugin_early_out(struct Sequence *UNUSED(seq), + float UNUSED(facf0), float UNUSED(facf1)) { return 0; } @@ -379,7 +383,7 @@ static int do_plugin_early_out(struct Sequence *seq, static void free_plugin(struct Sequence * seq) { free_plugin_seq(seq->plugin); - seq->plugin = 0; + seq->plugin = NULL; } /* ********************************************************************** @@ -524,22 +528,21 @@ static void do_alphaover_effect_float(float facf0, float facf1, int x, int y, } static struct ImBuf * do_alphaover_effect( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); if (out->rect_float) { do_alphaover_effect_float( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, ibuf1->rect_float, ibuf2->rect_float, out->rect_float); } else { do_alphaover_effect_byte( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, (char*) ibuf1->rect, (char*) ibuf2->rect, (char*) out->rect); } @@ -551,7 +554,7 @@ static struct ImBuf * do_alphaover_effect( ALPHA UNDER ********************************************************************** */ -void do_alphaunder_effect_byte( +static void do_alphaunder_effect_byte( float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out) { @@ -696,22 +699,22 @@ static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, } static struct ImBuf* do_alphaunder_effect( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs( + context, ibuf1, ibuf2, ibuf3); if (out->rect_float) { do_alphaunder_effect_float( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, ibuf1->rect_float, ibuf2->rect_float, out->rect_float); } else { do_alphaunder_effect_byte( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, (char*) ibuf1->rect, (char*) ibuf2->rect, (char*) out->rect); } @@ -723,7 +726,7 @@ static struct ImBuf* do_alphaunder_effect( CROSS ********************************************************************** */ -void do_cross_effect_byte(float facf0, float facf1, int x, int y, +static void do_cross_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out) { @@ -771,7 +774,7 @@ void do_cross_effect_byte(float facf0, float facf1, int x, int y, } } -void do_cross_effect_float(float facf0, float facf1, int x, int y, +static void do_cross_effect_float(float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out) { float fac1, fac2, fac3, fac4; @@ -821,22 +824,22 @@ void do_cross_effect_float(float facf0, float facf1, int x, int y, /* carefull: also used by speed effect! */ static struct ImBuf* do_cross_effect( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs( + context, ibuf1, ibuf2, ibuf3); if (out->rect_float) { do_cross_effect_float( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, ibuf1->rect_float, ibuf2->rect_float, out->rect_float); } else { do_cross_effect_byte( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, (char*) ibuf1->rect, (char*) ibuf2->rect, (char*) out->rect); } @@ -967,7 +970,7 @@ static void gamtabs(float gamma) } -static void build_gammatabs() +static void build_gammatabs(void) { if (gamma_tabs_init == FALSE) { gamtabs(2.0f); @@ -976,19 +979,19 @@ static void build_gammatabs() } } -static void init_gammacross(Sequence * seq) +static void init_gammacross(Sequence * UNUSED(seq)) { } -static void load_gammacross(Sequence * seq) +static void load_gammacross(Sequence * UNUSED(seq)) { } -static void free_gammacross(Sequence * seq) +static void free_gammacross(Sequence * UNUSED(seq)) { } -static void do_gammacross_effect_byte(float facf0, float facf1, +static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1), int x, int y, unsigned char *rect1, unsigned char *rect2, @@ -1044,7 +1047,7 @@ static void do_gammacross_effect_byte(float facf0, float facf1, } -static void do_gammacross_effect_float(float facf0, float facf1, +static void do_gammacross_effect_float(float facf0, float UNUSED(facf1), int x, int y, float *rect1, float *rect2, float *out) @@ -1088,24 +1091,24 @@ static void do_gammacross_effect_float(float facf0, float facf1, } static struct ImBuf * do_gammacross_effect( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, + Sequence *UNUSED(seq), float UNUSED(cfra), + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); build_gammatabs(); if (out->rect_float) { do_gammacross_effect_float( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, ibuf1->rect_float, ibuf2->rect_float, out->rect_float); } else { do_gammacross_effect_byte( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect, (unsigned char*) out->rect); } @@ -1206,22 +1209,22 @@ static void do_add_effect_float(float facf0, float facf1, int x, int y, } } -static struct ImBuf * do_add_effect(Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, +static struct ImBuf * do_add_effect(SeqRenderData context, + Sequence *UNUSED(seq), float UNUSED(cfra), + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); if (out->rect_float) { do_add_effect_float( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, ibuf1->rect_float, ibuf2->rect_float, out->rect_float); } else { do_add_effect_byte( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect, (unsigned char*) out->rect); } @@ -1323,22 +1326,21 @@ static void do_sub_effect_float(float facf0, float facf1, int x, int y, } static struct ImBuf * do_sub_effect( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); if (out->rect_float) { do_sub_effect_float( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, ibuf1->rect_float, ibuf2->rect_float, out->rect_float); } else { do_sub_effect_byte( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, (char*) ibuf1->rect, (char*) ibuf2->rect, (char*) out->rect); } @@ -1537,22 +1539,21 @@ static void do_mul_effect_float(float facf0, float facf1, int x, int y, } static struct ImBuf * do_mul_effect( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); if (out->rect_float) { do_mul_effect_float( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, ibuf1->rect_float, ibuf2->rect_float, out->rect_float); } else { do_mul_effect_byte( - facf0, facf1, x, y, + facf0, facf1, context.rectx, context.recty, (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect, (unsigned char*) out->rect); } @@ -1591,15 +1592,10 @@ static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo // This function calculates the blur band for the wipe effects static float in_band(WipeZone *wipezone,float width,float dist,float perc,int side,int dir) { - float t1,t2,alpha,percwidth; + float t1,t2,alpha; if(width == 0) return (float)side; - - if(side == 1) - percwidth = width * perc; - else - percwidth = width * (1 - perc); if(width < dist) return side; @@ -1860,7 +1856,7 @@ static void init_wipe_effect(Sequence *seq) seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars"); } -static int num_inputs_wipe() +static int num_inputs_wipe(void) { return 1; } @@ -1868,7 +1864,7 @@ static int num_inputs_wipe() static void free_wipe_effect(Sequence *seq) { if(seq->effectdata)MEM_freeN(seq->effectdata); - seq->effectdata = 0; + seq->effectdata = NULL; } static void copy_wipe_effect(Sequence *dst, Sequence *src) @@ -1876,7 +1872,7 @@ static void copy_wipe_effect(Sequence *dst, Sequence *src) dst->effectdata = MEM_dupallocN(src->effectdata); } -static void do_wipe_effect_byte(Sequence *seq, float facf0, float facf1, +static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1), int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) @@ -1934,7 +1930,7 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float facf1, } } -static void do_wipe_effect_float(Sequence *seq, float facf0, float facf1, +static void do_wipe_effect_float(Sequence *seq, float facf0, float UNUSED(facf1), int x, int y, float *rect1, float *rect2, float *out) @@ -1993,24 +1989,23 @@ static void do_wipe_effect_float(Sequence *seq, float facf0, float facf1, } static struct ImBuf * do_wipe_effect( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, Sequence *seq, float UNUSED(cfra), + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); if (out->rect_float) { do_wipe_effect_float(seq, - facf0, facf1, x, y, - ibuf1->rect_float, ibuf2->rect_float, - out->rect_float); + facf0, facf1, context.rectx, context.recty, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); } else { do_wipe_effect_byte(seq, - facf0, facf1, x, y, - (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect, - (unsigned char*) out->rect); + facf0, facf1, context.rectx, context.recty, + (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect, + (unsigned char*) out->rect); } return out; @@ -2045,7 +2040,7 @@ static void init_transform_effect(Sequence *seq) transform->uniform_scale=0; } -static int num_inputs_transform() +static int num_inputs_transform(void) { return 1; } @@ -2053,7 +2048,7 @@ static int num_inputs_transform() static void free_transform_effect(Sequence *seq) { if(seq->effectdata)MEM_freeN(seq->effectdata); - seq->effectdata = 0; + seq->effectdata = NULL; } static void copy_transform_effect(Sequence *dst, Sequence *src) @@ -2062,8 +2057,8 @@ static void copy_transform_effect(Sequence *dst, Sequence *src) } static void transform_image(int x, int y, struct ImBuf *ibuf1, struct ImBuf *out, - float scale_x, float scale_y, float translate_x, float translate_y, - float rotate, int interpolation) + float scale_x, float scale_y, float translate_x, float translate_y, + float rotate, int interpolation) { int xo, yo, xi, yi; float xt, yt, xr, yr; @@ -2111,7 +2106,7 @@ static void transform_image(int x, int y, struct ImBuf *ibuf1, struct ImBuf *out } } -static void do_transform(Scene *scene, Sequence *seq, float facf0, int x, int y, +static void do_transform(Scene *scene, Sequence *seq, float UNUSED(facf0), int x, int y, struct ImBuf *ibuf1,struct ImBuf *out) { TransformVars *transform = (TransformVars *)seq->effectdata; @@ -2144,15 +2139,15 @@ static void do_transform(Scene *scene, Sequence *seq, float facf0, int x, int y, static struct ImBuf * do_transform_effect( - Main *bmain, Scene *scene, Sequence *seq,float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, Sequence *seq,float UNUSED(cfra), + float facf0, float UNUSED(facf1), struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); - do_transform(scene, seq, facf0, x, y, ibuf1, out); + do_transform(context.scene, seq, facf0, + context.rectx, context.recty, ibuf1, out); return out; } @@ -2614,7 +2609,7 @@ static void init_glow_effect(Sequence *seq) glow->bNoComp = 0; } -static int num_inputs_glow() +static int num_inputs_glow(void) { return 1; } @@ -2622,7 +2617,7 @@ static int num_inputs_glow() static void free_glow_effect(Sequence *seq) { if(seq->effectdata)MEM_freeN(seq->effectdata); - seq->effectdata = 0; + seq->effectdata = NULL; } static void copy_glow_effect(Sequence *dst, Sequence *src) @@ -2631,55 +2626,56 @@ static void copy_glow_effect(Sequence *dst, Sequence *src) } //void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use) -static void do_glow_effect_byte(Sequence *seq, float facf0, float facf1, +static void do_glow_effect_byte(Sequence *seq, int render_size, float facf0, float UNUSED(facf1), int x, int y, char *rect1, - char *rect2, char *out) + char *UNUSED(rect2), char *out) { unsigned char *outbuf=(unsigned char *)out; unsigned char *inbuf=(unsigned char *)rect1; GlowVars *glow = (GlowVars *)seq->effectdata; - int size= 100; // renderdata XXX RVIsolateHighlights_byte(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost * facf0, glow->fClamp); - RVBlurBitmap2_byte (outbuf, x, y, glow->dDist * (size / 100.0f),glow->dQuality); + RVBlurBitmap2_byte (outbuf, x, y, glow->dDist * (render_size / 100.0f),glow->dQuality); if (!glow->bNoComp) RVAddBitmaps_byte (inbuf , outbuf, outbuf, x, y); } -static void do_glow_effect_float(Sequence *seq, float facf0, float facf1, +static void do_glow_effect_float(Sequence *seq, int render_size, float facf0, float UNUSED(facf1), int x, int y, - float *rect1, float *rect2, float *out) + float *rect1, float *UNUSED(rect2), float *out) { float *outbuf = out; float *inbuf = rect1; GlowVars *glow = (GlowVars *)seq->effectdata; - int size= 100; // renderdata XXX RVIsolateHighlights_float(inbuf, outbuf , x, y, glow->fMini*3.0f, glow->fBoost * facf0, glow->fClamp); - RVBlurBitmap2_float (outbuf, x, y, glow->dDist * (size / 100.0f),glow->dQuality); + RVBlurBitmap2_float (outbuf, x, y, glow->dDist * (render_size / 100.0f),glow->dQuality); if (!glow->bNoComp) RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y); } static struct ImBuf * do_glow_effect( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, Sequence *seq, float UNUSED(cfra), + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); + + int render_size = 100*context.rectx/context.scene->r.xsch; if (out->rect_float) { - do_glow_effect_float(seq, - facf0, facf1, x, y, - ibuf1->rect_float, ibuf2->rect_float, - out->rect_float); + do_glow_effect_float(seq, render_size, + facf0, facf1, + context.rectx, context.recty, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); } else { - do_glow_effect_byte(seq, - facf0, facf1, x, y, - (char*) ibuf1->rect, (char*) ibuf2->rect, - (char*) out->rect); + do_glow_effect_byte(seq, render_size, + facf0, facf1, + context.rectx, context.recty, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); } return out; @@ -2700,7 +2696,7 @@ static void init_solid_color(Sequence *seq) cv->col[0] = cv->col[1] = cv->col[2] = 0.5; } -static int num_inputs_color() +static int num_inputs_color(void) { return 0; } @@ -2708,7 +2704,7 @@ static int num_inputs_color() static void free_solid_color(Sequence *seq) { if(seq->effectdata)MEM_freeN(seq->effectdata); - seq->effectdata = 0; + seq->effectdata = NULL; } static void copy_solid_color(Sequence *dst, Sequence *src) @@ -2716,25 +2712,26 @@ static void copy_solid_color(Sequence *dst, Sequence *src) dst->effectdata = MEM_dupallocN(src->effectdata); } -static int early_out_color(struct Sequence *seq, - float facf0, float facf1) +static int early_out_color(struct Sequence *UNUSED(seq), + float UNUSED(facf0), float UNUSED(facf1)) { return -1; } static struct ImBuf * do_solid_color( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, + SeqRenderData context, Sequence *seq, float UNUSED(cfra), + float facf0, float facf1, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); SolidColorVars *cv = (SolidColorVars *)seq->effectdata; unsigned char *rect; float *rect_float; + int x; /*= context.rectx;*/ /*UNUSED*/ + int y; /*= context.recty;*/ /*UNUSED*/ if (out->rect) { unsigned char col0[3]; @@ -2808,22 +2805,21 @@ static struct ImBuf * do_solid_color( ********************************************************************** */ /* no effect inputs for multicam, we use give_ibuf_seq */ -static int num_inputs_multicam() +static int num_inputs_multicam(void) { return 0; } -static int early_out_multicam(struct Sequence *seq, float facf0, float facf1) +static int early_out_multicam(struct Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1)) { return -1; } static struct ImBuf * do_multicam( - Main *bmain, Scene *scene, Sequence *seq, float cfra, - float facf0, float facf1, int x, int y, - int preview_render_size, - struct ImBuf *ibuf1, struct ImBuf *ibuf2, - struct ImBuf *ibuf3) + SeqRenderData context, Sequence *seq, float cfra, + float UNUSED(facf0), float UNUSED(facf1), + struct ImBuf *UNUSED(ibuf1), struct ImBuf *UNUSED(ibuf2), + struct ImBuf *UNUSED(ibuf3)) { struct ImBuf * i; struct ImBuf * out; @@ -2831,25 +2827,24 @@ static struct ImBuf * do_multicam( ListBase * seqbasep; if (seq->multicam_source == 0 || seq->multicam_source >= seq->machine) { - return 0; + return NULL; } - ed = scene->ed; + ed = context.scene->ed; if (!ed) { - return 0; + return NULL; } seqbasep = seq_seqbase(&ed->seqbase, seq); if (!seqbasep) { - return 0; + return NULL; } - i = give_ibuf_seqbase(bmain, scene, x, y, cfra, seq->multicam_source, - preview_render_size, seqbasep); + i = give_ibuf_seqbase(context, cfra, seq->multicam_source, seqbasep); if (!i) { - return 0; + return NULL; } - if (input_have_to_preprocess(scene, seq, cfra, x, y)) { + if (input_have_to_preprocess(context, seq, cfra)) { out = IMB_dupImBuf(i); IMB_freeImBuf(i); } else { @@ -2872,8 +2867,8 @@ static void init_speed_effect(Sequence *seq) v = (SpeedControlVars *)seq->effectdata; v->globalSpeed = 1.0; - v->frameMap = 0; - v->flags = 0; + v->frameMap = NULL; + v->flags |= SEQ_SPEED_INTEGRATE; /* should be default behavior */ v->length = 0; } @@ -2881,11 +2876,11 @@ static void load_speed_effect(Sequence * seq) { SpeedControlVars * v = (SpeedControlVars *)seq->effectdata; - v->frameMap = 0; + v->frameMap = NULL; v->length = 0; } -static int num_inputs_speed() +static int num_inputs_speed(void) { return 1; } @@ -2895,7 +2890,7 @@ static void free_speed_effect(Sequence *seq) SpeedControlVars * v = (SpeedControlVars *)seq->effectdata; if(v->frameMap) MEM_freeN(v->frameMap); if(seq->effectdata) MEM_freeN(seq->effectdata); - seq->effectdata = 0; + seq->effectdata = NULL; } static void copy_speed_effect(Sequence *dst, Sequence *src) @@ -2903,18 +2898,18 @@ static void copy_speed_effect(Sequence *dst, Sequence *src) SpeedControlVars * v; dst->effectdata = MEM_dupallocN(src->effectdata); v = (SpeedControlVars *)dst->effectdata; - v->frameMap = 0; + v->frameMap = NULL; v->length = 0; } -static int early_out_speed(struct Sequence *seq, - float facf0, float facf1) +static int early_out_speed(struct Sequence *UNUSED(seq), + float UNUSED(facf0), float UNUSED(facf1)) { return 1; } static void store_icu_yrange_speed(struct Sequence * seq, - short adrcode, float * ymin, float * ymax) + short UNUSED(adrcode), float * ymin, float * ymax) { SpeedControlVars * v = (SpeedControlVars *)seq->effectdata; @@ -2936,11 +2931,11 @@ static void store_icu_yrange_speed(struct Sequence * seq, } void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) { - float ctime, div; int cfra; - float fallback_fac; + float fallback_fac = 1.0f; SpeedControlVars * v = (SpeedControlVars *)seq->effectdata; FCurve *fcu= NULL; + int flags = v->flags; /* if not already done, load / initialize data */ get_sequence_effect(seq); @@ -2955,7 +2950,7 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) /* XXX - new in 2.5x. should we use the animation system this way? * The fcurve is needed because many frames need evaluating at once - campbell */ - fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_fader", 0); + fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0); if (!v->frameMap || v->length != seq->len) { @@ -2968,15 +2963,23 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) } fallback_fac = 1.0; - - /* if there is no fcurve, try to make retiming easy by stretching the - strip */ - if (!fcu && seq->seq1->enddisp != seq->seq1->start && seq->seq1->len != 0) { - fallback_fac = (float) seq->seq1->len / - (float) (seq->seq1->enddisp - seq->seq1->start); + + if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) { + if (seq->seq1->enddisp != seq->seq1->start + && seq->seq1->len != 0) { + fallback_fac = (float) seq->seq1->len / + (float) (seq->seq1->enddisp - seq->seq1->start); + flags = SEQ_SPEED_INTEGRATE; + fcu = NULL; + } + } else { + /* if there is no fcurve, use value as simple multiplier */ + if (!fcu) { + fallback_fac = seq->speed_fader; /* same as speed_factor in rna*/ + } } - if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) { + if (flags & SEQ_SPEED_INTEGRATE) { float cursor = 0; float facf; @@ -2985,10 +2988,7 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) for (cfra = 1; cfra < v->length; cfra++) { if(fcu) { - ctime = seq->startdisp + cfra; - div = 1.0; - - facf = evaluate_fcurve(fcu, ctime/div); + facf = evaluate_fcurve(fcu, seq->startdisp + cfra); } else { facf = fallback_fac; } @@ -3010,19 +3010,16 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) for (cfra = 0; cfra < v->length; cfra++) { if(fcu) { - ctime = seq->startdisp + cfra; - div = 1.0; - - facf = evaluate_fcurve(fcu, ctime / div); - if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) { - facf *= v->length; - } + facf = evaluate_fcurve(fcu, seq->startdisp + cfra); + } else { + facf = fallback_fac; } - - if (!fcu) { - facf = (float) cfra * fallback_fac; + + if (flags & SEQ_SPEED_COMPRESS_IPO_Y) { + facf *= seq->seq1->len; } facf *= v->globalSpeed; + if (facf >= seq->seq1->len) { facf = seq->seq1->len - 1; } else { @@ -3033,56 +3030,43 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) } } -/* - simply reuse do_cross_effect for blending... - -static void do_speed_effect(Sequence * seq,int cfra, - float facf0, float facf1, int x, int y, - struct ImBuf *ibuf1, struct ImBuf *ibuf2, - struct ImBuf *ibuf3, struct ImBuf *out) -{ - -} -*/ - - /* ********************************************************************** sequence effect factory ********************************************************************** */ -static void init_noop(struct Sequence *seq) +static void init_noop(struct Sequence *UNUSED(seq)) { } -static void load_noop(struct Sequence *seq) +static void load_noop(struct Sequence *UNUSED(seq)) { } -static void init_plugin_noop(struct Sequence *seq, const char * fname) +static void init_plugin_noop(struct Sequence *UNUSED(seq), const char *UNUSED(fname)) { } -static void free_noop(struct Sequence *seq) +static void free_noop(struct Sequence *UNUSED(seq)) { } -static int num_inputs_default() +static int num_inputs_default(void) { return 2; } -static int early_out_noop(struct Sequence *seq, - float facf0, float facf1) +static int early_out_noop(struct Sequence *UNUSED(seq), + float UNUSED(facf0), float UNUSED(facf1)) { return 0; } -static int early_out_fade(struct Sequence *seq, +static int early_out_fade(struct Sequence *UNUSED(seq), float facf0, float facf1) { if (facf0 == 0.0 && facf1 == 0.0) { @@ -3093,7 +3077,7 @@ static int early_out_fade(struct Sequence *seq, return 0; } -static int early_out_mul_input2(struct Sequence *seq, +static int early_out_mul_input2(struct Sequence *UNUSED(seq), float facf0, float facf1) { if (facf0 == 0.0 && facf1 == 0.0) { @@ -3102,13 +3086,13 @@ static int early_out_mul_input2(struct Sequence *seq, return 0; } -static void store_icu_yrange_noop(struct Sequence * seq, - short adrcode, float * ymin, float * ymax) +static void store_icu_yrange_noop(struct Sequence * UNUSED(seq), + short UNUSED(adrcode), float *UNUSED(ymin), float *UNUSED(ymax)) { /* defaults are fine */ } -static void get_default_fac_noop(struct Sequence *seq, float cfra, +static void get_default_fac_noop(struct Sequence *UNUSED(seq), float UNUSED(cfra), float * facf0, float * facf1) { *facf0 = *facf1 = 1.0; @@ -3123,15 +3107,17 @@ static void get_default_fac_fade(struct Sequence *seq, float cfra, *facf1 /= seq->len; } -static struct ImBuf * do_overdrop_effect(Main *bmain, Scene *scene, Sequence *seq, float cfra, +static struct ImBuf * do_overdrop_effect(SeqRenderData context, + Sequence *UNUSED(seq), + float UNUSED(cfra), float facf0, float facf1, - int x, int y, - int preview_render_size, struct ImBuf * ibuf1, struct ImBuf * ibuf2, struct ImBuf * ibuf3) { - struct ImBuf * out = prepare_effect_imbufs(x, y, ibuf1, ibuf2, ibuf3); + struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3); + int x = context.rectx; + int y = context.recty; if (out->rect_float) { do_drop_effect_float( @@ -3274,9 +3260,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) struct SeqEffectHandle get_sequence_effect(Sequence * seq) { - struct SeqEffectHandle rval; - - memset(&rval, 0, sizeof(struct SeqEffectHandle)); + struct SeqEffectHandle rval= {NULL}; if (seq->type & SEQ_EFFECT) { rval = get_sequence_effect_impl(seq->type); @@ -3291,9 +3275,7 @@ struct SeqEffectHandle get_sequence_effect(Sequence * seq) struct SeqEffectHandle get_sequence_blend(Sequence * seq) { - struct SeqEffectHandle rval; - - memset(&rval, 0, sizeof(struct SeqEffectHandle)); + struct SeqEffectHandle rval= {NULL}; if (seq->blend_mode != 0) { rval = get_sequence_effect_impl(seq->blend_mode); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index b6bb5c3a51b..83e28db771a 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -41,6 +41,14 @@ #include "DNA_object_types.h" #include "DNA_sound_types.h" +#include "BLI_math.h" +#include "BLI_fileops.h" +#include "BLI_listbase.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + #include "BKE_animsys.h" #include "BKE_global.h" #include "BKE_image.h" @@ -49,21 +57,15 @@ #include "BKE_fcurve.h" #include "BKE_scene.h" #include "RNA_access.h" +#include "BKE_utildefines.h" + #include "RE_pipeline.h" -#include "BLI_math.h" -#include "BLI_fileops.h" -#include "BLI_listbase.h" -#include "BLI_path_util.h" -#include "BLI_string.h" -#include "BLI_threads.h" #include <pthread.h> #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" - - #include "BKE_context.h" #include "BKE_sound.h" #include "AUD_C-API.h" @@ -133,7 +135,7 @@ static void free_proxy_seq(Sequence *seq) { if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) { IMB_free_anim(seq->strip->proxy->anim); - seq->strip->proxy->anim = 0; + seq->strip->proxy->anim = NULL; } } @@ -191,7 +193,7 @@ void seq_free_sequence(Scene *scene, Sequence *seq) if (ed->act_seq==seq) ed->act_seq= NULL; - if(seq->scene_sound) + if(seq->scene_sound && ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) sound_remove_scene_sound(scene, seq->scene_sound); seq_free_animdata(scene, seq); @@ -244,7 +246,95 @@ void seq_free_editing(Scene *scene) MEM_freeN(ed); } -/* ************************* itterator ************************** */ +/* ********************************************************************** + * sequencer pipeline functions + ********************************************************************** */ + +SeqRenderData seq_new_render_data( + struct Main * bmain, struct Scene * scene, + int rectx, int recty, int preview_render_size) +{ + SeqRenderData rval; + + rval.bmain = bmain; + rval.scene = scene; + rval.rectx = rectx; + rval.recty = recty; + rval.preview_render_size = preview_render_size; + rval.motion_blur_samples = 0; + rval.motion_blur_shutter = 0; + + return rval; +} + +int seq_cmp_render_data(const SeqRenderData * a, const SeqRenderData * b) +{ + if (a->preview_render_size < b->preview_render_size) { + return -1; + } + if (a->preview_render_size > b->preview_render_size) { + return 1; + } + + if (a->rectx < b->rectx) { + return -1; + } + if (a->rectx > b->rectx) { + return 1; + } + + if (a->recty < b->recty) { + return -1; + } + if (a->recty > b->recty) { + return 1; + } + + if (a->bmain < b->bmain) { + return -1; + } + if (a->bmain > b->bmain) { + return 1; + } + + if (a->scene < b->scene) { + return -1; + } + if (a->scene > b->scene) { + return 1; + } + + if (a->motion_blur_shutter < b->motion_blur_shutter) { + return -1; + } + if (a->motion_blur_shutter > b->motion_blur_shutter) { + return 1; + } + + if (a->motion_blur_samples < b->motion_blur_samples) { + return -1; + } + if (a->motion_blur_samples > b->motion_blur_samples) { + return 1; + } + + return 0; +} + +unsigned int seq_hash_render_data(const SeqRenderData * a) +{ + unsigned int rval = a->rectx + a->recty; + + rval ^= a->preview_render_size; + rval ^= ((intptr_t) a->bmain) << 6; + rval ^= ((intptr_t) a->scene) << 6; + rval ^= (int) (a->motion_blur_shutter * 100.0) << 10; + rval ^= a->motion_blur_samples << 24; + + return rval; +} + +/* ************************* iterator ************************** */ /* *************** (replaces old WHILE_SEQ) ********************* */ /* **************** use now SEQ_BEGIN() SEQ_END ***************** */ @@ -339,7 +429,7 @@ void seq_end(SeqIterator *iter) * in metastrips!) ********************************************************************** */ - +#if 0 /* UNUSED */ static void do_seq_count(ListBase *seqbase, int *totseq) { Sequence *seq; @@ -366,7 +456,7 @@ static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth) } } -void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq) +static void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq) { Sequence **tseqar; @@ -374,7 +464,7 @@ void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq) do_seq_count(seqbase, totseq); if(*totseq==0) { - *seqar= 0; + *seqar= NULL; return; } *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar"); @@ -383,6 +473,7 @@ void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq) do_build_seqar(seqbase, seqar, 0); *seqar= tseqar; } +#endif /* UNUSED */ static void do_seq_count_cb(ListBase *seqbase, int *totseq, int (*test_func)(Sequence * seq)) @@ -413,8 +504,7 @@ static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth, seq->depth= depth; if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) { - do_build_seqar_cb(&seq->seqbase, seqar, depth+1, - test_func); + do_build_seqar_cb(&seq->seqbase, seqar, depth+1, test_func); } if (test & BUILD_SEQAR_COUNT_CURRENT) { **seqar= seq; @@ -433,7 +523,7 @@ void build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int *totseq, do_seq_count_cb(seqbase, totseq, test_func); if(*totseq==0) { - *seqar= 0; + *seqar= NULL; return; } *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar"); @@ -473,7 +563,7 @@ static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq) if(seq->type == SEQ_META) { seq_update_sound_bounds_recursive(scene, seq); } - else if((seq->type == SEQ_SOUND) || (seq->type == SEQ_SCENE)) { + else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) { if(seq->scene_sound) { int startofs = seq->startofs; int endofs = seq->endofs; @@ -504,8 +594,8 @@ void calc_sequence(Scene *scene, Sequence *seq) if(seq->type & SEQ_EFFECT) { /* pointers */ - if(seq->seq2==0) seq->seq2= seq->seq1; - if(seq->seq3==0) seq->seq3= seq->seq1; + if(seq->seq2==NULL) seq->seq2= seq->seq1; + if(seq->seq3==NULL) seq->seq3= seq->seq1; /* effecten go from seq1 -> seq2: test */ @@ -554,15 +644,13 @@ void calc_sequence(Scene *scene, Sequence *seq) } /* note: caller should run calc_sequence(scene, seq) after */ -void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int lock_range) +void reload_sequence_new_file(Scene *scene, Sequence * seq, int lock_range) { char str[FILE_MAXDIR+FILE_MAXFILE]; - int prev_startdisp, prev_enddisp; + int prev_startdisp=0, prev_enddisp=0; /* note: dont rename the strip, will break animation curves */ - if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE || - seq->type == SEQ_SOUND || - seq->type == SEQ_SCENE || seq->type == SEQ_META)) { + if (ELEM5(seq->type, SEQ_MOVIE, SEQ_IMAGE, SEQ_SOUND, SEQ_SCENE, SEQ_META)==0) { return; } @@ -576,13 +664,14 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc new_tstripdata(seq); - if (seq->type != SEQ_SCENE && seq->type != SEQ_META && - seq->type != SEQ_IMAGE) { - BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name); - BLI_path_abs(str, G.sce); + if (ELEM3(seq->type, SEQ_SCENE, SEQ_META, SEQ_IMAGE)==0) { + BLI_join_dirfile(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_abs(str, G.main->name); } - if (seq->type == SEQ_IMAGE) { + switch(seq->type) { + case SEQ_IMAGE: + { /* Hack? */ size_t olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem); @@ -593,7 +682,9 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc seq->len = 0; } seq->strip->len = seq->len; - } else if (seq->type == SEQ_MOVIE) { + break; + } + case SEQ_MOVIE: if(seq->anim) IMB_free_anim(seq->anim); seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0)); @@ -611,7 +702,9 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc seq->len = 0; } seq->strip->len = seq->len; - } else if (seq->type == SEQ_SOUND) { + case SEQ_SOUND: + if(!seq->sound) + return; seq->len = ceil(AUD_getInfo(seq->sound->playback_handle).length * FPS); seq->len -= seq->anim_startofs; seq->len -= seq->anim_endofs; @@ -619,9 +712,11 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc seq->len = 0; } seq->strip->len = seq->len; - } else if (seq->type == SEQ_SCENE) { + break; + case SEQ_SCENE: + { /* 'seq->scenenr' should be replaced with something more reliable */ - Scene * sce = bmain->scene.first; + Scene * sce = G.main->scene.first; int nr = 1; while(sce) { @@ -634,10 +729,8 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc if (sce) { seq->scene = sce; - } else { - sce = seq->scene; } - + seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1; seq->len -= seq->anim_startofs; seq->len -= seq->anim_endofs; @@ -645,6 +738,8 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc seq->len = 0; } seq->strip->len = seq->len; + break; + } } free_proxy_seq(seq); @@ -668,8 +763,8 @@ void sort_seq(Scene *scene) if(ed==NULL) return; - seqbase.first= seqbase.last= 0; - effbase.first= effbase.last= 0; + seqbase.first= seqbase.last= NULL; + effbase.first= effbase.last= NULL; while( (seq= ed->seqbasep->first) ) { BLI_remlink(ed->seqbasep, seq); @@ -683,7 +778,7 @@ void sort_seq(Scene *scene) } seqt= seqt->next; } - if(seqt==0) BLI_addtail(&effbase, seq); + if(seqt==NULL) BLI_addtail(&effbase, seq); } else { seqt= seqbase.first; @@ -694,11 +789,11 @@ void sort_seq(Scene *scene) } seqt= seqt->next; } - if(seqt==0) BLI_addtail(&seqbase, seq); + if(seqt==NULL) BLI_addtail(&seqbase, seq); } } - addlisttolist(&seqbase, &effbase); + BLI_movelisttolist(&seqbase, &effbase); *(ed->seqbasep)= seqbase; } @@ -783,7 +878,7 @@ void seqbase_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq) strcpy(seq->name+2, sui.name_dest); } -static char *give_seqname_by_type(int type) +static const char *give_seqname_by_type(int type) { switch(type) { case SEQ_META: return "Meta"; @@ -806,13 +901,13 @@ static char *give_seqname_by_type(int type) case SEQ_MULTICAM: return "Multicam"; case SEQ_SPEED: return "Speed"; default: - return 0; + return NULL; } } -char *give_seqname(Sequence *seq) +const char *give_seqname(Sequence *seq) { - char * name = give_seqname_by_type(seq->type); + const char *name = give_seqname_by_type(seq->type); if (!name) { if(seq->type<SEQ_EFFECT) { @@ -839,7 +934,7 @@ static void make_black_ibuf(ImBuf *ibuf) float *rect_float; int tot; - if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return; + if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) return; tot= ibuf->x*ibuf->y; @@ -898,19 +993,24 @@ static void multibuf(ImBuf *ibuf, float fmul) static float give_stripelem_index(Sequence *seq, float cfra) { float nr; + int sta = seq->start; + int end = seq->start+seq->len-1; if(seq->len == 0) return -1; + if(seq->flag&SEQ_REVERSE_FRAMES) { /*reverse frame in this sequence */ - if(cfra <= seq->start) nr= seq->len-1; - else if(cfra >= seq->start+seq->len-1) nr= 0; - else nr= (seq->start + seq->len - 1) - cfra; + if(cfra <= sta) nr= seq->len-1; + else if(cfra >= end) nr= 0; + else nr= end - cfra; } else { - if(cfra <= seq->start) nr= 0; - else if(cfra >= seq->start+seq->len-1) nr= seq->len-1; - else nr= cfra-seq->start; + if(cfra <= sta) nr= 0; + else if(cfra >= end) nr= seq->len-1; + else nr= cfra - sta; } + if (seq->strobe < 1.0) seq->strobe = 1.0; + if (seq->strobe > 1.0) { nr -= fmod((double)nr, (double)seq->strobe); } @@ -922,14 +1022,10 @@ StripElem *give_stripelem(Sequence *seq, int cfra) { StripElem *se= seq->strip->stripdata; - if(seq->type == SEQ_MOVIE) { - /* use the first */ - } - else { + if(seq->type != SEQ_MOVIE) { /* movie use the first */ int nr = (int) give_stripelem_index(seq, cfra); - if (nr == -1) return 0; - if (se == 0) return 0; + if (nr == -1 || se == NULL) return NULL; se += nr + seq->anim_startofs; } @@ -966,9 +1062,7 @@ int evaluate_seq_frame(Scene *scene, int cfra) static int video_seq_is_rendered(Sequence * seq) { - return (seq - && !(seq->flag & SEQ_MUTE) - && seq->type != SEQ_SOUND); + return (seq && !(seq->flag & SEQ_MUTE) && seq->type != SEQ_SOUND); } static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out) @@ -983,7 +1077,7 @@ static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Se if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) { if (b > 0) { - if (seq_arr[b] == 0) { + if (seq_arr[b] == NULL) { return 0; } } else { @@ -1005,7 +1099,7 @@ static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Se } } - for (;b <= chanshown; b++) { + for (;b <= chanshown && b >= 0; b++) { if (video_seq_is_rendered(seq_arr[b])) { seq_arr_out[cnt++] = seq_arr[b]; } @@ -1021,7 +1115,7 @@ static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Se #define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE) -static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * name, int render_size) +static int seq_proxy_get_fname(SeqRenderData context, Sequence * seq, int cfra, char * name) { int frameno; char dir[FILE_MAXDIR]; @@ -1030,103 +1124,96 @@ static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * na return FALSE; } - if ((seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) - || (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE)) { + if (seq->flag & (SEQ_USE_PROXY_CUSTOM_DIR|SEQ_USE_PROXY_CUSTOM_FILE)) { strcpy(dir, seq->strip->proxy->dir); } else { - if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) { - snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", - seq->strip->dir); + if (ELEM(seq->type, SEQ_IMAGE, SEQ_MOVIE)) { + snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", seq->strip->dir); } else { return FALSE; } } if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { - BLI_join_dirfile(name, dir, seq->strip->proxy->file); - BLI_path_abs(name, G.sce); + BLI_join_dirfile(name, FILE_MAX, dir, seq->strip->proxy->file); /* XXX, not real length */ + BLI_path_abs(name, G.main->name); return TRUE; } /* generate a separate proxy directory for each preview size */ - if (seq->type == SEQ_IMAGE) { - StripElem * se = give_stripelem(seq, cfra); - snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", - dir, render_size, se->name); + switch(seq->type) { + case SEQ_IMAGE: + snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", dir, + context.preview_render_size, + give_stripelem(seq, cfra)->name); frameno = 1; - } else if (seq->type == SEQ_MOVIE) { - frameno = (int) give_stripelem_index(seq, cfra) - + seq->anim_startofs; - + break; + case SEQ_MOVIE: + frameno = (int) give_stripelem_index(seq, cfra) + seq->anim_startofs; snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir, - seq->strip->stripdata->name, - render_size); - } else { - frameno = (int) give_stripelem_index(seq, cfra) - + seq->anim_startofs; - - snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, - render_size); + seq->strip->stripdata->name, context.preview_render_size); + break; + default: + frameno = (int) give_stripelem_index(seq, cfra) + seq->anim_startofs; + snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, + context.preview_render_size); } - BLI_path_abs(name, G.sce); + BLI_path_abs(name, G.main->name); BLI_path_frame(name, frameno, 0); - strcat(name, ".jpg"); return TRUE; } -static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, int render_size) +static struct ImBuf * seq_proxy_fetch(SeqRenderData context, Sequence * seq, int cfra) { char name[PROXY_MAXFILE]; if (!(seq->flag & SEQ_USE_PROXY)) { - return 0; + return NULL; } /* rendering at 100% ? No real sense in proxy-ing, right? */ - if (render_size == 100) { - return 0; + if (context.preview_render_size == 100) { + return NULL; } if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { - int frameno = (int) give_stripelem_index(seq, cfra) - + seq->anim_startofs; - if (!seq->strip->proxy->anim) { - if (!seq_proxy_get_fname( - scene, seq, cfra, name, render_size)) { - return 0; + int frameno = (int) give_stripelem_index(seq, cfra) + seq->anim_startofs; + if (seq->strip->proxy->anim == NULL) { + if (seq_proxy_get_fname(context, seq, cfra, name)==0) { + return NULL; } seq->strip->proxy->anim = openanim(name, IB_rect); } - if (!seq->strip->proxy->anim) { - return 0; + if (seq->strip->proxy->anim==NULL) { + return NULL; } return IMB_anim_absolute(seq->strip->proxy->anim, frameno); } - if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { - return 0; + if (seq_proxy_get_fname(context, seq, cfra, name) == 0) { + return NULL; } if (BLI_exists(name)) { return IMB_loadiffname(name, IB_rect); } else { - return 0; + return NULL; } } #if 0 static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra, - int build_proxy_run, int render_size); + int build_proxy_run, int preview_render_size); -static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size, int seqrectx, int seqrecty) +static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int preview_render_size, int seqrectx, int seqrecty) { char name[PROXY_MAXFILE]; int quality; @@ -1140,7 +1227,7 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re } /* rendering at 100% ? No real sense in proxy-ing, right? */ - if (render_size == 100) { + if (preview_render_size == 100) { return; } @@ -1149,7 +1236,7 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re return; } - if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { + if (!seq_proxy_get_fname(scene, seq, cfra, name, preview_render_size)) { return; } @@ -1163,15 +1250,15 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re se->ibuf = 0; } - do_build_seq_ibuf(scene, seq, se, cfra, TRUE, render_size, + do_build_seq_ibuf(scene, seq, se, cfra, TRUE, preview_render_size, seqrectx, seqrecty); if (!se->ibuf) { return; } - rectx= (render_size*scene->r.xsch)/100; - recty= (render_size*scene->r.ysch)/100; + rectx= (preview_render_size*scene->r.xsch)/100; + recty= (preview_render_size*scene->r.ysch)/100; ibuf = se->ibuf; @@ -1380,8 +1467,7 @@ static void color_balance_byte_float(Sequence * seq, ImBuf* ibuf, float mul) cb = calc_cb(seq->strip->color_balance); for (c = 0; c < 3; c++) { - make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], - cb_tab[c], mul); + make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul); } for (i = 0; i < 256; i++) { @@ -1444,17 +1530,12 @@ static void color_balance(Sequence * seq, ImBuf* ibuf, float mul) */ int input_have_to_preprocess( - Scene *scene, Sequence * seq, float cfra, int seqrectx, int seqrecty) + SeqRenderData UNUSED(context), Sequence * seq, float UNUSED(cfra)) { float mul; - if ((seq->flag & SEQ_FILTERY) || - (seq->flag & SEQ_USE_CROP) || - (seq->flag & SEQ_USE_TRANSFORM) || - (seq->flag & SEQ_FLIPX) || - (seq->flag & SEQ_FLIPY) || - (seq->flag & SEQ_USE_COLOR_BALANCE) || - (seq->flag & SEQ_MAKE_PREMUL)) { + if (seq->flag & (SEQ_FILTERY|SEQ_USE_CROP|SEQ_USE_TRANSFORM|SEQ_FLIPX| + SEQ_FLIPY|SEQ_USE_COLOR_BALANCE|SEQ_MAKE_PREMUL)) { return TRUE; } @@ -1476,26 +1557,19 @@ int input_have_to_preprocess( } static ImBuf * input_preprocess( - Scene *scene, Sequence *seq, float cfra, int seqrectx, int seqrecty, - ImBuf * ibuf) + SeqRenderData context, Sequence *seq, float UNUSED(cfra), ImBuf * ibuf) { float mul; - seq->strip->orx= ibuf->x; - seq->strip->ory= ibuf->y; - if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) { IMB_filtery(ibuf); } - if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) { - StripCrop c; - StripTransform t; + if(seq->flag & (SEQ_USE_CROP|SEQ_USE_TRANSFORM)) { + StripCrop c= {0}; + StripTransform t= {0}; int sx,sy,dx,dy; - memset(&c, 0, sizeof(StripCrop)); - memset(&t, 0, sizeof(StripTransform)); - if(seq->flag & SEQ_USE_CROP && seq->strip->crop) { c = *seq->strip->crop; } @@ -1509,27 +1583,17 @@ static ImBuf * input_preprocess( dy = sy; if (seq->flag & SEQ_USE_TRANSFORM) { - dx = scene->r.xsch; - dy = scene->r.ysch; + dx = context.scene->r.xsch; + dy = context.scene->r.ysch; } - if (c.top + c.bottom >= ibuf->y || - c.left + c.right >= ibuf->x || - t.xofs >= dx || t.yofs >= dy) { + if (c.top + c.bottom >= ibuf->y || c.left + c.right >= ibuf->x || + t.xofs >= dx || t.yofs >= dy) { make_black_ibuf(ibuf); } else { - ImBuf * i; + ImBuf * i = IMB_allocImBuf(dx, dy,32, ibuf->rect_float ? IB_rectfloat : IB_rect); - if (ibuf->rect_float) { - i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0); - } else { - i = IMB_allocImBuf(dx, dy,32, IB_rect, 0); - } - - IMB_rectcpy(i, ibuf, - t.xofs, t.yofs, - c.left, c.bottom, - sx, sy); + IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy); IMB_freeImBuf(ibuf); @@ -1548,7 +1612,7 @@ static ImBuf * input_preprocess( if(seq->sat != 1.0f) { /* inline for now, could become an imbuf function */ int i; - char *rct= (char *)ibuf->rect; + unsigned char *rct= (unsigned char *)ibuf->rect; float *rctf= ibuf->rect_float; const float sat= seq->sat; float hsv[3]; @@ -1596,38 +1660,35 @@ static ImBuf * input_preprocess( } if(seq->flag & SEQ_MAKE_PREMUL) { - if(ibuf->depth == 32 && ibuf->zbuf == 0) { + if(ibuf->depth == 32 && ibuf->zbuf == NULL) { IMB_premultiply_alpha(ibuf); } } - if(ibuf->x != seqrectx || ibuf->y != seqrecty ) { - if(scene->r.mode & R_OSA) { - IMB_scaleImBuf(ibuf, - (short)seqrectx, (short)seqrecty); + if(ibuf->x != context.rectx || ibuf->y != context.recty ) { + if(context.scene->r.mode & R_OSA) { + IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty); } else { - IMB_scalefastImBuf(ibuf, - (short)seqrectx, (short)seqrecty); + IMB_scalefastImBuf(ibuf, (short)context.rectx, (short)context.recty); } } return ibuf; } -static ImBuf * copy_from_ibuf_still(Sequence * seq, float nr, - int seqrectx, int seqrecty) +static ImBuf * copy_from_ibuf_still(SeqRenderData context, Sequence * seq, + float nr) { - ImBuf * rval = 0; - ImBuf * ibuf = 0; + ImBuf * rval = NULL; + ImBuf * ibuf = NULL; if (nr == 0) { ibuf = seq_stripelem_cache_get( - seq, seqrectx, seqrecty, seq->start, + context, seq, seq->start, SEQ_STRIPELEM_IBUF_STARTSTILL); - } - if (nr == seq->len - 1) { + } else if (nr == seq->len - 1) { ibuf = seq_stripelem_cache_get( - seq, seqrectx, seqrecty, seq->start, + context, seq, seq->start, SEQ_STRIPELEM_IBUF_ENDSTILL); } @@ -1639,18 +1700,19 @@ static ImBuf * copy_from_ibuf_still(Sequence * seq, float nr, return rval; } -static void copy_to_ibuf_still(Sequence * seq, float nr, +static void copy_to_ibuf_still(SeqRenderData context, Sequence * seq, float nr, ImBuf * ibuf) { if (nr == 0) { seq_stripelem_cache_put( - seq, 0, 0, seq->start, - SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf); - } + context, seq, seq->start, + SEQ_STRIPELEM_IBUF_STARTSTILL, IMB_dupImBuf(ibuf)); + } + if (nr == seq->len - 1) { seq_stripelem_cache_put( - seq, 0, 0, seq->start, - SEQ_STRIPELEM_IBUF_ENDSTILL, ibuf); + context, seq, seq->start, + SEQ_STRIPELEM_IBUF_ENDSTILL, IMB_dupImBuf(ibuf)); } } @@ -1658,45 +1720,46 @@ static void copy_to_ibuf_still(Sequence * seq, float nr, strip rendering functions ********************************************************************** */ -static ImBuf* seq_render_strip_stack( - Main *bmain, Scene *scene, - ListBase *seqbasep, float cfra, int chanshown, int render_size, - int seqrectx, int seqrecty); +static ImBuf* seq_render_strip_stack( + SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown); -static ImBuf * seq_render_strip(Main *bmain, Scene *scene, Sequence * seq, float cfra, - int render_size, - int seqrectx, int seqrecty); +static ImBuf * seq_render_strip( + SeqRenderData context, Sequence * seq, float cfra); static ImBuf* seq_render_effect_strip_impl( - Main *bmain, Scene *scene, float cfra, Sequence *seq, int render_size, - int seqrectx, int seqrecty) + SeqRenderData context, Sequence *seq, float cfra) { float fac, facf; int early_out; int i; - int must_preprocess = FALSE; - struct SeqEffectHandle sh = get_sequence_effect(seq); FCurve *fcu= NULL; ImBuf * ibuf[3]; - ImBuf * out = 0; + Sequence *input[3]; + ImBuf * out = NULL; + + ibuf[0] = ibuf[1] = ibuf[2] = NULL; - ibuf[0] = ibuf[1] = ibuf[2] = 0; + input[0] = seq->seq1; input[1] = seq->seq2; input[2] = seq->seq3; if (!sh.execute) { /* effect not supported in this version... */ - goto finish; + out = IMB_allocImBuf((short)context.rectx, + (short)context.recty, 32, IB_rect); + return out; } - if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) { + if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) { sh.get_default_fac(seq, cfra, &fac, &facf); - if( scene->r.mode & R_FIELDS ); else facf= fac; - } else { - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, - "effect_fader", 0); + + if ((context.scene->r.mode & R_FIELDS)==0) + facf= fac; + } + else { + fcu = id_data_find_fcurve(&context.scene->id, seq, &RNA_Sequence, "effect_fader", 0); if (fcu) { fac = facf = evaluate_fcurve(fcu, cfra); - if( scene->r.mode & R_FIELDS ) { + if( context.scene->r.mode & R_FIELDS ) { facf = evaluate_fcurve(fcu, cfra + 0.5); } } else { @@ -1706,88 +1769,57 @@ static ImBuf* seq_render_effect_strip_impl( early_out = sh.early_out(seq, fac, facf); - if (early_out == -1) { /* no input needed */ - out = sh.execute(bmain, scene, seq, cfra, fac, facf, - seqrectx, seqrecty, render_size, - 0, 0, 0); - goto finish; - } - - - must_preprocess = input_have_to_preprocess( - scene, seq, cfra, seqrectx, seqrecty); - switch (early_out) { - case 0: + case EARLY_NO_INPUT: + out = sh.execute(context, seq, cfra, fac, facf, + NULL, NULL, NULL); break; - case 1: - if (seq->seq1) { - ibuf[0] = seq_render_strip(bmain, scene, seq->seq1, cfra, - render_size, - seqrectx, seqrecty); + case EARLY_DO_EFFECT: + for(i=0; i<3; i++) { + if(input[i]) + ibuf[i] = seq_render_strip( + context, input[i], cfra); + } + + if (ibuf[0] && ibuf[1]) { + out = sh.execute(context, seq, cfra, fac, facf, + ibuf[0], ibuf[1], ibuf[2]); + } + break; + case EARLY_USE_INPUT_1: + if (input[0]) { + ibuf[0] = seq_render_strip(context, input[0], cfra); } if (ibuf[0]) { - if (must_preprocess) { + if (input_have_to_preprocess(context, seq, cfra)) { out = IMB_dupImBuf(ibuf[0]); } else { out = ibuf[0]; IMB_refImBuf(out); } } - goto finish; - case 2: - if (seq->seq2) { - ibuf[1] = seq_render_strip(bmain, scene, seq->seq2, cfra, - render_size, - seqrectx, seqrecty); + break; + case EARLY_USE_INPUT_2: + if (input[1]) { + ibuf[1] = seq_render_strip(context, input[1], cfra); } if (ibuf[1]) { - if (must_preprocess) { + if (input_have_to_preprocess(context, seq, cfra)) { out = IMB_dupImBuf(ibuf[1]); } else { out = ibuf[1]; IMB_refImBuf(out); } } - goto finish; - default: - goto finish; - } - - if (seq->seq1) { - ibuf[0] = seq_render_strip(bmain, scene, seq->seq1, cfra, - render_size, - seqrectx, seqrecty); - } - - if (seq->seq2) { - ibuf[1] = seq_render_strip(bmain, scene, seq->seq2, cfra, - render_size, - seqrectx, seqrecty); - } - - if (seq->seq3) { - ibuf[2] = seq_render_strip(bmain, scene, seq->seq3, cfra, - render_size, - seqrectx, seqrecty); - } - - if (!ibuf[0] || !ibuf[1]) { - goto finish; + break; } - out = sh.execute(bmain, scene, seq, cfra, fac, facf, seqrectx, seqrecty, - render_size, - ibuf[0], ibuf[1], ibuf[2]); - -finish: for (i = 0; i < 3; i++) { IMB_freeImBuf(ibuf[i]); } - if (!out) { - out = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, 32, IB_rect, 0); + if (out == NULL) { + out = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect); } return out; @@ -1795,15 +1827,16 @@ finish: static ImBuf * seq_render_scene_strip_impl( - Main *bmain, Scene * scene, Sequence * seq, float nr, int seqrectx, int seqrecty) + SeqRenderData context, Sequence * seq, float nr) { - ImBuf * ibuf = 0; + ImBuf * ibuf = NULL; float frame= seq->sfra + nr + seq->anim_startofs; float oldcfra; Object *oldcamera; ListBase oldmarkers; - /* Hack! This function can be called from do_render_seq(), in that case + /* Old info: + Hack! This function can be called from do_render_seq(), in that case the seq->scene can already have a Render initialized with same name, so we have to use a default name. (compositor uses scene name to find render). @@ -1815,9 +1848,27 @@ static ImBuf * seq_render_scene_strip_impl( and since G.rendering is uhm, gone... (Peter) */ + /* New info: + Using the same name for the renders works just fine as the do_render_seq() + render is not used while the scene strips are rendered. + + However rendering from UI (through sequencer_preview_area_draw) can crash in + very many cases since other renders (material preview, an actual render etc.) + can be started while this sequence preview render is running. The only proper + solution is to make the sequencer preview render a proper job, which can be + stopped when needed. This would also give a nice progress bar for the preview + space so that users know there's something happening. + + As a result the active scene now only uses OpenGL rendering for the sequencer + preview. This is far from nice, but is the only way to prevent crashes at this + time. + + -jahka + */ + int rendering = G.rendering; int doseq; - int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : (scene->r.seq_flag & R_SEQ_GL_PREV); + int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : /*(scene->r.seq_flag & R_SEQ_GL_PREV)*/ 1; int have_seq= FALSE; Scene *sce= seq->scene; /* dont refer to seq->scene above this point!, it can be NULL */ int sce_valid= FALSE; @@ -1834,8 +1885,8 @@ static ImBuf * seq_render_scene_strip_impl( oldcamera= seq->scene->camera; /* prevent eternal loop */ - doseq= scene->r.scemode & R_DOSEQ; - scene->r.scemode &= ~R_DOSEQ; + doseq= context.scene->r.scemode & R_DOSEQ; + context.scene->r.scemode &= ~R_DOSEQ; seq->scene->r.cfra= frame; if(seq->scene_camera) @@ -1849,27 +1900,34 @@ static ImBuf * seq_render_scene_strip_impl( seq->scene->markers.first= seq->scene->markers.last= NULL; #endif - if(sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (seq->scene == scene || have_seq==0) && seq->scene->camera) { + if(sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (seq->scene == context.scene || have_seq==0) && seq->scene->camera) { + /* for old scened this can be uninitialized, should probably be added to do_versions at some point if the functionality stays */ + if(context.scene->r.seq_prev_type==0) + context.scene->r.seq_prev_type = 3 /* ==OB_SOLID */; + /* opengl offscreen render */ - scene_update_for_newframe(bmain, seq->scene, seq->scene->lay); - ibuf= sequencer_view3d_cb(seq->scene, seqrectx, seqrecty, IB_rect, - scene->r.seq_prev_type); + scene_update_for_newframe(context.bmain, seq->scene, seq->scene->lay); + ibuf= sequencer_view3d_cb(seq->scene, context.rectx, context.recty, IB_rect, context.scene->r.seq_prev_type); } else { - Render *re; + Render *re = RE_GetRender(sce->id.name); RenderResult rres; - - if(rendering) - re= RE_NewRender(" do_build_seq_ibuf"); - else - re= RE_NewRender(sce->id.name); - - RE_BlenderFrame(re, bmain, sce, NULL, sce->lay, frame); + + /* XXX: this if can be removed when sequence preview rendering uses the job system */ + if(rendering || context.scene != sce) { + if(re==NULL) + re= RE_NewRender(sce->id.name); + + RE_BlenderFrame(re, context.bmain, sce, NULL, sce->lay, frame, FALSE); + + /* restore previous state after it was toggled on & off by RE_BlenderFrame */ + G.rendering = rendering; + } RE_AcquireResultImage(re, &rres); if(rres.rectf) { - ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0); + ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat); memcpy(ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty); if(rres.rectz) { addzbuffloatImBuf(ibuf); @@ -1881,7 +1939,7 @@ static ImBuf * seq_render_scene_strip_impl( IMB_convert_profile(ibuf, IB_PROFILE_SRGB); } else if (rres.rect32) { - ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0); + ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect); memcpy(ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty); } @@ -1891,10 +1949,12 @@ static ImBuf * seq_render_scene_strip_impl( } /* restore */ - scene->r.scemode |= doseq; + context.scene->r.scemode |= doseq; seq->scene->r.cfra = oldcfra; seq->scene->camera= oldcamera; + if(frame != oldcfra) + scene_update_for_newframe(context.bmain, seq->scene, seq->scene->lay); #ifdef DURIAN_CAMERA_SWITCH /* stooping to new low's in hackyness :( */ @@ -1904,186 +1964,152 @@ static ImBuf * seq_render_scene_strip_impl( return ibuf; } -static ImBuf * seq_render_strip(Main *bmain, Scene *scene, Sequence * seq, float cfra, - int render_size, - int seqrectx, int seqrecty) +static ImBuf * seq_render_strip(SeqRenderData context, Sequence * seq, float cfra) { + ImBuf * ibuf = NULL; char name[FILE_MAXDIR+FILE_MAXFILE]; - int use_preprocess = input_have_to_preprocess( - scene, seq, cfra, seqrectx, seqrecty); - ImBuf * ibuf = seq_stripelem_cache_get( - seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF); + int use_preprocess = input_have_to_preprocess(context, seq, cfra); float nr = give_stripelem_index(seq, cfra); + /* all effects are handled similarly with the exception of speed effect */ + int type = (seq->type & SEQ_EFFECT && seq->type != SEQ_SPEED) ? SEQ_EFFECT : seq->type; - /* currently, we cache preprocessed images */ - if (ibuf) { + ibuf = seq_stripelem_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); + + /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF, + but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */ + if (ibuf) use_preprocess = FALSE; - } - if(seq->type == SEQ_META) { - ImBuf * meta_ibuf = 0; + if (ibuf == NULL) + ibuf = copy_from_ibuf_still(context, seq, nr); + + if (ibuf == NULL) + ibuf = seq_proxy_fetch(context, seq, cfra); - if (ibuf == 0) { - ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - } + if(ibuf == NULL) switch(type) { + case SEQ_META: + { + ImBuf * meta_ibuf = NULL; - if(!ibuf && seq->seqbase.first) { - meta_ibuf = seq_render_strip_stack( - bmain, scene, - &seq->seqbase, seq->start + nr, 0, - render_size, seqrectx, seqrecty); - } + if(seq->seqbase.first) + meta_ibuf = seq_render_strip_stack( + context, &seq->seqbase, + seq->start + nr, 0); - if(!ibuf && meta_ibuf) { - ibuf = meta_ibuf; - if(ibuf && use_preprocess) { - struct ImBuf * i = IMB_dupImBuf(ibuf); + if(meta_ibuf) { + ibuf = meta_ibuf; + if(ibuf && use_preprocess) { + struct ImBuf * i = IMB_dupImBuf(ibuf); - IMB_freeImBuf(ibuf); + IMB_freeImBuf(ibuf); - ibuf = i; + ibuf = i; + } } + break; } - } else if(seq->type == SEQ_SPEED) { - ImBuf * child_ibuf = 0; - - if (ibuf == 0) { - ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - } + case SEQ_SPEED: + { + ImBuf * child_ibuf = NULL; - if (ibuf == 0) { float f_cfra; - SpeedControlVars * s - = (SpeedControlVars *)seq->effectdata; + SpeedControlVars * s = (SpeedControlVars *)seq->effectdata; - sequence_effect_speed_rebuild_map(scene, seq, 0); + sequence_effect_speed_rebuild_map(context.scene,seq, 0); /* weeek! */ f_cfra = seq->start + s->frameMap[(int) nr]; - child_ibuf = seq_render_strip(bmain, scene, seq->seq1, f_cfra, - render_size, - seqrectx, seqrecty); - } + child_ibuf = seq_render_strip(context,seq->seq1,f_cfra); - if (!ibuf && child_ibuf) { - ibuf = child_ibuf; - if(ibuf && use_preprocess) { - struct ImBuf * i = IMB_dupImBuf(ibuf); + if (child_ibuf) { + ibuf = child_ibuf; + if(ibuf && use_preprocess) { + struct ImBuf * i = IMB_dupImBuf(ibuf); - IMB_freeImBuf(ibuf); + IMB_freeImBuf(ibuf); - ibuf = i; + ibuf = i; + } } + break; } - } else if(seq->type & SEQ_EFFECT) { - /* should the effect be recalculated? */ - - if (ibuf == 0) { - ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - } - - if(ibuf == 0) { - ibuf = seq_render_effect_strip_impl( - bmain, scene, cfra, seq, render_size, - seqrectx, seqrecty); + case SEQ_EFFECT: + { + ibuf = seq_render_effect_strip_impl(context, seq, cfra); + break; } - } else if(seq->type == SEQ_IMAGE) { - StripElem * s_elem = give_stripelem(seq, cfra); - - if(ibuf == 0 && s_elem) { - BLI_join_dirfile(name, seq->strip->dir, s_elem->name); - BLI_path_abs(name, G.sce); + case SEQ_IMAGE: + { + StripElem * s_elem = give_stripelem(seq, cfra); - ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - } + if (s_elem) { + BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); + BLI_path_abs(name, G.main->name); + } - if (ibuf == 0) { - ibuf = copy_from_ibuf_still(seq,nr,seqrectx,seqrecty); - } + if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) { + /* we don't need both (speed reasons)! */ + if (ibuf->rect_float && ibuf->rect) + imb_freerectImBuf(ibuf); - if (ibuf == 0 && s_elem && - (ibuf = IMB_loadiffname(name, IB_rect))) { - /* we don't need both (speed reasons)! */ - if (ibuf->rect_float && ibuf->rect) - imb_freerectImBuf(ibuf); + /* all sequencer color is done in SRGB space, linear gives odd crossfades */ + if(ibuf->profile == IB_PROFILE_LINEAR_RGB) + IMB_convert_profile(ibuf, IB_PROFILE_NONE); - /* all sequencer color is done in SRGB space, linear gives odd crossfades */ - if(ibuf->profile == IB_PROFILE_LINEAR_RGB) - IMB_convert_profile(ibuf, IB_PROFILE_NONE); + copy_to_ibuf_still(context, seq, nr, ibuf); - copy_to_ibuf_still(seq, nr, ibuf); - } - } else if(seq->type == SEQ_MOVIE) { - if(ibuf == 0) { - ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - - } - - if (ibuf == 0) { - ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty); + s_elem->orig_width = ibuf->x; + s_elem->orig_height = ibuf->y; + } + break; } - - if (ibuf == 0) { - if(seq->anim==0) { - BLI_join_dirfile(name, - seq->strip->dir, - seq->strip->stripdata->name); - BLI_path_abs(name, G.sce); + case SEQ_MOVIE: + { + if(seq->anim==NULL) { + BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_abs(name, G.main->name); - seq->anim = openanim( - name, IB_rect | - ((seq->flag & SEQ_FILTERY) - ? IB_animdeinterlace : 0)); + seq->anim = openanim(name, IB_rect | + ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0)); } + if(seq->anim) { - IMB_anim_set_preseek(seq->anim, - seq->anim_preseek); - ibuf = IMB_anim_absolute(seq->anim, - nr - + seq->anim_startofs); + IMB_anim_set_preseek(seq->anim, seq->anim_preseek); + ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs); /* we don't need both (speed reasons)! */ - if (ibuf && ibuf->rect_float - && ibuf->rect) { + if (ibuf && ibuf->rect_float && ibuf->rect) imb_freerectImBuf(ibuf); + if (ibuf) { + seq->strip->stripdata->orig_width = ibuf->x; + seq->strip->stripdata->orig_height = ibuf->y; } - } - copy_to_ibuf_still(seq, nr, ibuf); - } - - } else if(seq->type == SEQ_SCENE) { // scene can be NULL after deletions - if (ibuf == 0) { - ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - } - if (ibuf == 0) { - ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty); + copy_to_ibuf_still(context, seq, nr, ibuf); + break; } - - if (ibuf == 0) { - ibuf = seq_render_scene_strip_impl(bmain, scene, seq, nr, - seqrectx, seqrecty); + case SEQ_SCENE: + { // scene can be NULL after deletions + ibuf = seq_render_scene_strip_impl(context, seq, nr); + + /* Scene strips update all animation, so we need to restore original state.*/ + BKE_animsys_evaluate_all_animation(context.bmain, cfra); - copy_to_ibuf_still(seq, nr, ibuf); + copy_to_ibuf_still(context, seq, nr, ibuf); + break; } } - if (!ibuf) { - ibuf = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, 32, IB_rect, 0); - } + if (ibuf == NULL) + ibuf = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect); - if (ibuf->x != seqrectx || ibuf->y != seqrecty) { + if (ibuf->x != context.rectx || ibuf->y != context.recty) use_preprocess = TRUE; - } - if (use_preprocess) { - ibuf = input_preprocess(scene, seq, cfra, seqrectx, - seqrecty, ibuf); - } + if (use_preprocess) + ibuf = input_preprocess(context, seq, cfra, ibuf); - seq_stripelem_cache_put( - seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF, ibuf); + seq_stripelem_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf); return ibuf; } @@ -2099,9 +2125,7 @@ static int seq_must_swap_input_in_blend_mode(Sequence * seq) /* bad hack, to fix crazy input ordering of those two effects */ - if (seq->blend_mode == SEQ_ALPHAOVER || - seq->blend_mode == SEQ_ALPHAUNDER || - seq->blend_mode == SEQ_OVERDROP) { + if (ELEM3(seq->blend_mode, SEQ_ALPHAOVER, SEQ_ALPHAUNDER, SEQ_OVERDROP)) { swap_input = TRUE; } @@ -2114,34 +2138,32 @@ static int seq_get_early_out_for_blend_mode(Sequence * seq) float facf = seq->blend_opacity / 100.0; int early_out = sh.early_out(seq, facf, facf); - if (early_out < 1) { + if (ELEM(early_out, EARLY_DO_EFFECT, EARLY_NO_INPUT)) { return early_out; } if (seq_must_swap_input_in_blend_mode(seq)) { - if (early_out == 2) { - return 1; - } else if (early_out == 1) { - return 2; + if (early_out == EARLY_USE_INPUT_2) { + return EARLY_USE_INPUT_1; + } else if (early_out == EARLY_USE_INPUT_1) { + return EARLY_USE_INPUT_2; } } return early_out; } static ImBuf* seq_render_strip_stack( - Main *bmain, Scene *scene, ListBase *seqbasep, float cfra, int chanshown, - int render_size, int seqrectx, int seqrecty) + SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown) { Sequence* seq_arr[MAXSEQ+1]; int count; int i; - ImBuf* out = 0; + ImBuf* out = NULL; - count = get_shown_sequences(seqbasep, cfra, chanshown, - (Sequence **)&seq_arr); + count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr); - if (!count) { - return 0; + if (count == 0) { + return NULL; } #if 0 /* commentind since this breaks keyframing, since it resets the value on draw */ @@ -2152,22 +2174,17 @@ static ImBuf* seq_render_strip_stack( } #endif - out = seq_stripelem_cache_get( - seq_arr[count - 1], - seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP); + out = seq_stripelem_cache_get(context, seq_arr[count - 1], + cfra, SEQ_STRIPELEM_IBUF_COMP); if (out) { return out; } if(count == 1) { - out = seq_render_strip(bmain, scene, seq_arr[0], - cfra, render_size, - seqrectx, seqrecty); - seq_stripelem_cache_put( - seq_arr[0], - seqrectx, seqrecty, cfra, - SEQ_STRIPELEM_IBUF_COMP, out); + out = seq_render_strip(context, seq_arr[0], cfra); + seq_stripelem_cache_put(context, seq_arr[0], cfra, + SEQ_STRIPELEM_IBUF_COMP, out); return out; } @@ -2175,43 +2192,34 @@ static ImBuf* seq_render_strip_stack( for (i = count - 1; i >= 0; i--) { int early_out; - Sequence * seq = seq_arr[i]; + Sequence *seq = seq_arr[i]; out = seq_stripelem_cache_get( - seq, - seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP); + context, seq, cfra, SEQ_STRIPELEM_IBUF_COMP); if (out) { break; } if (seq->blend_mode == SEQ_BLEND_REPLACE) { - out = seq_render_strip(bmain, scene, seq, cfra, - render_size, - seqrectx, seqrecty); + out = seq_render_strip(context, seq, cfra); break; } early_out = seq_get_early_out_for_blend_mode(seq); switch (early_out) { - case -1: - case 2: - out = seq_render_strip(bmain, scene, seq, cfra, - render_size, - seqrectx, seqrecty); + case EARLY_NO_INPUT: + case EARLY_USE_INPUT_2: + out = seq_render_strip(context, seq, cfra); break; - case 1: + case EARLY_USE_INPUT_1: if (i == 0) { - out = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); + out = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect); } break; - case 0: + case EARLY_DO_EFFECT: if (i == 0) { - out = seq_render_strip(bmain, scene, seq, cfra, - render_size, - seqrectx, seqrecty); + out = seq_render_strip(context, seq, cfra); } break; @@ -2221,9 +2229,8 @@ static ImBuf* seq_render_strip_stack( } } - seq_stripelem_cache_put( - seq_arr[i], seqrectx, seqrecty, cfra, - SEQ_STRIPELEM_IBUF_COMP, out); + seq_stripelem_cache_put(context, seq_arr[i], cfra, + SEQ_STRIPELEM_IBUF_COMP, out); i++; @@ -2231,37 +2238,30 @@ static ImBuf* seq_render_strip_stack( for (; i < count; i++) { Sequence * seq = seq_arr[i]; - if (seq_get_early_out_for_blend_mode(seq) == 0) { + if (seq_get_early_out_for_blend_mode(seq) == EARLY_DO_EFFECT) { struct SeqEffectHandle sh = get_sequence_blend(seq); ImBuf * ibuf1 = out; - ImBuf * ibuf2 = seq_render_strip(bmain, scene, seq, cfra, - render_size, - seqrectx, seqrecty); + ImBuf * ibuf2 = seq_render_strip(context, seq, cfra); float facf = seq->blend_opacity / 100.0; - int swap_input - = seq_must_swap_input_in_blend_mode(seq); - - int x= seqrectx; - int y= seqrecty; + int swap_input = seq_must_swap_input_in_blend_mode(seq); if (swap_input) { - out = sh.execute(bmain, scene, seq, cfra, - facf, facf, x, y, render_size, - ibuf2, ibuf1, 0); + out = sh.execute(context, seq, cfra, + facf, facf, + ibuf2, ibuf1, NULL); } else { - out = sh.execute(bmain, scene, seq, cfra, - facf, facf, x, y, render_size, - ibuf1, ibuf2, 0); + out = sh.execute(context, seq, cfra, + facf, facf, + ibuf1, ibuf2, NULL); } IMB_freeImBuf(ibuf1); IMB_freeImBuf(ibuf2); } - seq_stripelem_cache_put( - seq_arr[i], seqrectx, seqrecty, cfra, - SEQ_STRIPELEM_IBUF_COMP, out); + seq_stripelem_cache_put(context, seq_arr[i], cfra, + SEQ_STRIPELEM_IBUF_COMP, out); } return out; @@ -2272,9 +2272,9 @@ static ImBuf* seq_render_strip_stack( * you have to free after usage! */ -ImBuf *give_ibuf_seq(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) +ImBuf *give_ibuf_seq(SeqRenderData context, float cfra, int chanshown) { - Editing *ed= seq_give_editing(scene, FALSE); + Editing *ed= seq_give_editing(context.scene, FALSE); int count; ListBase *seqbasep; @@ -2288,19 +2288,18 @@ ImBuf *give_ibuf_seq(Main *bmain, Scene *scene, int rectx, int recty, int cfra, seqbasep= ed->seqbasep; } - return seq_render_strip_stack( - bmain, scene, seqbasep, cfra, chanshown, render_size, rectx, recty); + return seq_render_strip_stack(context, seqbasep, cfra, chanshown); } -ImBuf *give_ibuf_seqbase(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size, ListBase *seqbasep) +ImBuf *give_ibuf_seqbase(SeqRenderData context, float cfra, int chanshown, ListBase *seqbasep) { - return seq_render_strip_stack(bmain, scene, seqbasep, cfra, chanshown, render_size, rectx, recty); + return seq_render_strip_stack(context, seqbasep, cfra, chanshown); } -ImBuf *give_ibuf_seq_direct(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq) +ImBuf *give_ibuf_seq_direct(SeqRenderData context, float cfra, Sequence *seq) { - return seq_render_strip(bmain, scene, seq, cfra, render_size, rectx, recty); + return seq_render_strip(context, seq, cfra); } #if 0 @@ -2350,9 +2349,9 @@ typedef struct PrefetchQueueElem { int rectx; int recty; - int cfra; + float cfra; int chanshown; - int render_size; + int preview_render_size; int monoton_cfra; @@ -2400,7 +2399,7 @@ static void *seq_prefetch_thread(void * This_) if (e->cfra >= s_last) { e->ibuf = give_ibuf_seq_impl(This->scene, e->rectx, e->recty, e->cfra, e->chanshown, - e->render_size); + e->preview_render_size); } pthread_mutex_lock(&queue_lock); @@ -2510,8 +2509,7 @@ static void seq_stop_threads() } #endif -void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, - int render_size) +void give_ibuf_prefetch_request(SeqRenderData context, float cfra, int chanshown) { PrefetchQueueElem *e; if (seq_thread_shutdown) { @@ -2519,11 +2517,11 @@ void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, } e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem"); - e->rectx = rectx; - e->recty = recty; + e->rectx = context.rectx; + e->recty = context.recty; e->cfra = cfra; e->chanshown = chanshown; - e->render_size = render_size; + e->preview_render_size = context.preview_render_size; e->monoton_cfra = monoton_cfra++; pthread_mutex_lock(&queue_lock); @@ -2566,13 +2564,13 @@ static void seq_wait_for_prefetch_ready() } #endif -ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) +ImBuf *give_ibuf_seq_threaded(SeqRenderData context, float cfra, int chanshown) { PrefetchQueueElem *e = NULL; int found_something = FALSE; if (seq_thread_shutdown) { - return give_ibuf_seq(bmain, scene, rectx, recty, cfra, chanshown, render_size); + return give_ibuf_seq(context, cfra, chanshown); } while (!e) { @@ -2582,9 +2580,9 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i for (e = prefetch_done.first; e; e = e->next) { if (cfra == e->cfra && chanshown == e->chanshown && - rectx == e->rectx && - recty == e->recty && - render_size == e->render_size) { + context.rectx == e->rectx && + context.recty == e->recty && + context.preview_render_size == e->preview_render_size) { success = TRUE; found_something = TRUE; break; @@ -2595,9 +2593,9 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i for (e = prefetch_wait.first; e; e = e->next) { if (cfra == e->cfra && chanshown == e->chanshown && - rectx == e->rectx && - recty == e->recty && - render_size == e->render_size) { + context.rectx == e->rectx && + context.recty == e->recty && + context.preview_render_size == e->preview_render_size) { found_something = TRUE; break; } @@ -2612,9 +2610,9 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i if (tslot->current && cfra == tslot->current->cfra && chanshown == tslot->current->chanshown && - rectx == tslot->current->rectx && - recty == tslot->current->recty && - render_size== tslot->current->render_size){ + context.rectx == tslot->current->rectx && + context.recty == tslot->current->recty && + context.preview_render_size== tslot->current->preview_render_size){ found_something = TRUE; break; } @@ -2644,7 +2642,7 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i } } - return e ? e->ibuf : 0; + return e ? e->ibuf : NULL; } /* Functions to free imbuf and anim data on changes */ @@ -2653,7 +2651,7 @@ static void free_anim_seq(Sequence *seq) { if(seq->anim) { IMB_free_anim(seq->anim); - seq->anim = 0; + seq->anim = NULL; } } @@ -2697,8 +2695,7 @@ void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage, } } if(seq->type==SEQ_META) { - free_imbuf_seq(scene, &seq->seqbase, FALSE, - keep_file_handles); + free_imbuf_seq(scene, &seq->seqbase, FALSE, keep_file_handles); } if(seq->type==SEQ_SCENE) { /* FIXME: recurs downwards, @@ -2822,11 +2819,7 @@ void seq_tx_set_final_right(Sequence *seq, int val) since they work a bit differently to normal image seq's (during transform) */ int seq_single_check(Sequence *seq) { - if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR - || seq->type == SEQ_MULTICAM)) - return 1; - else - return 0; + return (seq->len==1 && ELEM3(seq->type, SEQ_IMAGE, SEQ_COLOR, SEQ_MULTICAM)); } /* check if the selected seq's reference unselected seq's */ @@ -2848,17 +2841,20 @@ int seqbase_isolated_sel_check(ListBase *seqbase) /* test relationships */ for(seq= seqbase->first; seq; seq= seq->next) { + if((seq->type & SEQ_EFFECT)==0) + continue; + if(seq->flag & SELECT) { - if(seq->type & SEQ_EFFECT) { - if(seq->seq1 && (seq->seq1->flag & SELECT)==0) return FALSE; - if(seq->seq2 && (seq->seq2->flag & SELECT)==0) return FALSE; - if(seq->seq3 && (seq->seq3->flag & SELECT)==0) return FALSE; - } + if( (seq->seq1 && (seq->seq1->flag & SELECT)==0) || + (seq->seq2 && (seq->seq2->flag & SELECT)==0) || + (seq->seq3 && (seq->seq3->flag & SELECT)==0) ) + return FALSE; } - else if(seq->type & SEQ_EFFECT) { - if(seq->seq1 && (seq->seq1->flag & SELECT)) return FALSE; - if(seq->seq2 && (seq->seq2->flag & SELECT)) return FALSE; - if(seq->seq3 && (seq->seq3->flag & SELECT)) return FALSE; + else { + if( (seq->seq1 && (seq->seq1->flag & SELECT)) || + (seq->seq2 && (seq->seq2->flag & SELECT)) || + (seq->seq3 && (seq->seq3->flag & SELECT)) ) + return FALSE; } } @@ -2935,12 +2931,8 @@ int seq_tx_test(Sequence * seq) static int seq_overlap(Sequence *seq1, Sequence *seq2) { - if(seq1 != seq2) - if(seq1->machine==seq2->machine) - if(((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0) - return 1; - - return 0; + return (seq1 != seq2 && seq1->machine == seq2->machine && + ((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0); } int seq_test_overlap(ListBase * seqbasep, Sequence *test) @@ -2958,7 +2950,7 @@ int seq_test_overlap(ListBase * seqbasep, Sequence *test) } -static void seq_translate(Scene *evil_scene, Sequence *seq, int delta) +void seq_translate(Scene *evil_scene, Sequence *seq, int delta) { seq_offset_animdata(evil_scene, seq, delta); seq->start += delta; @@ -2973,6 +2965,28 @@ static void seq_translate(Scene *evil_scene, Sequence *seq, int delta) calc_sequence_disp(evil_scene, seq); } +Sequence *seq_foreground_frame_get(Scene *scene, int frame) +{ + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq, *best_seq=NULL; + int best_machine = -1; + + if(!ed) return NULL; + + for (seq=ed->seqbasep->first; seq; seq= seq->next) { + if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame) + continue; + /* only use elements you can see - not */ + if (ELEM5(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_COLOR)) { + if (seq->machine > best_machine) { + best_seq = seq; + best_machine = seq->machine; + } + } + } + return best_seq; +} + /* return 0 if there werent enough space */ int shuffle_seq(ListBase * seqbasep, Sequence *test, Scene *evil_scene) { @@ -3107,7 +3121,7 @@ static void seq_update_muting_recursive(Scene *scene, ListBase *seqbasep, Sequen seq_update_muting_recursive(scene, &seq->seqbase, metaseq, seqmute); } - else if((seq->type == SEQ_SOUND) || (seq->type == SEQ_SCENE)) { + else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) { if(seq->scene_sound) { sound_mute_scene_sound(scene, seq->scene_sound, seqmute); } @@ -3210,7 +3224,7 @@ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) for (fcu= scene->adt->action->curves.first; fcu; fcu= fcu->next) { if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) { - int i; + unsigned int i; for (i = 0; i < fcu->totvert; i++) { BezTriple *bezt= &fcu->bezt[i]; bezt->vec[0][0] += ofs; @@ -3247,7 +3261,7 @@ void seq_dupe_animdata(Scene *scene, char *name_from, char *name_to) BKE_animdata_fix_paths_rename(&scene->id, scene->adt, "sequence_editor.sequences_all", name_from, name_to, 0, 0, 0); /* add the original fcurves back */ - addlisttolist(&scene->adt->action->curves, &lb); + BLI_movelisttolist(&scene->adt->action->curves, &lb); } /* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */ @@ -3385,6 +3399,7 @@ Sequence *alloc_sequence(ListBase *lb, int cfra, int machine) seq->mul= 1.0; seq->blend_opacity = 100.0; seq->volume = 1.0f; + seq->scene_sound = NULL; return seq; } @@ -3395,7 +3410,6 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo Scene *scene= CTX_data_scene(C); /* only for active seq */ Sequence *seq; Strip *strip; - StripElem *se; seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); seq->type= SEQ_IMAGE; @@ -3406,7 +3420,7 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo strip->len = seq->len = seq_load->len ? seq_load->len : 1; strip->us= 1; - strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir)); seq_load_apply(scene, seq, seq_load); @@ -3476,14 +3490,14 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo Scene *scene= CTX_data_scene(C); /* only for sound */ char path[sizeof(seq_load->path)]; - Sequence *seq, *soundseq; /* generic strip vars */ + Sequence *seq; /* generic strip vars */ Strip *strip; StripElem *se; struct anim *an; BLI_strncpy(path, seq_load->path, sizeof(path)); - BLI_path_abs(path, G.sce); + BLI_path_abs(path, G.main->name); an = openanim(path, IB_rect); @@ -3515,7 +3529,7 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo int start_frame_back= seq_load->start_frame; seq_load->channel++; - soundseq = sequencer_add_sound_strip(C, seqbasep, seq_load); + sequencer_add_sound_strip(C, seqbasep, seq_load); seq_load->start_frame= start_frame_back; seq_load->channel--; @@ -3531,8 +3545,9 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo } -static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag) +static Sequence *seq_dupli(struct Scene *scene, struct Scene *scene_to, Sequence *seq, int dupe_flag) { + Scene *sce_audio= scene_to ? scene_to : scene; Sequence *seqn = MEM_dupallocN(seq); seq->tmp = seqn; @@ -3550,6 +3565,7 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag) if (seq->strip->proxy) { seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy); + seqn->strip->proxy->anim = NULL; } if (seq->strip->color_balance) { @@ -3558,24 +3574,24 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag) } if(seq->type==SEQ_META) { - seqn->strip->stripdata = 0; + seqn->strip->stripdata = NULL; - seqn->seqbase.first= seqn->seqbase.last= 0; + seqn->seqbase.first= seqn->seqbase.last= NULL; /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */ /* - seq_dupli_recursive(&seq->seqbase,&seqn->seqbase);*/ } else if(seq->type == SEQ_SCENE) { - seqn->strip->stripdata = 0; + seqn->strip->stripdata = NULL; if(seq->scene_sound) - seqn->scene_sound = sound_scene_add_scene_sound(scene, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); + seqn->scene_sound = sound_scene_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); } else if(seq->type == SEQ_MOVIE) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); - seqn->anim= 0; + seqn->anim= NULL; } else if(seq->type == SEQ_SOUND) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); if(seq->scene_sound) - seqn->scene_sound = sound_add_scene_sound(scene, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); + seqn->scene_sound = sound_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); seqn->sound->id.us++; } else if(seq->type == SEQ_IMAGE) { @@ -3593,7 +3609,7 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag) sh.copy(seq, seqn); } - seqn->strip->stripdata = 0; + seqn->strip->stripdata = NULL; } else { fprintf(stderr, "Aiiiiekkk! sequence type not " @@ -3610,13 +3626,13 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag) return seqn; } -Sequence * seq_dupli_recursive(struct Scene *scene, Sequence * seq, int dupe_flag) +Sequence * seq_dupli_recursive(struct Scene *scene, struct Scene *scene_to, Sequence * seq, int dupe_flag) { - Sequence * seqn = seq_dupli(scene, seq, dupe_flag); + Sequence * seqn = seq_dupli(scene, scene_to, seq, dupe_flag); if (seq->type == SEQ_META) { Sequence *s; for(s= seq->seqbase.first; s; s = s->next) { - Sequence *n = seq_dupli_recursive(scene, s, dupe_flag); + Sequence *n = seq_dupli_recursive(scene, scene_to, s, dupe_flag); if (n) { BLI_addtail(&seqn->seqbase, n); } @@ -3625,16 +3641,16 @@ Sequence * seq_dupli_recursive(struct Scene *scene, Sequence * seq, int dupe_fla return seqn; } -void seqbase_dupli_recursive(Scene *scene, ListBase *nseqbase, ListBase *seqbase, int dupe_flag) +void seqbase_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag) { Sequence *seq; - Sequence *seqn = 0; + Sequence *seqn = NULL; Sequence *last_seq = seq_active_get(scene); for(seq= seqbase->first; seq; seq= seq->next) { seq->tmp= NULL; if((seq->flag & SELECT) || (dupe_flag & SEQ_DUPE_ALL)) { - seqn = seq_dupli(scene, seq, dupe_flag); + seqn = seq_dupli(scene, scene_to, seq, dupe_flag); if (seqn) { /*should never fail */ if(dupe_flag & SEQ_DUPE_CONTEXT) { seq->flag &= ~SEQ_ALLSEL; @@ -3643,7 +3659,7 @@ void seqbase_dupli_recursive(Scene *scene, ListBase *nseqbase, ListBase *seqbase BLI_addtail(nseqbase, seqn); if(seq->type==SEQ_META) - seqbase_dupli_recursive(scene, &seqn->seqbase, &seq->seqbase, dupe_flag); + seqbase_dupli_recursive(scene, scene_to, &seqn->seqbase, &seq->seqbase, dupe_flag); if(dupe_flag & SEQ_DUPE_CONTEXT) { if (seq == last_seq) { diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 454a82c2ad3..5311f3a9c38 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -1,5 +1,5 @@ -/** - * shrinkwrap.c +/* + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): André Pinto + * Contributor(s): Andr Pinto * * ***** END GPL LICENSE BLOCK ***** */ @@ -41,25 +41,21 @@ #include "DNA_scene_types.h" #include "DNA_windowmanager_types.h" +#include "BLI_editVert.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + #include "BKE_shrinkwrap.h" #include "BKE_DerivedMesh.h" #include "BKE_lattice.h" -#include "BKE_utildefines.h" + #include "BKE_deform.h" #include "BKE_mesh.h" #include "BKE_subsurf.h" #include "BKE_mesh.h" #include "BKE_tessmesh.h" -#include "BLI_math.h" -#include "BLI_editVert.h" - - - /* Util macros */ -#define TO_STR(a) #a -#define JOIN(a,b) a##b - #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n")) /* Benchmark macros */ @@ -90,20 +86,18 @@ typedef void ( *Shrinkwrap_ForeachVertexCallback) (DerivedMesh *target, float *c /* get derived mesh */ //TODO is anyfunction that does this? returning the derivedFinal witouth we caring if its in edit mode or not? -DerivedMesh *object_get_derived_final(struct Scene *scene, Object *ob, CustomDataMask dataMask) +DerivedMesh *object_get_derived_final(Object *ob) { Mesh *me= ob->data; BMEditMesh *em = me->edit_btmesh; if (em) { - DerivedMesh *final = NULL; - editbmesh_get_derived_cage_and_final(scene, ob, em, &final, dataMask); - - return final; + DerivedMesh *dm = em->derivedFinal; + return dm; } - else - return mesh_get_derived_final(scene, ob, dataMask); + + return ob->derivedFinal; } /* Space transform */ @@ -111,7 +105,7 @@ void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float { float itarget[4][4]; invert_m4_m4(itarget, target); - mul_serie_m4(data->local2target, itarget, local, 0, 0, 0, 0, 0, 0); + mul_serie_m4(data->local2target, itarget, local, NULL, NULL, NULL, NULL, NULL, NULL); invert_m4_m4(data->target2local, data->local2target); } @@ -264,22 +258,26 @@ int normal_projection_project_vertex(char options, const float *vert, const floa BLI_bvhtree_ray_cast(tree, co, no, 0.0f, &hit_tmp, callback, userdata); - if(hit_tmp.index != -1) - { - float dot = INPR( dir, hit_tmp.no); - - if(((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f) - || ((options & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && dot >= 0.0f)) - return FALSE; //Ignore hit - + if(hit_tmp.index != -1) { + /* invert the normal first so face culling works on rotated objects */ + if(transf) { + space_transform_invert_normal(transf, hit_tmp.no); + } - //Inverting space transform (TODO make coeherent with the initial dist readjust) - if(transf) - { - space_transform_invert( transf, hit_tmp.co ); - space_transform_invert_normal( transf, hit_tmp.no ); + if (options & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE|MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) { + /* apply backface */ + const float dot= dot_v3v3(dir, hit_tmp.no); + if( ((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f) || + ((options & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && dot >= 0.0f) + ) { + return FALSE; /* Ignore hit */ + } + } - hit_tmp.dist = len_v3v3( (float*)vert, hit_tmp.co ); + if(transf) { + /* Inverting space transform (TODO make coeherent with the initial dist readjust) */ + space_transform_invert(transf, hit_tmp.co); + hit_tmp.dist = len_v3v3((float *)vert, hit_tmp.co); } memcpy(hit, &hit_tmp, sizeof(hit_tmp) ); @@ -289,7 +287,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa } -static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct Scene *scene) +static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) { int i; @@ -334,12 +332,14 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct S if(calc->smd->auxTarget) { - auxMesh = object_get_derived_final(scene, calc->smd->auxTarget, CD_MASK_BAREMESH); + auxMesh = object_get_derived_final(calc->smd->auxTarget); + if(!auxMesh) + return; space_transform_setup( &local2aux, calc->ob, calc->smd->auxTarget); } //After sucessufuly build the trees, start projection vertexs - if( bvhtree_from_mesh_faces(&treeData, calc->target, calc->keepDist, 4, 6) + if( bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 4, 6) && (auxMesh == NULL || bvhtree_from_mesh_faces(&auxData, auxMesh, 0.0, 4, 6))) { @@ -388,10 +388,10 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct S } //Project over negative direction of axis - if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR) + if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR && hit.index == -1) { - float inv_no[3] = { -tmp_no[0], -tmp_no[1], -tmp_no[2] }; - + float inv_no[3]; + negate_v3_v3(inv_no, tmp_no); if(auxData.tree) normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData); @@ -402,6 +402,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct S if(hit.index != -1) { + madd_v3_v3v3fl(hit.co, hit.co, tmp_no, calc->keepDist); interp_v3_v3v3(co, co, hit.co, weight); } } @@ -500,7 +501,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) } /* Main shrinkwrap function */ -void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) +void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { DerivedMesh *ss_mesh = NULL; @@ -531,7 +532,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Scene *scene, Object if(smd->target) { - calc.target = object_get_derived_final(scene, smd->target, CD_MASK_BAREMESH); + calc.target = object_get_derived_final(smd->target); //TODO there might be several "bugs" on non-uniform scales matrixs //because it will no longer be nearest surface, not sphere projection @@ -555,8 +556,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Scene *scene, Object //Using vertexs positions/normals as if a subsurface was applied if(smd->subsurfLevels) { - SubsurfModifierData ssmd; - memset(&ssmd, 0, sizeof(ssmd)); + SubsurfModifierData ssmd= {{0}}; ssmd.subdivType = ME_CC_SUBSURF; //catmull clark ssmd.levels = smd->subsurfLevels; //levels @@ -589,7 +589,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Scene *scene, Object break; case MOD_SHRINKWRAP_PROJECT: - BENCH(shrinkwrap_calc_normal_projection(&calc, scene)); + BENCH(shrinkwrap_calc_normal_projection(&calc)); break; case MOD_SHRINKWRAP_NEAREST_VERTEX: diff --git a/source/blender/blenkernel/intern/sketch.c b/source/blender/blenkernel/intern/sketch.c index 7e39cdd1196..8917d2946bd 100644 --- a/source/blender/blenkernel/intern/sketch.c +++ b/source/blender/blenkernel/intern/sketch.c @@ -1,4 +1,4 @@ -/** +/* * * $Id$ * @@ -31,9 +31,10 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_utildefines.h" #include "BKE_sketch.h" -#include "BKE_utildefines.h" + #include "DNA_userdef_types.h" @@ -53,7 +54,7 @@ void freeSketch(SK_Sketch *sketch) MEM_freeN(sketch); } -SK_Sketch* createSketch() +SK_Sketch* createSketch(void) { SK_Sketch *sketch; @@ -101,7 +102,7 @@ void sk_freeStroke(SK_Stroke *stk) MEM_freeN(stk); } -SK_Stroke* sk_createStroke() +SK_Stroke* sk_createStroke(void) { SK_Stroke *stk; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index c6993e933c2..b2f8831cced 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -1,4 +1,4 @@ -/** +/* * smoke.c * * $Id$ @@ -48,6 +48,7 @@ #include "BLI_edgehash.h" #include "BLI_kdtree.h" #include "BLI_kdopbvh.h" +#include "BLI_utildefines.h" #include "BKE_bvhutils.h" #include "BKE_cdderivedmesh.h" @@ -58,7 +59,7 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_smoke.h" -#include "BKE_utildefines.h" + #include "DNA_customdata_types.h" #include "DNA_group_types.h" @@ -94,7 +95,7 @@ static void tend ( void ) { QueryPerformanceCounter ( &liCurrentTime ); } -static double tval() +static double tval( void ) { return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart)* (double)1000.0/(double)liFrequency.QuadPart )); } @@ -110,6 +111,8 @@ static void tend ( void ) { gettimeofday ( &_tend,&tz ); } + +#if 0 // unused static double tval() { double t1, t2; @@ -118,6 +121,7 @@ static double tval() return t2-t1; } #endif +#endif struct Object; struct Scene; @@ -131,7 +135,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) #define TRI_UVOFFSET (1./4.) -int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm) +static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm) { if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid) { @@ -177,7 +181,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive if(size[0] > size[1]) { - if(size[0] > size[1]) + if(size[0] > size[2]) { scale = res / size[0]; smd->domain->dx = size[0] / res; @@ -187,11 +191,11 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive } else { - scale = res / size[1]; - smd->domain->dx = size[1] / res; - smd->domain->res[1] = res; + scale = res / size[2]; + smd->domain->dx = size[2] / res; + smd->domain->res[2] = res; smd->domain->res[0] = (int)(size[0] * scale + 0.5); - smd->domain->res[2] = (int)(size[2] * scale + 0.5); + smd->domain->res[1] = (int)(size[1] * scale + 0.5); } } else @@ -435,7 +439,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) } /*! init triangle divisions */ -void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *faces, int numfaces, int numtris, int **tridivs, float cell_len) +void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFace *faces, int numfaces, int numtris, int **tridivs, float cell_len) { // mTriangleDivs1.resize( faces.size() ); // mTriangleDivs2.resize( faces.size() ); @@ -554,8 +558,6 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd) BKE_ptcache_free_list(&(smd->domain->ptcaches[0])); smd->domain->point_cache[0] = NULL; - BKE_ptcache_free_list(&(smd->domain->ptcaches[1])); - smd->domain->point_cache[1] = NULL; MEM_freeN(smd->domain); smd->domain = NULL; @@ -629,9 +631,6 @@ void smokeModifier_reset(struct SmokeModifierData *smd) smd->domain->fluid = NULL; } - smd->domain->point_cache[0]->flag |= PTCACHE_OUTDATED; - smd->domain->point_cache[1]->flag |= PTCACHE_OUTDATED; - smokeModifier_reset_turbulence(smd); smd->time = -1; @@ -698,10 +697,9 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->point_cache[0]->flag |= PTCACHE_DISK_CACHE; smd->domain->point_cache[0]->step = 1; - smd->domain->point_cache[1] = BKE_ptcache_add(&(smd->domain->ptcaches[1])); - smd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE; - smd->domain->point_cache[1]->step = 1; - + /* Deprecated */ + smd->domain->point_cache[1] = NULL; + smd->domain->ptcaches[1].first = smd->domain->ptcaches[1].last = NULL; /* set some standard values */ smd->domain->fluid = NULL; smd->domain->wt = NULL; @@ -779,6 +777,9 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData tsmd->domain->viewsettings = smd->domain->viewsettings; tsmd->domain->fluid_group = smd->domain->fluid_group; tsmd->domain->coll_group = smd->domain->coll_group; + tsmd->domain->vorticity = smd->domain->vorticity; + tsmd->domain->time_scale = smd->domain->time_scale; + tsmd->domain->border_collisions = smd->domain->border_collisions; MEM_freeN(tsmd->domain->effector_weights); tsmd->domain->effector_weights = MEM_dupallocN(smd->domain->effector_weights); @@ -787,6 +788,8 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData tsmd->flow->temp = smd->flow->temp; tsmd->flow->psys = smd->flow->psys; tsmd->flow->type = smd->flow->type; + tsmd->flow->flags = smd->flow->flags; + tsmd->flow->vel_multi = smd->flow->vel_multi; } else if (tsmd->coll) { ; /* leave it as initialised, collision settings is mostly caches */ @@ -800,20 +803,25 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix static int get_lamp(Scene *scene, float *light) { Base *base_tmp = NULL; - for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) - { - if(base_tmp->object->type == OB_LAMP) - { - Lamp *la = (Lamp *)base_tmp->object->data; - - if(la->type == LA_LOCAL) - { - VECCOPY(light, base_tmp->object->obmat[3]); - return 1; - } - } - } - return 0; + int found_lamp = 0; + + // try to find a lamp, preferably local + for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) { + if(base_tmp->object->type == OB_LAMP) { + Lamp *la = base_tmp->object->data; + + if(la->type == LA_LOCAL) { + copy_v3_v3(light, base_tmp->object->obmat[3]); + return 1; + } + else if(!found_lamp) { + copy_v3_v3(light, base_tmp->object->obmat[3]); + found_lamp = 1; + } + } + } + + return found_lamp; } static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) @@ -822,9 +830,109 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) GroupObject *go = NULL; Base *base = NULL; + // do collisions, needs to be done before emission, so that smoke isn't emitted inside collision cells + if(1) + { + Object *otherobj = NULL; + ModifierData *md = NULL; + + if(sds->coll_group) // we use groups since we have 2 domains + go = sds->coll_group->gobject.first; + else + base = scene->base.first; + + while(base || go) + { + otherobj = NULL; + if(sds->coll_group) + { + if(go->ob) + otherobj = go->ob; + } + else + otherobj = base->object; + if(!otherobj) + { + if(sds->coll_group) + go = go->next; + else + base= base->next; + continue; + } + md = modifiers_findByType(otherobj, eModifierType_Smoke); + + // check for active smoke modifier + if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) + { + SmokeModifierData *smd2 = (SmokeModifierData *)md; + + if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points) + { + // we got nice collision object + SmokeCollSettings *scs = smd2->coll; + size_t i, j; + unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid); + + for(i = 0; i < scs->numpoints; i++) + { + int badcell = 0; + size_t index = 0; + int cell[3]; + + // 1. get corresponding cell + get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, &scs->points[3 * i], cell, 0); + + // check if cell is valid (in the domain boundary) + for(j = 0; j < 3; j++) + if((cell[j] > sds->res[j] - 1) || (cell[j] < 0)) + { + badcell = 1; + break; + } + + if(badcell) + continue; + // 2. set cell values (heat, density and velocity) + index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); + + // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]); + // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index); + obstacles[index] = 1; + // for moving gobstacles + /* + const LbmFloat maxVelVal = 0.1666; + const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5; + + LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); + { + const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; + USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); + if(usqr>maxusqr) { + // cutoff at maxVelVal + for(int jj=0; jj<3; jj++) { + if(objvel[jj]>0.) objvel[jj] = maxVelVal; + if(objvel[jj]<0.) objvel[jj] = -maxVelVal; + } + } + } + const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); + const LbmVec oldov=objvel; // debug + objvel = vec2L((*pNormals)[n]) *dp; + */ + } + } + } + + if(sds->coll_group) + go = go->next; + else + base= base->next; + } + } + // do flows and fluids if(1) - { + { Object *otherobj = NULL; ModifierData *md = NULL; if(sds->fluid_group) // we use groups since we have 2 domains @@ -866,9 +974,8 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) if(sfs && sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected { + ParticleSimulationData sim; ParticleSystem *psys = sfs->psys; - ParticleSettings *part=psys->part; - ParticleData *pa = NULL; int p = 0; float *density = smoke_get_density(sds->fluid); float *bigdensity = smoke_turbulence_get_density(sds->wt); @@ -888,6 +995,10 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) */ float *temp_emission_map = NULL; + sim.scene = scene; + sim.ob = otherobj; + sim.psys = psys; + // initialize temp emission map if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) { @@ -900,19 +1011,26 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) } // mostly copied from particle code - for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) - { - int cell[3]; - size_t i = 0; - size_t index = 0; - int badcell = 0; - if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue; - else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue; - else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; + for(p=0; p<psys->totpart; p++) + { + int cell[3]; + size_t i = 0; + size_t index = 0; + int badcell = 0; + ParticleKey state; + + if(psys->particles[p].flag & (PARS_NO_DISP|PARS_UNEXIST)) + continue; + + state.time = smd->time; + + if(psys_get_particle_state(&sim, p, &state, 0) == 0) + continue; + // VECCOPY(pos, pa->state.co); // mul_m4_v3(ob->imat, pos); // 1. get corresponding cell - get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, pa->state.co, cell, 0); + get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, state.co, cell, 0); // check if cell is valid (in the domain boundary) for(i = 0; i < 3; i++) { @@ -926,7 +1044,7 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) continue; // 2. set cell values (heat, density and velocity) index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); - if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index] & 2)) // this is inflow + if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index])) // this is inflow { // heat[index] += sfs->temp * 0.1; // density[index] += sfs->density * 0.1; @@ -938,9 +1056,9 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) // Uses particle velocity as initial velocity for smoke if(sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO)) { - velocity_x[index] = pa->state.vel[0]*sfs->vel_multi; - velocity_y[index] = pa->state.vel[1]*sfs->vel_multi; - velocity_z[index] = pa->state.vel[2]*sfs->vel_multi; + velocity_x[index] = state.vel[0]*sfs->vel_multi; + velocity_y[index] = state.vel[1]*sfs->vel_multi; + velocity_z[index] = state.vel[2]*sfs->vel_multi; } } else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow @@ -1165,107 +1283,8 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) pdEndEffectors(&effectors); } - // do collisions - if(1) - { - Object *otherobj = NULL; - ModifierData *md = NULL; - - if(sds->coll_group) // we use groups since we have 2 domains - go = sds->coll_group->gobject.first; - else - base = scene->base.first; - - while(base || go) - { - otherobj = NULL; - if(sds->coll_group) - { - if(go->ob) - otherobj = go->ob; - } - else - otherobj = base->object; - if(!otherobj) - { - if(sds->coll_group) - go = go->next; - else - base= base->next; - continue; - } - md = modifiers_findByType(otherobj, eModifierType_Smoke); - - // check for active smoke modifier - if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) - { - SmokeModifierData *smd2 = (SmokeModifierData *)md; - - if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points) - { - // we got nice collision object - SmokeCollSettings *scs = smd2->coll; - size_t i, j; - unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid); - - for(i = 0; i < scs->numpoints; i++) - { - int badcell = 0; - size_t index = 0; - int cell[3]; - - // 1. get corresponding cell - get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, &scs->points[3 * i], cell, 0); - - // check if cell is valid (in the domain boundary) - for(j = 0; j < 3; j++) - if((cell[j] > sds->res[j] - 1) || (cell[j] < 0)) - { - badcell = 1; - break; - } - - if(badcell) - continue; - // 2. set cell values (heat, density and velocity) - index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); - - // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]); - // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index); - obstacles[index] = 1; - // for moving gobstacles - /* - const LbmFloat maxVelVal = 0.1666; - const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5; - - LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); - { - const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; - USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); - if(usqr>maxusqr) { - // cutoff at maxVelVal - for(int jj=0; jj<3; jj++) { - if(objvel[jj]>0.) objvel[jj] = maxVelVal; - if(objvel[jj]<0.) objvel[jj] = -maxVelVal; - } - } - } - const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); - const LbmVec oldov=objvel; // debug - objvel = vec2L((*pNormals)[n]) *dp; - */ - } - } - } - - if(sds->coll_group) - go = go->next; - else - base= base->next; - } - } } -void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) +void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm) { if((smd->type & MOD_SMOKE_TYPE_FLOW)) { @@ -1320,82 +1339,77 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM float light[3]; PointCache *cache = NULL; PTCacheID pid; - PointCache *cache_wt = NULL; - PTCacheID pid_wt; int startframe, endframe, framenr; float timescale; - int cache_result = 0, cache_result_wt = 0; - int did_init = 0; framenr = scene->r.cfra; - printf("time: %d\n", scene->r.cfra); + //printf("time: %d\n", scene->r.cfra); cache = sds->point_cache[0]; BKE_ptcache_id_from_smoke(&pid, ob, smd); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); - cache_wt = sds->point_cache[1]; - BKE_ptcache_id_from_smoke_turbulence(&pid_wt, ob, smd); - - if(!smd->domain->fluid) + if(!smd->domain->fluid || framenr == startframe) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); - BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_OUTDATED); + BKE_ptcache_validate(cache, framenr); + cache->flag &= ~PTCACHE_REDO_NEEDED; } - if(framenr < startframe) + if(!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD)==0 && (cache->flag & PTCACHE_BAKED)==0) return; - if(framenr > endframe) - return; + smd->domain->flags &= ~MOD_SMOKE_FILE_LOAD; - if(!smd->domain->fluid && (framenr != startframe)) + CLAMP(framenr, startframe, endframe); + + /* If already viewing a pre/after frame, no need to reload */ + if ((smd->time == framenr) && (framenr != scene->r.cfra)) return; // printf("startframe: %d, framenr: %d\n", startframe, framenr); - if(!(did_init = smokeModifier_init(smd, ob, scene, dm))) + if(smokeModifier_init(smd, ob, scene, dm)==0) { printf("bad smokeModifier_init\n"); return; } /* try to read from cache */ - cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec); - // printf("cache_result: %d\n", cache_result); - - if(cache_result == PTCACHE_READ_EXACT) - { + if(BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) { BKE_ptcache_validate(cache, framenr); - - if(sds->wt) - { - cache_result_wt = BKE_ptcache_read_cache(&pid_wt, (float)framenr, scene->r.frs_sec); - - if(cache_result_wt == PTCACHE_READ_EXACT) - { - BKE_ptcache_validate(cache_wt, framenr); - - return; - } - else - { - ; /* don't return in the case we only got low res cache but no high res cache */ - /* we still need to calculate the high res cache */ - } - } - else - return; + smd->time = framenr; + return; } + + /* only calculate something when we advanced a single frame */ + if(framenr != (int)smd->time+1) + return; - /* only calculate something when we advanced a frame */ - if(framenr == smd->time) + /* don't simulate if viewing start frame, but scene frame is not real start frame */ + if (framenr != scene->r.cfra) return; tstart(); smoke_calc_domain(scene, ob, smd); + + /* if on second frame, write cache for first frame */ + if((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) { + // create shadows straight after domain initialization so we get nice shadows for startframe, too + if(get_lamp(scene, light)) + smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx); + + if(sds->wt) + { + if(sds->flags & MOD_SMOKE_DISSOLVE) + smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); + smoke_turbulence_step(sds->wt, sds->fluid); + } + + BKE_ptcache_write(&pid, startframe); + } // set new time smd->time = scene->r.cfra; @@ -1412,39 +1426,24 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); smoke_step(sds->fluid, smd->time, scene->r.frs_sec / scene->r.frs_sec_base); } - else - { - /* Smoke did not load cache and was not reset but we're on startframe */ - /* So now reinit the smoke since it was not done yet */ - if(did_init == 2) - { - smokeModifier_reset(smd); - smokeModifier_init(smd, ob, scene, dm); - } - } - // create shadows before writing cache so we get nice shadows for startframe, too + // create shadows before writing cache so they get stored if(get_lamp(scene, light)) smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx); - - BKE_ptcache_validate(cache, framenr); - BKE_ptcache_write_cache(&pid, framenr); if(sds->wt) { - if(framenr!=startframe) - { - if(sds->flags & MOD_SMOKE_DISSOLVE) - smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); - smoke_turbulence_step(sds->wt, sds->fluid); - } - - BKE_ptcache_validate(cache_wt, framenr); - BKE_ptcache_write_cache(&pid_wt, framenr); + if(sds->flags & MOD_SMOKE_DISSOLVE) + smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); + smoke_turbulence_step(sds->wt, sds->fluid); } + + BKE_ptcache_validate(cache, framenr); + if(framenr != startframe) + BKE_ptcache_write(&pid, framenr); tend(); - printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() ); + //printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() ); } } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index d9cb03be37f..d197541c620 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -63,6 +63,7 @@ variables on the UI for now #include "DNA_meshdata_types.h" #include "BLI_math.h" +#include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_threads.h" #include "BLI_cellalloc.h" @@ -161,7 +162,7 @@ typedef struct SB_thread_context { #define BFF_CLOSEVERT 2 /* collider vertex repulses face */ -float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb parameters and sizes */ +static float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb parameters and sizes */ /* local prototypes */ static void free_softbody_intern(SoftBody *sb); @@ -172,7 +173,7 @@ static void Vec3PlusStVec(float *v, float s, float *v1); /*physical unit of force is [kg * m / sec^2]*/ -static float sb_grav_force_scale(Object *ob) +static float sb_grav_force_scale(Object *UNUSED(ob)) /* since unit of g is [m/sec^2] and F = mass * g we rescale unit mass of node to 1 gramm put it to a function here, so we can add user options later without touching simulation code */ @@ -180,7 +181,7 @@ static float sb_grav_force_scale(Object *ob) return (0.001f); } -static float sb_fric_force_scale(Object *ob) +static float sb_fric_force_scale(Object *UNUSED(ob)) /* rescaling unit of drag [1 / sec] to somehow reasonable put it to a function here, so we can add user options later without touching simulation code */ @@ -261,7 +262,7 @@ float operations still /* just an ID here to reduce the prob for killing objects ** ob->sumohandle points to we should not kill :) */ -const int CCD_SAVETY = 190561; +static const int CCD_SAVETY = 190561; typedef struct ccdf_minmax{ float minx,miny,minz,maxx,maxy,maxz; @@ -549,7 +550,7 @@ static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *h } /*+++ only with deflecting set */ - if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == 0) { + if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == NULL) { DerivedMesh *dm= NULL; if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */ @@ -679,7 +680,7 @@ static void add_mesh_quad_diag_springs(Object *ob) } } -static void add_2nd_order_roller(Object *ob,float stiffness,int *counter, int addsprings) +static void add_2nd_order_roller(Object *ob,float UNUSED(stiffness), int *counter, int addsprings) { /*assume we have a softbody*/ SoftBody *sb= ob->soft; /* is supposed to be there */ @@ -698,12 +699,12 @@ static void add_2nd_order_roller(Object *ob,float stiffness,int *counter, int ad bs = sb->bspring + bp->springs[b-1]; /*nasty thing here that springs have two ends so here we have to make sure we examine the other */ - if (( v0 == bs->v1) ){ + if (v0 == bs->v1){ bpo =sb->bpoint+bs->v2; notthis = bs->v2; } else { - if (( v0 == bs->v2) ){ + if (v0 == bs->v2){ bpo =sb->bpoint+bs->v1; notthis = bs->v1; } @@ -1030,7 +1031,7 @@ static int query_external_colliders(Scene *scene, Object *me) /* +++ the aabb "force" section*/ -static int sb_detect_aabb_collisionCached( float force[3], unsigned int par_layer,struct Object *vertexowner,float time) +static int sb_detect_aabb_collisionCached( float UNUSED(force[3]), unsigned int UNUSED(par_layer),struct Object *vertexowner,float UNUSED(time)) { Object *ob; SoftBody *sb=vertexowner->soft; @@ -1095,7 +1096,7 @@ static int sb_detect_aabb_collisionCached( float force[3], unsigned int par_laye /* +++ the face external section*/ static int sb_detect_face_pointCached(float face_v1[3],float face_v2[3],float face_v3[3],float *damp, - float force[3], unsigned int par_layer,struct Object *vertexowner,float time) + float force[3], unsigned int UNUSED(par_layer),struct Object *vertexowner,float time) { Object *ob; GHash *hash; @@ -1193,7 +1194,7 @@ static int sb_detect_face_pointCached(float face_v1[3],float face_v2[3],float fa static int sb_detect_face_collisionCached(float face_v1[3],float face_v2[3],float face_v3[3],float *damp, - float force[3], unsigned int par_layer,struct Object *vertexowner,float time) + float force[3], unsigned int UNUSED(par_layer),struct Object *vertexowner,float time) { Object *ob; GHash *hash; @@ -1419,7 +1420,7 @@ static void scan_for_ext_face_forces(Object *ob,float timenow) /* +++ the spring external section*/ static int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp, - float force[3], unsigned int par_layer,struct Object *vertexowner,float time) + float force[3], unsigned int UNUSED(par_layer),struct Object *vertexowner,float time) { Object *ob; GHash *hash; @@ -1647,9 +1648,7 @@ static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow) ListBase *do_effector = NULL; do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights); - if (sb){ - _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector); - } + _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector); pdEndEffectors(&do_effector); } @@ -1657,10 +1656,10 @@ static void *exec_scan_for_ext_spring_forces(void *data) { SB_thread_context *pctx = (SB_thread_context*)data; _scan_for_ext_spring_forces(pctx->scene, pctx->ob, pctx->timenow, pctx->ifirst, pctx->ilast, pctx->do_effector); - return 0; + return NULL; } -static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,int totsprings,int *ptr_to_break_func()) +static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,int totsprings,int *UNUSED(ptr_to_break_func(void))) { ListBase *do_effector = NULL; ListBase threads; @@ -1750,7 +1749,7 @@ static int choose_winner(float*w, float* pos,float*a,float*b,float*c,float*ca,fl static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *damp, - float force[3], unsigned int par_layer,struct Object *vertexowner, + float force[3], unsigned int UNUSED(par_layer), struct Object *vertexowner, float time,float vel[3], float *intrusion) { Object *ob= NULL; @@ -2085,7 +2084,7 @@ static void dfdv_goal(int ia, int ic,float factor) for(i=0;i<3;i++) nlMatrixAdd(ia+i,ic+i,factor); } */ -static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float forcetime,int nl_flags) +static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float UNUSED(forcetime), int nl_flags) { SoftBody *sb= ob->soft; /* is supposed to be there */ BodyPoint *bp1,*bp2; @@ -2176,7 +2175,7 @@ static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float fo /* since this is definitely the most CPU consuming task here .. try to spread it */ /* core function _softbody_calc_forces_slice_in_a_thread */ /* result is int to be able to flag user break */ -static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, float forcetime, float timenow,int ifirst,int ilast,int *ptr_to_break_func(),ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor) +static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, float forcetime, float timenow,int ifirst,int ilast,int *UNUSED(ptr_to_break_func(void)),ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor) { float iks; int bb,do_selfcollision,do_springcollision,do_aero; @@ -2384,10 +2383,10 @@ static void *exec_softbody_calc_forces(void *data) { SB_thread_context *pctx = (SB_thread_context*)data; _softbody_calc_forces_slice_in_a_thread(pctx->scene, pctx->ob, pctx->forcetime, pctx->timenow, pctx->ifirst, pctx->ilast, NULL, pctx->do_effector,pctx->do_deflector,pctx->fieldfactor,pctx->windfactor); - return 0; + return NULL; } -static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float timenow,int totpoint,int *ptr_to_break_func(),struct ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor) +static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float timenow,int totpoint,int *UNUSED(ptr_to_break_func(void)),struct ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor) { ListBase threads; SB_thread_context *sb_threads; @@ -2445,7 +2444,7 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t MEM_freeN(sb_threads); } -static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow, int nl_flags) +static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow, int UNUSED(nl_flags)) { /* rule we never alter free variables :bp->vec bp->pos in here ! * this will ruin adaptive stepsize AKA heun! (BM) @@ -2453,7 +2452,8 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl SoftBody *sb= ob->soft; /* is supposed to be there */ BodyPoint *bproot; ListBase *do_effector = NULL; - float iks, gravity; + float gravity; + /* float iks; */ float fieldfactor = -1.0f, windfactor = 0.25; int do_deflector,do_selfcollision,do_springcollision,do_aero; @@ -2465,7 +2465,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); - iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */ + /* iks = 1.0f/(1.0f-sb->inspring)-1.0f; */ /* inner spring constants function */ /* UNUSED */ bproot= sb->bpoint; /* need this for proper spring addressing */ if (do_springcollision || do_aero) @@ -3823,7 +3823,7 @@ void SB_estimate_transform(Object *ob,float lloc[3],float lrot[3][3],float lscal { BodyPoint *bp; ReferenceVert *rp; - SoftBody *sb = 0; + SoftBody *sb = NULL; float (*opos)[3]; float (*rpos)[3]; float com[3],rcom[3]; @@ -4135,7 +4135,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i } /* try to read from cache */ - cache_result = BKE_ptcache_read_cache(&pid, framenr, scene->r.frs_sec); + cache_result = BKE_ptcache_read(&pid, framenr); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { softbody_to_object(ob, vertexCos, numVerts, sb->local); @@ -4143,14 +4143,14 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i BKE_ptcache_validate(cache, framenr); if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) - BKE_ptcache_write_cache(&pid, framenr); + BKE_ptcache_write(&pid, framenr); return; } else if(cache_result==PTCACHE_READ_OLD) { ; /* do nothing */ } - else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { + else if(/*ob->id.lib || */(cache->flag & PTCACHE_BAKED)) { /* "library linking & pointcaches" has to be solved properly at some point */ /* if baked and nothing in cache, do nothing */ BKE_ptcache_invalidate(cache); return; @@ -4158,7 +4158,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i /* if on second frame, write cache for first frame */ if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - BKE_ptcache_write_cache(&pid, startframe); + BKE_ptcache_write(&pid, startframe); softbody_update_positions(ob, sb, vertexCos, numVerts); @@ -4171,6 +4171,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i softbody_to_object(ob, vertexCos, numVerts, 0); BKE_ptcache_validate(cache, framenr); - BKE_ptcache_write_cache(&pid, framenr); + BKE_ptcache_write(&pid, framenr); } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 8f3b82643e0..88ca0c33624 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -55,7 +55,7 @@ static void sound_sync_callback(void* data, int mode, float time) } #endif -int sound_define_from_str(char *str) +int sound_define_from_str(const char *str) { if (BLI_strcaseeq(str, "NULL")) return AUD_NULL_DEVICE; @@ -74,7 +74,7 @@ void sound_force_device(int device) force_device = device; } -void sound_init_once() +void sound_init_once(void) { AUD_initOnce(); } @@ -110,15 +110,17 @@ void sound_init(struct Main *bmain) #ifdef WITH_JACK AUD_setSyncCallback(sound_sync_callback, bmain); +#else + (void)bmain; /* unused */ #endif } -void sound_exit() +void sound_exit(void) { AUD_exit(); } -struct bSound* sound_new_file(struct Main *bmain, char* filename) +struct bSound* sound_new_file(struct Main *bmain, const char *filename) { bSound* sound = NULL; @@ -129,7 +131,7 @@ struct bSound* sound_new_file(struct Main *bmain, char* filename) strcpy(str, filename); - path = /*bmain ? bmain->name :*/ G.sce; + path = /*bmain ? bmain->name :*/ G.main->name; BLI_path_abs(str, path); @@ -264,7 +266,7 @@ void sound_load(struct Main *bmain, struct bSound* sound) if(sound->id.lib) path = sound->id.lib->filepath; else - path = /*bmain ? bmain->name :*/ G.sce; + path = bmain->name; BLI_path_abs(fullpath, path); @@ -274,7 +276,7 @@ void sound_load(struct Main *bmain, struct bSound* sound) /* or else load it from disk */ else sound->handle = AUD_load(fullpath); - } // XXX + } // XXX unused currently #if 0 break; @@ -380,7 +382,7 @@ void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, i AUD_moveSequencer(scene->sound_scene, handle, startframe / FPS, endframe / FPS, frameskip / FPS); } -void sound_start_play_scene(struct Scene *scene) +static void sound_start_play_scene(struct Scene *scene) { scene->sound_scene_handle = AUD_play(scene->sound_scene, 1); AUD_setLoop(scene->sound_scene_handle, -1); @@ -433,9 +435,11 @@ void sound_seek_scene(struct bContext *C) if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) { - // AUD_XXX TODO: fix scrubbing, it currently doesn't stop playing if(scene->audio.flag & AUDIO_SYNC) + { + AUD_seek(scene->sound_scene_handle, CFRA / FPS); AUD_seekSequencer(scene->sound_scene_handle, CFRA / FPS); + } else AUD_seek(scene->sound_scene_handle, CFRA / FPS); AUD_resume(scene->sound_scene_handle); @@ -480,3 +484,12 @@ int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length, flo return AUD_readSound(limiter, buffer, length); AUD_unload(limiter); } + +int sound_get_channels(struct bSound* sound) +{ + AUD_SoundInfo info; + + info = AUD_getInfo(sound->playback_handle); + + return info.specs.channels; +} diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 7e3b5691177..86e901345c4 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -41,6 +41,13 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BLI_blenlib.h" +#include "BLI_edgehash.h" +#include "BLI_math.h" +#include "BLI_memarena.h" +#include "BLI_pbvh.h" +#include "BLI_utildefines.h" + #include "BKE_cdderivedmesh.h" #include "BKE_global.h" #include "BKE_mesh.h" @@ -51,11 +58,6 @@ #include "BKE_tessmesh.h" #include "BKE_utildefines.h" -#include "BLI_blenlib.h" -#include "BLI_edgehash.h" -#include "BLI_math.h" -#include "BLI_memarena.h" -#include "BLI_pbvh.h" #include "PIL_time.h" #include "BLI_array.h" @@ -73,8 +75,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int useSubsurfUv, DerivedMesh *dm); -static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm); - /// static void *arena_alloc(CCGAllocatorHDL a, int numBytes) { @@ -87,13 +87,13 @@ static void *arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSiz } return p2; } -static void arena_free(CCGAllocatorHDL a, void *ptr) { +static void arena_free(CCGAllocatorHDL UNUSED(a), void *UNUSED(ptr)) { } static void arena_release(CCGAllocatorHDL a) { BLI_memarena_free(a); } -static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAging, int useArena, int useFlatSubdiv) { +static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAging, int useArena, int UNUSED(useFlatSubdiv)) { CCGMeshIFC ifc; CCGSubSurf *ccgSS; @@ -320,7 +320,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, CCGFace **faceMap; MTFace *tf; CCGFaceIterator *fi; - int index, gridSize, gridFaces, edgeSize, totface, x, y, S; + int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S; MTFace *dmtface = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, n); MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n); @@ -337,7 +337,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, /* get some info from CCGSubSurf */ totface = ccgSubSurf_getNumFaces(uvss); - edgeSize = ccgSubSurf_getEdgeSize(uvss); + /* edgeSize = ccgSubSurf_getEdgeSize(uvss); */ /*UNUSED*/ gridSize = ccgSubSurf_getGridSize(uvss); gridFaces = gridSize - 1; @@ -1174,7 +1174,7 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med) /* this edge comes from face data */ int lastface = ccgSubSurf_getNumFaces(ss) - 1; CCGFace *f; - int x, y, grid, numVerts; + int x, y, grid /*, numVerts*/; int offset; int gridSize = ccgSubSurf_getGridSize(ss); int edgeSize = ccgSubSurf_getEdgeSize(ss); @@ -1186,7 +1186,7 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med) ++i; f = cgdm->faceMap[i].face; - numVerts = ccgSubSurf_getFaceNumVerts(f); + /* numVerts = ccgSubSurf_getFaceNumVerts(f); */ /*UNUSED*/ gridSideEdges = gridSize - 1; gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; @@ -1251,7 +1251,7 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) int gridFaces = gridSideEdges * gridSideEdges; int i; CCGFace *f; - int numVerts; + /*int numVerts;*/ int offset; int grid; int x, y; @@ -1265,7 +1265,7 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) i = cgdm->reverseFaceMap[faceNum]; f = cgdm->faceMap[i].face; - numVerts = ccgSubSurf_getFaceNumVerts(f); + /*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/ offset = faceNum - cgdm->faceMap[i].startFace; grid = offset / gridFaces; @@ -1794,7 +1794,23 @@ static void ccgDM_drawVerts(DerivedMesh *dm) { ccgFaceIterator_free(fi); glEnd(); } -static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges) { + +static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm) +{ + if(ccgdm->pbvh) { + CCGFace **faces; + int totface; + + BLI_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void***)&faces, &totface); + if(totface) { + ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface); + ccgSubSurf_updateNormals(ccgdm->ss, faces, totface); + MEM_freeN(faces); + } + } +} + +static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int UNUSED(drawAllEdges)) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss); @@ -1803,6 +1819,8 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdge int gridSize = ccgSubSurf_getGridSize(ss); int useAging; + ccgdm_pbvh_update(ccgdm); + ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL); for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { @@ -1893,25 +1911,10 @@ void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) no[1] = b_dZ*a_cX - b_dX*a_cZ; no[2] = b_dX*a_cY - b_dY*a_cX; - /* don't normalize, GL_NORMALIZE is be enabled */ + /* don't normalize, GL_NORMALIZE is enabled */ glNormal3fv(no); } -static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm) -{ - if(ccgdm->pbvh && ccgDM_use_grid_pbvh(ccgdm)) { - CCGFace **faces; - int totface; - - BLI_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void***)&faces, &totface); - if(totface) { - ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface); - ccgSubSurf_updateNormals(ccgdm->ss, faces, totface); - MEM_freeN(faces); - } - } -} - /* Only used by non-editmesh types */ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], int fast, int (*setMaterial)(int, void *attribs)) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; @@ -2006,7 +2009,7 @@ static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo CCGSubSurf *ss = cgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); GPUVertexAttribs gattribs; - DMVertexAttribs attribs; + DMVertexAttribs attribs= {{{0}}}; MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); int gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; @@ -2018,13 +2021,10 @@ static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo ccgdm_pbvh_update(cgdm); doDraw = 0; - numVerts = 0; matnr = -1; transp = GPU_get_material_blend_mode(); orig_transp = transp; - memset(&attribs, 0, sizeof(attribs)); - #define PASSATTRIB(dx, dy, vert) { \ if(attribs.totorco) { \ index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize); \ @@ -2042,7 +2042,7 @@ static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo } \ if(attribs.tottang) { \ float *tang = attribs.tang.array[a*4 + vert]; \ - glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ + glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \ } \ } @@ -2070,7 +2070,7 @@ static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); } - if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) { + if(!doDraw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) && !setDrawOptions(userData, origIndex))) { a += gridFaces*gridFaces*numVerts; continue; } @@ -2268,9 +2268,12 @@ static void cgdm_drawFacesTex_common(DerivedMesh *dm, if(drawParams) flag = drawParams(tf, mcol!=NULL, mat_nr); - else + else if (index != ORIGINDEX_NONE) flag= (drawParamsMapped)? drawParamsMapped(userData, index): 1; - + else + flag= GPU_enable_material(mat_nr, NULL) ? 1:0; + + if (flag == 0) { /* flag 0 == the face is hidden or invisible */ if(tf) tf += gridFaces*gridFaces*numVerts; if(mcol) mcol += gridFaces*gridFaces*numVerts*4; @@ -2410,7 +2413,7 @@ static void cgdm_drawUVEdges(DerivedMesh *dm) } } -static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) { +static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs)) { CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = cgdm->ss; MCol *mcol= NULL; @@ -2442,10 +2445,14 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u mcol += gridFaces*gridFaces*numVerts*4; } - if (index!=-1) { - int draw; - draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, index, &drawSmooth); - + { + int draw= 1; + + if(index == ORIGINDEX_NONE) + draw= setMaterial(faceFlags ? faceFlags[origIndex*2 + 1] + 1: 1, NULL); /* XXX, no faceFlags no material */ + else if (setDrawOptions) + draw= setDrawOptions(userData, index, &drawSmooth); + if (draw) { if (draw==2) { glEnable(GL_POLYGON_STIPPLE); @@ -2846,14 +2853,14 @@ static void ccgdm_create_grids(DerivedMesh *dm) DMGridAdjacency *gridAdjacency, *adj; CCGFace **gridFaces; int *gridOffset; - int index, numFaces, numGrids, S, gIndex, gridSize; + int index, numFaces, numGrids, S, gIndex /*, gridSize*/; if(cgdm->gridData) return; numGrids = ccgDM_getNumGrids(dm); numFaces = ccgSubSurf_getNumFaces(ss); - gridSize = ccgDM_getGridSize(dm); + /*gridSize = ccgDM_getGridSize(dm);*/ /*UNUSED*/ /* compute offset into grid array for each face */ gridOffset = MEM_mallocN(sizeof(int)*numFaces, "cgdm.gridOffset"); @@ -2939,28 +2946,10 @@ static ListBase *ccgDM_getFaceMap(Object *ob, DerivedMesh *dm) return ccgdm->fmap; } -static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm) -{ - ModifierData *md; - MultiresModifierData *mmd= ccgdm->multires.mmd; - - /* in sync with sculpt mode, only use multires grid pbvh if we are - the last enabled modifier in the stack, otherwise we use the base - mesh */ - if(!mmd) - return 0; - - for(md=mmd->modifier.next; md; md= md->next) - if(modifier_isEnabled(mmd->modifier.scene, md, eModifierMode_Realtime)) - return 0; - - return 1; -} - static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) { CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; - int gridSize, numGrids, grid_pbvh; + int gridSize, numGrids; if(!ob) { ccgdm->pbvh= NULL; @@ -2970,20 +2959,15 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) if(!ob->sculpt) return NULL; - grid_pbvh = ccgDM_use_grid_pbvh(ccgdm); - if(ob->sculpt->pbvh) { - if(grid_pbvh) { - /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm - but this can be freed on ccgdm release, this updates the pointers - when the ccgdm gets remade, the assumption is that the topology - does not change. */ - ccgdm_create_grids(dm); - BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void**)ccgdm->gridFaces); - } + /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm + but this can be freed on ccgdm release, this updates the pointers + when the ccgdm gets remade, the assumption is that the topology + does not change. */ + ccgdm_create_grids(dm); + BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void**)ccgdm->gridFaces); ccgdm->pbvh = ob->sculpt->pbvh; - ccgdm->pbvh_draw = grid_pbvh; } if(ccgdm->pbvh) @@ -2992,25 +2976,14 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) /* no pbvh exists yet, we need to create one. only in case of multires we build a pbvh over the modified mesh, in other cases the base mesh is being sculpted, so we build a pbvh from that. */ - if(grid_pbvh) { - ccgdm_create_grids(dm); - - gridSize = ccgDM_getGridSize(dm); - numGrids = ccgDM_getNumGrids(dm); + ccgdm_create_grids(dm); - ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new(); - BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, - numGrids, gridSize, (void**)ccgdm->gridFaces); - ccgdm->pbvh_draw = 1; - } - else if(ob->type == OB_MESH) { - Mesh *me= ob->data; + gridSize = ccgDM_getGridSize(dm); + numGrids = ccgDM_getNumGrids(dm); - ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new(); - BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert, - me->totface, me->totvert); - ccgdm->pbvh_draw = 0; - } + ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new(); + BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, + numGrids, gridSize, (void**)ccgdm->gridFaces); return ccgdm->pbvh; } @@ -3037,17 +3010,16 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int edgeSize, has_edge_origindex; int gridSize; int gridFaces, gridCuts; - int gridSideVerts; + /*int gridSideVerts;*/ int gridSideEdges; int numTex, numCol; int gridInternalEdges; - float *w = NULL, one = 1.0f; + float *w = NULL; WeightTable wtable = {0}; MCol *mcol; MEdge *medge = NULL, medge2; MFace *mface = NULL; MPoly *mpoly = NULL; - int *orig_indices; DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM, ccgSubSurf_getNumFinalVerts(ss), @@ -3167,7 +3139,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, edgeSize = ccgSubSurf_getEdgeSize(ss); gridSize = ccgSubSurf_getGridSize(ss); gridFaces = gridSize - 1; - gridSideVerts = gridSize - 2; gridCuts = gridSize - 2; /*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */ gridSideEdges = gridSize - 1; diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c index 1b720c1adaa..052b545cfb4 100644 --- a/source/blender/blenkernel/intern/suggestions.c +++ b/source/blender/blenkernel/intern/suggestions.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -54,7 +54,7 @@ static int txttl_cmp(const char *first, const char *second, int len) { return cmp; } -static void txttl_free_suggest() { +static void txttl_free_suggest(void) { SuggItem *item, *prev; for (item = suggestions.last; item; item=prev) { prev = item->prev; @@ -66,7 +66,7 @@ static void txttl_free_suggest() { suggestions.top = 0; } -static void txttl_free_docs() { +static void txttl_free_docs(void) { if (documentation) { MEM_freeN(documentation); documentation = NULL; @@ -77,7 +77,7 @@ static void txttl_free_docs() { /* General tool functions */ /**************************/ -void free_texttools() { +void free_texttools(void) { txttl_free_suggest(); txttl_free_docs(); } @@ -88,7 +88,7 @@ void texttool_text_set_active(Text *text) { activeToolText = text; } -void texttool_text_clear() { +void texttool_text_clear(void) { free_texttools(); activeToolText = NULL; } @@ -191,15 +191,15 @@ void texttool_suggest_prefix(const char *prefix) { } } -void texttool_suggest_clear() { +void texttool_suggest_clear(void) { txttl_free_suggest(); } -SuggItem *texttool_suggest_first() { +SuggItem *texttool_suggest_first(void) { return suggestions.firstmatch; } -SuggItem *texttool_suggest_last() { +SuggItem *texttool_suggest_last(void) { return suggestions.lastmatch; } @@ -207,11 +207,11 @@ void texttool_suggest_select(SuggItem *sel) { suggestions.selected = sel; } -SuggItem *texttool_suggest_selected() { +SuggItem *texttool_suggest_selected(void) { return suggestions.selected; } -int *texttool_suggest_top() { +int *texttool_suggest_top(void) { return &suggestions.top; } @@ -243,10 +243,10 @@ void texttool_docs_show(const char *docs) { documentation[len] = '\0'; } -char *texttool_docs_get() { +char *texttool_docs_get(void) { return documentation; } -void texttool_docs_clear() { +void texttool_docs_clear(void) { txttl_free_docs(); } diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 19bc853276a..1bd41c7aa86 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -36,6 +36,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "DNA_constraint_types.h" #include "DNA_controller_types.h" @@ -51,9 +52,9 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_text.h" -#include "BKE_utildefines.h" -#ifndef DISABLE_PYTHON + +#ifdef WITH_PYTHON #include "BPY_extern.h" #endif @@ -93,7 +94,7 @@ TMARK_EDITALL is set the group ID defines which other markers should be edited. The mrk->clr field is used to visually group markers where the flags may not match. A template system, for example, may allow editing of repeating tokens (in one group) but include other marked positions (in another group) all in the -same template with the same colour. +same template with the same color. Undo -- @@ -167,12 +168,12 @@ void free_text(Text *text) if(text->name) MEM_freeN(text->name); MEM_freeN(text->undo_buf); -#ifndef DISABLE_PYTHON - if (text->compiled) BPY_free_compiled_text(text); +#ifdef WITH_PYTHON + if (text->compiled) BPY_text_free_code(text); #endif } -Text *add_empty_text(char *name) +Text *add_empty_text(const char *name) { Main *bmain= G.main; Text *ta; @@ -241,7 +242,7 @@ int reopen_text(Text *text) if (!text || !text->name) return 0; BLI_strncpy(str, text->name, FILE_MAXDIR+FILE_MAXFILE); - BLI_path_abs(str, G.sce); + BLI_path_abs(str, G.main->name); fp= fopen(str, "r"); if(fp==NULL) return 0; @@ -279,7 +280,6 @@ int reopen_text(Text *text) text->mtime= st.st_mtime; text->nlines=0; - i=0; llen=0; for(i=0; i<len; i++) { if (buffer[i]=='\n') { @@ -325,7 +325,7 @@ int reopen_text(Text *text) return 1; } -Text *add_text(char *file, const char *relpath) +Text *add_text(const char *file, const char *relpath) { Main *bmain= G.main; FILE *fp; @@ -521,7 +521,7 @@ void unlink_text(Main *bmain, Text *text) } if(update) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } /* pynodes */ @@ -559,7 +559,7 @@ void clear_text(Text *text) /* called directly from rna */ txt_make_dirty(text); } -void write_text(Text *text, char *str) /* called directly from rna */ +void write_text(Text *text, const char *str) /* called directly from rna */ { int oldstate; @@ -585,7 +585,7 @@ static void make_new_line (TextLine *line, char *newline) line->format= NULL; } -static TextLine *txt_new_line(char *str) +static TextLine *txt_new_line(const char *str) { TextLine *tmp; @@ -683,8 +683,8 @@ int txt_get_span (TextLine *from, TextLine *to) static void txt_make_dirty (Text *text) { text->flags |= TXT_ISDIRTY; -#ifndef DISABLE_PYTHON - if (text->compiled) BPY_free_compiled_text(text); +#ifdef WITH_PYTHON + if (text->compiled) BPY_text_free_code(text); #endif } @@ -991,8 +991,8 @@ void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel) if ((*linep)->next) *linep= (*linep)->next; else break; } - if (ch>(*linep)->len) - ch= (*linep)->len; + if (ch>(unsigned int)((*linep)->len)) + ch= (unsigned int)((*linep)->len); *charp= ch; if(!sel) txt_pop_sel(text); @@ -1232,7 +1232,7 @@ int txt_find_string(Text *text, char *findstr, int wrap) { TextLine *tl, *startl; char *s= NULL; - int oldcl, oldsl, oldcc, oldsc; + int oldcl, oldsl; if (!text || !text->curl || !text->sell) return 0; @@ -1241,8 +1241,6 @@ int txt_find_string(Text *text, char *findstr, int wrap) oldcl= txt_get_span(text->lines.first, text->curl); oldsl= txt_get_span(text->lines.first, text->sell); tl= startl= text->sell; - oldcc= text->curc; - oldsc= text->selc; s= strstr(&tl->line[text->selc], findstr); while (!s) { @@ -1431,7 +1429,7 @@ void txt_print_undo(Text *text) { int i= 0; int op; - char *ops; + const char *ops; int linep, charp; dump_buffer(text); @@ -2219,7 +2217,6 @@ static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb) } while (mrk && mrk->lineno==lineno); } if (lineno==-1) lineno= txt_get_span(text->lines.first, lineb); - if (!mrk) mrk= text->markers.first; tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string"); @@ -2470,7 +2467,7 @@ void indent(Text *text) int len, num; char *tmp; - char *add = "\t"; + const char *add = "\t"; int indentlen = 1; /* hardcoded: TXT_TABSIZE = 4 spaces: */ @@ -2531,7 +2528,7 @@ void indent(Text *text) void unindent(Text *text) { int num = 0; - char *remove = "\t"; + const char *remove = "\t"; int indent = 1; /* hardcoded: TXT_TABSIZE = 4 spaces: */ @@ -2694,7 +2691,7 @@ int setcurr_tab_spaces (Text *text, int space) const char *word = ":"; const char *comm = "#"; const char indent= (text->flags & TXT_TABSTOSPACES) ? ' ' : '\t'; - static char *back_words[]= {"return", "break", "continue", "pass", "yield", NULL}; + static const char *back_words[]= {"return", "break", "continue", "pass", "yield", NULL}; if (!text) return 0; if (!text->curl) return 0; @@ -2710,9 +2707,13 @@ int setcurr_tab_spaces (Text *text, int space) } if(strstr(text->curl->line, word)) { - //if we find a : then add a tab but not if it is in a comment + /* if we find a ':' on this line, then add a tab but not if it is: + * 1) in a comment + * 2) within an identifier + * 3) after the cursor (text->curc), i.e. when creating space before a function def [#25414] + */ int a, indent = 0; - for(a=0; text->curl->line[a] != '\0'; a++) + for(a=0; (a < text->curc) && (text->curl->line[a] != '\0'); a++) { if (text->curl->line[a]=='#') { break; @@ -2746,7 +2747,7 @@ int setcurr_tab_spaces (Text *text, int space) /*********************************/ /* Creates and adds a marker to the list maintaining sorted order */ -void txt_add_marker(Text *text, TextLine *line, int start, int end, char color[4], int group, int flags) { +void txt_add_marker(Text *text, TextLine *line, int start, int end, const unsigned char color[4], int group, int flags) { TextMarker *tmp, *marker; marker= MEM_mallocN(sizeof(TextMarker), "text_marker"); diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 77416f4dd12..c22b1d32849 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -38,11 +38,10 @@ #include "PIL_dynlib.h" - - #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_kdopbvh.h" +#include "BLI_utildefines.h" #include "DNA_key_types.h" #include "DNA_object_types.h" @@ -52,6 +51,7 @@ #include "DNA_brush_types.h" #include "DNA_node_types.h" #include "DNA_color_types.h" +#include "DNA_particle_types.h" #include "IMB_imbuf.h" @@ -93,14 +93,14 @@ void open_plugin_tex(PluginTex *pit) int (*version)(void); /* init all the happy variables */ - pit->doit= 0; - pit->pname= 0; - pit->stnames= 0; - pit->varstr= 0; - pit->result= 0; - pit->cfra= 0; + pit->doit= NULL; + pit->pname= NULL; + pit->stnames= NULL; + pit->varstr= NULL; + pit->result= NULL; + pit->cfra= NULL; pit->version= 0; - pit->instance_init= 0; + pit->instance_init= NULL; /* clear the error list */ PIL_dynlib_get_error_as_string(NULL); @@ -113,12 +113,12 @@ void open_plugin_tex(PluginTex *pit) pit->handle= PIL_dynlib_open(pit->name); if(test_dlerr(pit->name, pit->name)) return; - if (pit->handle != 0) { + if (pit->handle != NULL) { /* find the address of the version function */ version= (int (*)(void)) PIL_dynlib_find_symbol(pit->handle, "plugin_tex_getversion"); if (test_dlerr(pit->name, "plugin_tex_getversion")) return; - if (version != 0) { + if (version != NULL) { pit->version= version(); if( pit->version >= 2 && pit->version <=6) { int (*info_func)(PluginInfo *); @@ -168,8 +168,8 @@ PluginTex *add_plugin_tex(char *str) strcpy(pit->name, str); open_plugin_tex(pit); - if(pit->doit==0) { - if(pit->handle==0) {;} //XXX error("no plugin: %s", str); + if(pit->doit==NULL) { + if(pit->handle==NULL) {;} //XXX error("no plugin: %s", str); else {;} //XXX error("in plugin: %s", str); MEM_freeN(pit); return NULL; @@ -193,7 +193,7 @@ PluginTex *add_plugin_tex(char *str) void free_plugin_tex(PluginTex *pit) { - if(pit==0) return; + if(pit==NULL) return; /* no PIL_dynlib_close: same plugin can be opened multiple times, 1 handle */ MEM_freeN(pit); @@ -573,6 +573,7 @@ void default_tex(Tex *tex) tex->iuser.fie_ima= 2; tex->iuser.ok= 1; tex->iuser.frames= 100; + tex->iuser.sfra= 1; tex->preview = NULL; } @@ -618,7 +619,7 @@ void default_mtex(MTex *mtex) { mtex->texco= TEXCO_ORCO; mtex->mapto= MAP_COL; - mtex->object= 0; + mtex->object= NULL; mtex->projx= PROJ_X; mtex->projy= PROJ_Y; mtex->projz= PROJ_Z; @@ -629,8 +630,8 @@ void default_mtex(MTex *mtex) mtex->size[0]= 1.0; mtex->size[1]= 1.0; mtex->size[2]= 1.0; - mtex->tex= 0; - mtex->texflag= MTEX_NEW_BUMP; + mtex->tex= NULL; + mtex->texflag= MTEX_3TAP_BUMP | MTEX_BUMP_OBJECTSPACE; mtex->colormodel= 0; mtex->r= 1.0; mtex->g= 0.0; @@ -671,14 +672,16 @@ void default_mtex(MTex *mtex) mtex->lifefac= 1.0f; mtex->sizefac= 1.0f; mtex->ivelfac= 1.0f; - mtex->pvelfac= 1.0f; + mtex->dampfac= 1.0f; + mtex->gravityfac= 1.0f; + mtex->fieldfac= 1.0f; mtex->normapspace= MTEX_NSPACE_TANGENT; } /* ------------------------------------------------------------------------- */ -MTex *add_mtex() +MTex *add_mtex(void) { MTex *mtex; @@ -740,7 +743,7 @@ Tex *copy_texture(Tex *tex) texn= copy_libblock(tex); if(texn->type==TEX_IMAGE) id_us_plus((ID *)texn->ima); - else texn->ima= 0; + else texn->ima= NULL; #if 0 // XXX old animation system id_us_plus((ID *)texn->ipo); @@ -760,7 +763,7 @@ Tex *copy_texture(Tex *tex) if(tex->nodetree) { ntreeEndExecTree(tex->nodetree); - texn->nodetree= ntreeCopyTree(tex->nodetree, 0); /* 0 == full new tree */ + texn->nodetree= ntreeCopyTree(tex->nodetree); /* 0 == full new tree */ } return texn; @@ -776,6 +779,7 @@ void make_local_texture(Tex *tex) World *wrld; Lamp *la; Brush *br; + ParticleSettings *pa; int a, local=0, lib=0; /* - only lib users: do nothing @@ -783,19 +787,19 @@ void make_local_texture(Tex *tex) * - mixed: make copy */ - if(tex->id.lib==0) return; + if(tex->id.lib==NULL) return; /* special case: ima always local immediately */ if(tex->ima) { - tex->ima->id.lib= 0; + tex->ima->id.lib= NULL; tex->ima->id.flag= LIB_LOCAL; - new_id(0, (ID *)tex->ima, 0); + new_id(NULL, (ID *)tex->ima, NULL); } if(tex->id.us==1) { - tex->id.lib= 0; + tex->id.lib= NULL; tex->id.flag= LIB_LOCAL; - new_id(0, (ID *)tex, 0); + new_id(NULL, (ID *)tex, NULL); return; } @@ -838,11 +842,21 @@ void make_local_texture(Tex *tex) } br= br->id.next; } + pa= bmain->particle.first; + while(pa) { + for(a=0; a<MAX_MTEX; a++) { + if(pa->mtex[a] && pa->mtex[a]->tex==tex) { + if(pa->id.lib) lib= 1; + else local= 1; + } + } + pa= pa->id.next; + } if(local && lib==0) { - tex->id.lib= 0; + tex->id.lib= NULL; tex->id.flag= LIB_LOCAL; - new_id(0, (ID *)tex, 0); + new_id(NULL, (ID *)tex, NULL); } else if(local && lib) { texn= copy_texture(tex); @@ -852,7 +866,7 @@ void make_local_texture(Tex *tex) while(ma) { for(a=0; a<MAX_MTEX; a++) { if(ma->mtex[a] && ma->mtex[a]->tex==tex) { - if(ma->id.lib==0) { + if(ma->id.lib==NULL) { ma->mtex[a]->tex= texn; texn->id.us++; tex->id.us--; @@ -865,7 +879,7 @@ void make_local_texture(Tex *tex) while(la) { for(a=0; a<MAX_MTEX; a++) { if(la->mtex[a] && la->mtex[a]->tex==tex) { - if(la->id.lib==0) { + if(la->id.lib==NULL) { la->mtex[a]->tex= texn; texn->id.us++; tex->id.us--; @@ -878,7 +892,7 @@ void make_local_texture(Tex *tex) while(wrld) { for(a=0; a<MAX_MTEX; a++) { if(wrld->mtex[a] && wrld->mtex[a]->tex==tex) { - if(wrld->id.lib==0) { + if(wrld->id.lib==NULL) { wrld->mtex[a]->tex= texn; texn->id.us++; tex->id.us--; @@ -890,7 +904,7 @@ void make_local_texture(Tex *tex) br= bmain->brush.first; while(br) { if(br->mtex.tex==tex) { - if(br->id.lib==0) { + if(br->id.lib==NULL) { br->mtex.tex= texn; texn->id.us++; tex->id.us--; @@ -898,6 +912,19 @@ void make_local_texture(Tex *tex) } br= br->id.next; } + pa= bmain->particle.first; + while(pa) { + for(a=0; a<MAX_MTEX; a++) { + if(pa->mtex[a] && pa->mtex[a]->tex==tex) { + if(pa->id.lib==NULL) { + pa->mtex[a]->tex= texn; + texn->id.us++; + tex->id.us--; + } + } + } + pa= pa->id.next; + } } } @@ -940,8 +967,8 @@ Tex *give_current_object_texture(Object *ob) Material *ma; Tex *tex= NULL; - if(ob==0) return 0; - if(ob->totcol==0 && !(ob->type==OB_LAMP)) return 0; + if(ob==NULL) return NULL; + if(ob->totcol==0 && !(ob->type==OB_LAMP)) return NULL; if(ob->type==OB_LAMP) { tex= give_current_lamp_texture(ob->data); @@ -1048,6 +1075,10 @@ int give_active_mtex(ID *id, MTex ***mtex_ar, short *act) *mtex_ar= ((Lamp *)id)->mtex; if(act) *act= (((Lamp *)id)->texact); break; + case ID_PA: + *mtex_ar= ((ParticleSettings *)id)->mtex; + if(act) *act= (((ParticleSettings *)id)->texact); + break; default: *mtex_ar = NULL; if(act) *act= 0; @@ -1072,6 +1103,9 @@ void set_active_mtex(ID *id, short act) case ID_LA: ((Lamp *)id)->texact= act; break; + case ID_PA: + ((ParticleSettings *)id)->texact= act; + break; } } @@ -1121,7 +1155,7 @@ Tex *give_current_world_texture(World *world) MTex *mtex= NULL; Tex *tex= NULL; - if(!world) return 0; + if(!world) return NULL; mtex= world->mtex[(int)(world->texact)]; if(mtex) tex= mtex->tex; @@ -1167,6 +1201,42 @@ void set_current_brush_texture(Brush *br, Tex *newtex) } } +Tex *give_current_particle_texture(ParticleSettings *part) +{ + MTex *mtex= NULL; + Tex *tex= NULL; + + if(!part) return NULL; + + mtex= part->mtex[(int)(part->texact)]; + if(mtex) tex= mtex->tex; + + return tex; +} + +void set_current_particle_texture(ParticleSettings *part, Tex *newtex) +{ + int act= part->texact; + + if(part->mtex[act] && part->mtex[act]->tex) + id_us_min(&part->mtex[act]->tex->id); + + if(newtex) { + if(!part->mtex[act]) { + part->mtex[act]= add_mtex(); + part->mtex[act]->texco= TEXCO_ORCO; + part->mtex[act]->blendtype= MTEX_MUL; + } + + part->mtex[act]->tex= newtex; + id_us_plus(&newtex->id); + } + else if(part->mtex[act]) { + MEM_freeN(part->mtex[act]); + part->mtex[act]= NULL; + } +} + /* ------------------------------------------------------------------------- */ EnvMap *BKE_add_envmap(void) @@ -1285,8 +1355,7 @@ void BKE_free_pointdensity(PointDensity *pd) void BKE_free_voxeldatadata(struct VoxelData *vd) { if (vd->dataset) { - if(vd->file_format != TEX_VD_SMOKE) - MEM_freeN(vd->dataset); + MEM_freeN(vd->dataset); vd->dataset = NULL; } @@ -1337,13 +1406,11 @@ int BKE_texture_dependsOnTime(const struct Tex *texture) else if( texture->ima && ELEM(texture->ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { return 1; - } -#if 0 // XXX old animation system - else if(texture->ipo) { - // assume any ipo means the texture is animated + } + else if(texture->adt) { + // assume anything in adt means the texture is animated return 1; } -#endif // XXX old animation system return 0; } diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 133f858e9ea..b071f2c9da5 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -1,4 +1,5 @@ -/** +/* + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -24,29 +25,59 @@ #include <stdio.h> #include <ctype.h> #include <string.h> -#ifdef WIN32 -#define _USE_MATH_DEFINES -#endif -#include <math.h> +#include <assert.h> +#include "BKE_unit.h" +#include "BLI_math.h" #include "BLI_winstuff.h" + #define TEMP_STR_SIZE 256 #define SEP_CHR '#' #define SEP_STR "#" -#define EPS 0.000001 - +#define EPS 0.00001 + +#define UN_SC_KM 1000.0f +#define UN_SC_HM 100.0f +#define UN_SC_DAM 10.0f +#define UN_SC_M 1.0f +#define UN_SC_DM 0.1f +#define UN_SC_CM 0.01f +#define UN_SC_MM 0.001f +#define UN_SC_UM 0.000001f + +#define UN_SC_MI 1609.344f +#define UN_SC_FUR 201.168f +#define UN_SC_CH 20.1168f +#define UN_SC_YD 0.9144f +#define UN_SC_FT 0.3048f +#define UN_SC_IN 0.0254f +#define UN_SC_MIL 0.0000254f + +#define UN_SC_MTON 1000.0f /* metric ton */ +#define UN_SC_QL 100.0f +#define UN_SC_KG 1.0f +#define UN_SC_HG 0.1f +#define UN_SC_DAG 0.01f +#define UN_SC_G 0.001f + +#define UN_SC_ITON 907.18474f /* imperial ton */ +#define UN_SC_CWT 45.359237f +#define UN_SC_ST 6.35029318f +#define UN_SC_LB 0.45359237f +#define UN_SC_OZ 0.028349523125f /* define a single unit */ typedef struct bUnitDef { - char *name; - char *name_plural; /* abused a bit for the display name */ - char *name_short; /* this is used for display*/ - char *name_alt; /* can be NULL */ + const char *name; + const char *name_plural; /* abused a bit for the display name */ + const char *name_short; /* this is used for display*/ + const char *name_alt; /* keyboard-friendly ASCII-only version of name_short, can be NULL */ + /* if name_short has non-ASCII chars, name_alt should be present */ - char *name_display; /* can be NULL */ + const char *name_display; /* can be NULL */ double scalar; double bias; /* not used yet, needed for converting temperature */ @@ -59,7 +90,7 @@ typedef struct bUnitDef { /* define a single unit */ typedef struct bUnitCollection { struct bUnitDef *units; - int base_unit; /* use for 0.0, or none given */ + int base_unit; /* basic unit index (when user desn't specify unit explicitly) */ int flag; /* options for this system */ int length; /* to quickly find the last item */ } bUnitCollection; @@ -74,14 +105,14 @@ static struct bUnitCollection buDummyCollecton = {buDummyDef, 0, 0, sizeof(buDum /* Lengths */ static struct bUnitDef buMetricLenDef[] = { - {"kilometer", "kilometers", "km", NULL, "Kilometers", 1000.0, 0.0, B_UNIT_DEF_NONE}, - {"hectometer", "hectometers", "hm", NULL, "100 Meters", 100.0, 0.0, B_UNIT_DEF_SUPPRESS}, - {"dekameter", "dekameters", "dkm",NULL, "10 Meters", 10.0, 0.0, B_UNIT_DEF_SUPPRESS}, - {"meter", "meters", "m", NULL, "Meters", 1.0, 0.0, B_UNIT_DEF_NONE}, /* base unit */ - {"decimetre", "decimetres", "dm", NULL, "10 Centimeters", 0.1, 0.0, B_UNIT_DEF_SUPPRESS}, - {"centimeter", "centimeters", "cm", NULL, "Centimeters", 0.01, 0.0, B_UNIT_DEF_NONE}, - {"millimeter", "millimeters", "mm", NULL, "Millimeters", 0.001, 0.0, B_UNIT_DEF_NONE}, - {"micrometer", "micrometers", "µm", "um", "Micrometers", 0.000001, 0.0, B_UNIT_DEF_NONE}, // micron too? + {"kilometer", "kilometers", "km", NULL, "Kilometers", UN_SC_KM, 0.0, B_UNIT_DEF_NONE}, + {"hectometer", "hectometers", "hm", NULL, "100 Meters", UN_SC_HM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"dekameter", "dekameters", "dam",NULL, "10 Meters", UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"meter", "meters", "m", NULL, "Meters", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"decimetre", "decimetres", "dm", NULL, "10 Centimeters", UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"centimeter", "centimeters", "cm", NULL, "Centimeters", UN_SC_CM, 0.0, B_UNIT_DEF_NONE}, + {"millimeter", "millimeters", "mm", NULL, "Millimeters", UN_SC_MM, 0.0, B_UNIT_DEF_NONE}, + {"micrometer", "micrometers", "µm", "um", "Micrometers", UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, // micron too? /* These get displayed because of float precision problems in the transform header, * could work around, but for now probably people wont use these */ @@ -94,17 +125,121 @@ static struct bUnitDef buMetricLenDef[] = { static struct bUnitCollection buMetricLenCollecton = {buMetricLenDef, 3, 0, sizeof(buMetricLenDef)/sizeof(bUnitDef)}; static struct bUnitDef buImperialLenDef[] = { - {"mile", "miles", "mi", "m", "Miles", 1609.344, 0.0, B_UNIT_DEF_NONE}, - {"furlong", "furlongs", "fur", NULL, "Furlongs",201.168, 0.0, B_UNIT_DEF_SUPPRESS}, - {"chain", "chains", "ch", NULL, "Chains", 0.9144*22.0, 0.0, B_UNIT_DEF_SUPPRESS}, - {"yard", "yards", "yd", NULL, "Yards", 0.9144, 0.0, B_UNIT_DEF_NONE}, - {"foot", "feet", "'", "ft", "Feet", 0.3048, 0.0, B_UNIT_DEF_NONE}, - {"inch", "inches", "\"", "in", "Inches", 0.0254, 0.0, B_UNIT_DEF_NONE}, /* base unit */ - {"thou", "thous", "mil", NULL, "Thous", 0.0000254, 0.0, B_UNIT_DEF_NONE}, + {"mile", "miles", "mi", "m", "Miles", UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, + {"furlong", "furlongs", "fur", NULL, "Furlongs",UN_SC_FUR, 0.0, B_UNIT_DEF_SUPPRESS}, + {"chain", "chains", "ch", NULL, "Chains", UN_SC_CH, 0.0, B_UNIT_DEF_SUPPRESS}, + {"yard", "yards", "yd", NULL, "Yards", UN_SC_YD, 0.0, B_UNIT_DEF_NONE}, + {"foot", "feet", "'", "ft", "Feet", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"inch", "inches", "\"", "in", "Inches", UN_SC_IN, 0.0, B_UNIT_DEF_NONE}, + {"thou", "thous", "mil", NULL, "Thous", UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; static struct bUnitCollection buImperialLenCollecton = {buImperialLenDef, 4, 0, sizeof(buImperialLenDef)/sizeof(bUnitDef)}; +/* Areas */ +static struct bUnitDef buMetricAreaDef[] = { + {"square kilometer", "square kilometers", "km²", "km2", "Square Kilometers", UN_SC_KM*UN_SC_KM, 0.0, B_UNIT_DEF_NONE}, + {"square hectometer","square hectometers", "hm²", "hm2", "Square Hectometers", UN_SC_HM*UN_SC_HM, 0.0, B_UNIT_DEF_NONE}, /* hectare */ + {"square dekameter", "square dekameters", "dam²","dam2", "Square Dekameters", UN_SC_DAM*UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, /* are */ + {"square meter", "square meters", "m²", "m2", "Square Meters", UN_SC_M*UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"square decimetre", "square decimetres", "dm²", "dm2", "Square Decimetres", UN_SC_DM*UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"square centimeter", "square centimeters", "cm²", "cm2", "Square Centimeters", UN_SC_CM*UN_SC_CM, 0.0, B_UNIT_DEF_NONE}, + {"square millimeter", "square millimeters", "mm²", "mm2", "Square Millimeters", UN_SC_MM*UN_SC_MM, 0.0, B_UNIT_DEF_NONE}, + {"square micrometer", "square micrometers", "µm²", "um2", "Square Micrometers", UN_SC_UM*UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricAreaCollecton = {buMetricAreaDef, 3, 0, sizeof(buMetricAreaDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialAreaDef[] = { + {"square mile", "square miles", "sq mi", "sq m","Square Miles", UN_SC_MI*UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, + {"square furlong", "square furlongs", "sq fur",NULL, "Square Furlongs", UN_SC_FUR*UN_SC_FUR, 0.0,B_UNIT_DEF_SUPPRESS}, + {"square chain", "square chains", "sq ch", NULL, "Square Chains", UN_SC_CH*UN_SC_CH, 0.0, B_UNIT_DEF_SUPPRESS}, + {"square yard", "square yards", "sq yd", NULL, "Square Yards", UN_SC_YD*UN_SC_YD, 0.0, B_UNIT_DEF_NONE}, + {"square foot", "square feet", "sq ft", NULL, "Square Feet", UN_SC_FT*UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"square inch", "square inches", "sq in", NULL, "Square Inches", UN_SC_IN*UN_SC_IN, 0.0, B_UNIT_DEF_NONE}, + {"square thou", "square thous", "sq mil",NULL, "Square Thous", UN_SC_MIL*UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialAreaCollecton = {buImperialAreaDef, 4, 0, sizeof(buImperialAreaDef)/sizeof(bUnitDef)}; + +/* Volumes */ +static struct bUnitDef buMetricVolDef[] = { + {"cubic kilometer", "cubic kilometers", "km³", "km3", "Cubic Kilometers", UN_SC_KM*UN_SC_KM*UN_SC_KM, 0.0, B_UNIT_DEF_NONE}, + {"cubic hectometer","cubic hectometers", "hm³", "hm3", "Cubic Hectometers", UN_SC_HM*UN_SC_HM*UN_SC_HM, 0.0, B_UNIT_DEF_NONE}, + {"cubic dekameter", "cubic dekameters", "dam³","dam3", "Cubic Dekameters", UN_SC_DAM*UN_SC_DAM*UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"cubic meter", "cubic meters", "m³", "m3", "Cubic Meters", UN_SC_M*UN_SC_M*UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"cubic decimetre", "cubic decimetres", "dm³", "dm3", "Cubic Decimetres", UN_SC_DM*UN_SC_DM*UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"cubic centimeter", "cubic centimeters", "cm³", "cm3", "Cubic Centimeters", UN_SC_CM*UN_SC_CM*UN_SC_CM, 0.0, B_UNIT_DEF_NONE}, + {"cubic millimeter", "cubic millimeters", "mm³", "mm3", "Cubic Millimeters", UN_SC_MM*UN_SC_MM*UN_SC_MM, 0.0, B_UNIT_DEF_NONE}, + {"cubic micrometer", "cubic micrometers", "µm³", "um3", "Cubic Micrometers", UN_SC_UM*UN_SC_UM*UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricVolCollecton = {buMetricVolDef, 3, 0, sizeof(buMetricVolDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialVolDef[] = { + {"cubic mile", "cubic miles", "cu mi", "cu m","Cubic Miles", UN_SC_MI*UN_SC_MI*UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, + {"cubic furlong", "cubic furlongs", "cu fur",NULL, "Cubic Furlongs", UN_SC_FUR*UN_SC_FUR*UN_SC_FUR, 0.0,B_UNIT_DEF_SUPPRESS}, + {"cubic chain", "cubic chains", "cu ch", NULL, "Cubic Chains", UN_SC_CH*UN_SC_CH*UN_SC_CH, 0.0, B_UNIT_DEF_SUPPRESS}, + {"cubic yard", "cubic yards", "cu yd", NULL, "Cubic Yards", UN_SC_YD*UN_SC_YD*UN_SC_YD, 0.0, B_UNIT_DEF_NONE}, + {"cubic foot", "cubic feet", "cu ft", NULL, "Cubic Feet", UN_SC_FT*UN_SC_FT*UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"cubic inch", "cubic inches", "cu in", NULL, "Cubic Inches", UN_SC_IN*UN_SC_IN*UN_SC_IN, 0.0, B_UNIT_DEF_NONE}, + {"cubic thou", "cubic thous", "cu mil",NULL, "Cubic Thous", UN_SC_MIL*UN_SC_MIL*UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialVolCollecton = {buImperialVolDef, 4, 0, sizeof(buImperialVolDef)/sizeof(bUnitDef)}; + +/* Mass */ +static struct bUnitDef buMetricMassDef[] = { + {"ton", "tonnes", "ton", "t", "1000 Kilograms", UN_SC_MTON, 0.0, B_UNIT_DEF_NONE}, + {"quintal", "quintals", "ql", "q", "100 Kilograms", UN_SC_QL, 0.0, B_UNIT_DEF_NONE}, + {"kilogram", "kilograms", "kg", NULL, "Kilograms", UN_SC_KG, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"hectogram", "hectograms", "hg", NULL, "Hectograms", UN_SC_HG, 0.0, B_UNIT_DEF_NONE}, + {"dekagram", "dekagrams", "dag",NULL, "10 Grams", UN_SC_DAG, 0.0, B_UNIT_DEF_SUPPRESS}, + {"gram", "grams", "g", NULL, "Grams", UN_SC_G, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricMassCollecton = {buMetricMassDef, 2, 0, sizeof(buMetricMassDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialMassDef[] = { + {"ton", "tonnes", "ton", "t", "Tonnes", UN_SC_ITON, 0.0, B_UNIT_DEF_NONE}, + {"centum weight", "centum weights", "cwt", NULL, "Centum weights", UN_SC_CWT, 0.0, B_UNIT_DEF_NONE}, + {"stone", "stones", "st", NULL, "Stones", UN_SC_ST, 0.0, B_UNIT_DEF_NONE}, + {"pound", "pounds", "lb", NULL, "Pounds", UN_SC_LB, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"ounce", "ounces", "oz", NULL, "Ounces", UN_SC_OZ, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialMassCollecton = {buImperialMassDef, 3, 0, sizeof(buImperialMassDef)/sizeof(bUnitDef)}; + +/* Even if user scales the system to a point where km^3 is used, velocity and + * acceleration aren't scaled: that's why we have so few units for them */ + +/* Velocity */ +static struct bUnitDef buMetricVelDef[] = { + {"meter per second", "meters per second", "m/s", NULL, "Meters per second", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"kilometer per hour", "kilometers per hour", "km/h", NULL, "Kilometers per hour", UN_SC_KM/3600.0f, 0.0, B_UNIT_DEF_SUPPRESS}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricVelCollecton = {buMetricVelDef, 0, 0, sizeof(buMetricVelDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialVelDef[] = { + {"foot per second", "feet per second", "ft/s", "fps", "Feet per second", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"mile per hour", "miles per hour", "mph", NULL, "Miles per hour", UN_SC_MI/3600.0f, 0.0,B_UNIT_DEF_SUPPRESS}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialVelCollecton = {buImperialVelDef, 0, 0, sizeof(buImperialVelDef)/sizeof(bUnitDef)}; + +/* Acceleration */ +static struct bUnitDef buMetricAclDef[] = { + {"meter per second squared", "meters per second squared", "m/s²", "m/s2", "Meters per second squared", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricAclCollecton = {buMetricAclDef, 0, 0, sizeof(buMetricAclDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialAclDef[] = { + {"foot per second squared", "feet per second squared", "ft/s²", "ft/s2", "Feet per second squared", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialAclCollecton = {buImperialAclDef, 0, 0, sizeof(buImperialAclDef)/sizeof(bUnitDef)}; /* Time */ static struct bUnitDef buNaturalTimeDef[] = { @@ -114,7 +249,7 @@ static struct bUnitDef buNaturalTimeDef[] = { {"minute", "minutes", "min", "m", "Minutes", 60.0, 0.0, B_UNIT_DEF_NONE}, {"second", "seconds", "sec", "s", "Seconds", 1.0, 0.0, B_UNIT_DEF_NONE}, /* base unit */ {"millisecond", "milliseconds", "ms", NULL, "Milliseconds", 0.001, 0.0 , B_UNIT_DEF_NONE}, - {"microsecond", "microseconds", "us", NULL, "Microseconds", 0.000001, 0.0, B_UNIT_DEF_NONE}, + {"microsecond", "microseconds", "µs", "us", "Microseconds", 0.000001, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; static struct bUnitCollection buNaturalTimeCollecton = {buNaturalTimeDef, 3, 0, sizeof(buNaturalTimeDef)/sizeof(bUnitDef)}; @@ -122,21 +257,26 @@ static struct bUnitCollection buNaturalTimeCollecton = {buNaturalTimeDef, 3, 0, static struct bUnitDef buNaturalRotDef[] = { {"degree", "degrees", "°", NULL, "Degrees", M_PI/180.0, 0.0, B_UNIT_DEF_NONE}, +// {"radian", "radians", "r", NULL, "Radians", 1.0, 0.0, B_UNIT_DEF_NONE}, +// {"turn", "turns", "t", NULL, "Turns", 1.0/(M_PI*2.0), 0.0,B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; static struct bUnitCollection buNaturalRotCollection = {buNaturalRotDef, 0, 0, sizeof(buNaturalRotDef)/sizeof(bUnitDef)}; -#define UNIT_SYSTEM_MAX 3 -static struct bUnitCollection *bUnitSystems[][8] = { - {0,0,0,0,0,&buNaturalRotCollection,&buNaturalTimeCollecton,0}, - {0,&buMetricLenCollecton, 0,0,0, &buNaturalRotCollection, &buNaturalTimeCollecton,0}, /* metric */ - {0,&buImperialLenCollecton, 0,0,0,&buNaturalRotCollection, &buNaturalTimeCollecton,0}, /* imperial */ - {0,0,0,0,0,0,0,0} +#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / 9) / sizeof(void *)) - 1) +static struct bUnitCollection *bUnitSystems[][9] = { + {NULL, NULL, NULL, NULL, NULL, &buNaturalRotCollection, &buNaturalTimeCollecton, NULL, NULL}, + {NULL, &buMetricLenCollecton, &buMetricAreaCollecton, &buMetricVolCollecton, &buMetricMassCollecton, &buNaturalRotCollection, &buNaturalTimeCollecton, &buMetricVelCollecton, &buMetricAclCollecton}, /* metric */ + {NULL, &buImperialLenCollecton, &buImperialAreaCollecton, &buImperialVolCollecton, &buImperialMassCollecton, &buNaturalRotCollection, &buNaturalTimeCollecton, &buImperialVelCollecton, &buImperialAclCollecton}, /* imperial */ + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} }; + + /* internal, has some option not exposed */ static bUnitCollection *unit_get_system(int system, int type) { + assert((system > -1) && (system < UNIT_SYSTEM_TOT) && (type > -1) && (type < B_UNIT_TYPE_TOT)); return bUnitSystems[system][type]; /* select system to use, metric/imperial/other? */ } @@ -199,7 +339,8 @@ static int unit_as_string(char *str, int len_max, double value, int prec, bUnitC /* Convert to a string */ { - char conv_str[6] = {'%', '.', '0'+prec, 'l', 'f', '\0'}; /* "%.2lf" when prec is 2, must be under 10 */ + char conv_str[6] = {'%', '.', '0', 'l', 'f', '\0'}; /* "%.2lf" when prec is 2, must be under 10 */ + conv_str[2] += prec; len= snprintf(str, len_max, conv_str, (float)value_conv); if(len >= len_max) @@ -256,9 +397,9 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system, if(usys==NULL || usys->units[0].name==NULL) usys= &buDummyCollecton; - - if(split) { - int i; + + /* split output makes sense only for length, mass and time */ + if(split && (type==B_UNIT_LENGTH || type==B_UNIT_MASS || type==B_UNIT_TIME)) { bUnitDef *unit_a, *unit_b; double value_a, value_b; @@ -266,7 +407,7 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system, /* check the 2 is a smaller unit */ if(unit_b > unit_a) { - i= unit_as_string(str, len_max, value_a, prec, usys, unit_a, '\0'); + int i= unit_as_string(str, len_max, value_a, prec, usys, unit_a, '\0'); /* is there enough space for at least 1 char of the next unit? */ if(i+2 < len_max) { @@ -283,7 +424,7 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system, } -static char *unit_find_str(char *str, char *substr) +static char *unit_find_str(char *str, const char *substr) { char *str_found; @@ -338,7 +479,7 @@ static int ch_is_op(char op) } } -static int unit_scale_str(char *str, int len_max, char *str_tmp, double scale_pref, bUnitDef *unit, char *replace_str) +static int unit_scale_str(char *str, int len_max, char *str_tmp, double scale_pref, bUnitDef *unit, const char *replace_str) { char *str_found; @@ -443,10 +584,6 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre for(unit= usys->units; unit->name; unit++) { - - if(unit->flag & B_UNIT_DEF_SUPPRESS) - continue; - /* incase there are multiple instances */ while(unit_replace(str, len_max, str_tmp, scale_pref, unit)) change= 1; @@ -458,18 +595,15 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre bUnitCollection *usys_iter; int system_iter; - for(system_iter= 0; system_iter<UNIT_SYSTEM_MAX; system_iter++) { + for(system_iter= 0; system_iter<UNIT_SYSTEM_TOT; system_iter++) { if (system_iter != system) { usys_iter= unit_get_system(system_iter, type); if (usys_iter) { for(unit= usys_iter->units; unit->name; unit++) { - - if((unit->flag & B_UNIT_DEF_SUPPRESS) == 0) { - int ofs = 0; - /* incase there are multiple instances */ - while((ofs=unit_replace(str+ofs, len_max-ofs, str_tmp, scale_pref, unit))) - change= 1; - } + int ofs = 0; + /* incase there are multiple instances */ + while((ofs=unit_replace(str+ofs, len_max-ofs, str_tmp, scale_pref, unit))) + change= 1; } } } @@ -482,10 +616,6 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre if(str_prev) { /* see which units the original value had */ for(unit= usys->units; unit->name; unit++) { - - if(unit->flag & B_UNIT_DEF_SUPPRESS) - continue; - if (unit_find(str_prev, unit)) break; } @@ -543,6 +673,49 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre return change; } +/* 45µm --> 45um */ +void bUnit_ToUnitAltName(char *str, int len_max, char *orig_str, int system, int type) +{ + bUnitCollection *usys = unit_get_system(system, type); + + bUnitDef *unit; + bUnitDef *unit_def= unit_default(usys); + + /* find and substitute all units */ + for(unit= usys->units; unit->name; unit++) { + if(len_max > 0 && (unit->name_alt || unit == unit_def)) + { + char *found= NULL; + + found= unit_find_str(orig_str, unit->name_short); + if(found) { + int offset= (int)(found - orig_str); + int len_name= 0; + + /* copy everything before the unit */ + offset= (offset<len_max? offset: len_max); + strncpy(str, orig_str, offset); + + str+= offset; + orig_str+= offset + strlen(unit->name_short); + len_max-= offset; + + /* print the alt_name */ + if(unit->name_alt) + len_name= snprintf(str, len_max, "%s", unit->name_alt); + else + len_name= 0; + + len_name= (len_name<len_max? len_name: len_max); + str+= len_name; + len_max-= len_name; + } + } + } + + /* finally copy the rest of the string */ + strncpy(str, orig_str, len_max); +} double bUnit_ClosestScalar(double value, int system, int type) { @@ -566,6 +739,12 @@ double bUnit_BaseScalar(int system, int type) } /* external access */ +int bUnit_IsValid(int system, int type) +{ + return !(system < 0 || system > UNIT_SYSTEM_TOT || type < 0 || type > B_UNIT_TYPE_TOT); +} + + void bUnit_GetSystem(void **usys_pt, int *len, int system, int type) { bUnitCollection *usys = unit_get_system(system, type); @@ -579,11 +758,16 @@ void bUnit_GetSystem(void **usys_pt, int *len, int system, int type) *len= usys->length; } -char *bUnit_GetName(void *usys_pt, int index) +int bUnit_GetBaseUnit(void *usys_pt) +{ + return ((bUnitCollection *)usys_pt)->base_unit; +} + +const char *bUnit_GetName(void *usys_pt, int index) { return ((bUnitCollection *)usys_pt)->units[index].name; } -char *bUnit_GetNameDisplay(void *usys_pt, int index) +const char *bUnit_GetNameDisplay(void *usys_pt, int index) { return ((bUnitCollection *)usys_pt)->units[index].name_display; } diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 42df92443f3..5412e44f0eb 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -38,6 +38,7 @@ #include "DNA_scene_types.h" #include "DNA_texture_types.h" +#include "BKE_world.h" #include "BKE_library.h" #include "BKE_animsys.h" #include "BKE_global.h" @@ -63,7 +64,7 @@ void free_world(World *wrld) } -World *add_world(char *name) +World *add_world(const char *name) { Main *bmain= G.main; World *wrld; @@ -136,11 +137,11 @@ void make_local_world(World *wrld) * - mixed: make copy */ - if(wrld->id.lib==0) return; + if(wrld->id.lib==NULL) return; if(wrld->id.us==1) { - wrld->id.lib= 0; + wrld->id.lib= NULL; wrld->id.flag= LIB_LOCAL; - new_id(0, (ID *)wrld, 0); + new_id(NULL, (ID *)wrld, NULL); return; } @@ -156,7 +157,7 @@ void make_local_world(World *wrld) if(local && lib==0) { wrld->id.lib= 0; wrld->id.flag= LIB_LOCAL; - new_id(0, (ID *)wrld, 0); + new_id(NULL, (ID *)wrld, NULL); } else if(local && lib) { wrldn= copy_world(wrld); @@ -165,7 +166,7 @@ void make_local_world(World *wrld) sce= bmain->scene.first; while(sce) { if(sce->world==wrld) { - if(sce->id.lib==0) { + if(sce->id.lib==NULL) { sce->world= wrldn; wrldn->id.us++; wrld->id.us--; diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index 00614ef0f4f..1c1febf2609 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -1,4 +1,4 @@ -/** +/* * Functions for writing avi-format files. * Added interface for generic movie support (ton) * @@ -38,10 +38,12 @@ #include "DNA_scene_types.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "BKE_global.h" +#include "BKE_main.h" #include "BKE_report.h" -#include "BKE_utildefines.h" + #include "BKE_writeavi.h" #include "AVI_avi.h" @@ -119,7 +121,7 @@ static void filepath_avi (char *string, RenderData *rd) if (string==NULL) return; strcpy(string, rd->pic); - BLI_path_abs(string, G.sce); + BLI_path_abs(string, G.main->name); BLI_make_existing_file(string); @@ -137,6 +139,8 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL int quality; double framerate; + (void)scene; /* unused */ + filepath_avi(name, rd); sframe = (rd->sfra); @@ -175,7 +179,7 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL return 1; } -static int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) +static int append_avi(RenderData *UNUSED(rd), int frame, int *pixels, int rectx, int recty, ReportList *UNUSED(reports)) { unsigned int *rt1, *rt2, *rectot; int x, y; @@ -210,7 +214,7 @@ static int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int rec return 1; } -void end_avi(void) +static void end_avi(void) { if (avi == NULL) return; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 8ebf98ef930..f3b759113ff 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -1,4 +1,6 @@ /* + * $Id$ + * * ffmpeg-write support * * Partial Copyright (c) 2006 Peter Schlaile @@ -19,7 +21,7 @@ #include <string.h> #include <stdio.h> -#if defined(_WIN32) && defined(_DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__) +#if defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__) /* This does not seem necessary or present on MSVC 8, but may be needed in earlier versions? */ #if _MSC_VER < 1400 #include <stdint.h> @@ -69,7 +71,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -extern void do_init_ffmpeg(); +extern void do_init_ffmpeg(void); static int ffmpeg_type = 0; static int ffmpeg_codec = CODEC_ID_MPEG4; @@ -160,7 +162,7 @@ static int write_audio_frame(void) pkt.stream_index = audio_stream->index; pkt.flags |= PKT_FLAG_KEY; if (av_interleaved_write_frame(outfile, &pkt) != 0) { - // XXX error("Error writing audio packet"); + fprintf(stderr, "Error writing audio packet!\n"); return -1; } return 0; @@ -290,7 +292,9 @@ static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports packet.data = video_buffer; packet.size = outsize; ret = av_interleaved_write_frame(outfile, &packet); - } else ret = 0; + } else { + ret = 0; + } if (ret != 0) { success= 0; @@ -515,6 +519,7 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex if (codec_id == CODEC_ID_XVID) { /* arghhhh ... */ c->pix_fmt = PIX_FMT_YUV420P; + c->codec_tag = (('D'<<24) + ('I'<<16) + ('V'<<8) + 'X'); } if (codec_id == CODEC_ID_H264) { @@ -777,6 +782,69 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report return 1; } +/** + * Writes any delayed frames in the encoder. This function is called before + * closing the encoder. + * + * <p> + * Since an encoder may use both past and future frames to predict + * inter-frames (H.264 B-frames, for example), it can output the frames + * in a different order from the one it was given. + * For example, when sending frames 1, 2, 3, 4 to the encoder, it may write + * them in the order 1, 4, 2, 3 - first the two frames used for predition, + * and then the bidirectionally-predicted frames. What this means in practice + * is that the encoder may not immediately produce one output frame for each + * input frame. These delayed frames must be flushed before we close the + * stream. We do this by calling avcodec_encode_video with NULL for the last + * parameter. + * </p> + */ +void flush_ffmpeg(void) +{ + int outsize = 0; + int ret = 0; + + AVCodecContext* c = get_codec_from_stream(video_stream); + /* get the delayed frames */ + while (1) { + AVPacket packet; + av_init_packet(&packet); + + outsize = avcodec_encode_video(c, video_buffer, video_buffersize, NULL); + if (outsize < 0) { + fprintf(stderr, "Error encoding delayed frame %d\n", outsize); + break; + } + if (outsize == 0) { + break; + } + if (c->coded_frame->pts != AV_NOPTS_VALUE) { +#ifdef FFMPEG_CODEC_TIME_BASE + packet.pts = av_rescale_q(c->coded_frame->pts, + c->time_base, + video_stream->time_base); +#else + packet.pts = c->coded_frame->pts; +#endif + fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts); + } else { + fprintf(stderr, "Video Frame PTS: not set\n"); + } + if (c->coded_frame->key_frame) { + packet.flags |= PKT_FLAG_KEY; + } + packet.stream_index = video_stream->index; + packet.data = video_buffer; + packet.size = outsize; + ret = av_interleaved_write_frame(outfile, &packet); + if (ret != 0) { + fprintf(stderr, "Error writing delayed frame %d\n", ret); + break; + } + } + avcodec_flush_buffers(get_codec_from_stream(video_stream)); +} + /* ********************************************************************** * public interface ********************************************************************** */ @@ -791,7 +859,7 @@ void filepath_ffmpeg(char* string, RenderData* rd) { if (!string || !exts) return; strcpy(string, rd->pic); - BLI_path_abs(string, G.sce); + BLI_path_abs(string, G.main->name); BLI_make_existing_file(string); @@ -887,10 +955,9 @@ int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, return success; } - void end_ffmpeg(void) { - int i; + unsigned int i; fprintf(stderr, "Closing ffmpeg...\n"); @@ -904,6 +971,11 @@ void end_ffmpeg(void) audio_mixdown_device = 0; } + if (video_stream && get_codec_from_stream(video_stream)) { + fprintf(stderr, "Flushing delayed frames...\n"); + flush_ffmpeg (); + } + if (outfile) { av_write_trailer(outfile); } @@ -912,8 +984,8 @@ void end_ffmpeg(void) if (video_stream && get_codec_from_stream(video_stream)) { avcodec_close(get_codec_from_stream(video_stream)); - video_stream = 0; printf("zero video stream %p\n", video_stream); + video_stream = 0; } @@ -988,6 +1060,8 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int IDPropertyTemplate val; int idp_type; char name[256]; + + val.i = 0; avcodec_get_context_defaults(&c); @@ -995,8 +1069,6 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int parent = c.av_class->option + parent_index; if (!rd->ffcodecdata.properties) { - IDPropertyTemplate val; - rd->ffcodecdata.properties = IDP_New(IDP_GROUP, val, "ffmpeg"); } @@ -1005,8 +1077,6 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int rd->ffcodecdata.properties, (char*) type); if (!group) { - IDPropertyTemplate val; - group = IDP_New(IDP_GROUP, val, (char*) type); IDP_AddToGroup(rd->ffcodecdata.properties, group); } @@ -1194,20 +1264,47 @@ void ffmpeg_set_preset(RenderData *rd, int preset) rd->ffcodecdata.mux_packet_size = 2048; rd->ffcodecdata.mux_rate = 10080000; + /* + * All options here are for x264, but must be set via ffmpeg. + * The names are therefore different - Search for "x264 to FFmpeg option mapping" + * to get a list. + */ + + /* + * Use CABAC coder. Using "coder:1", which should be equivalent, + * crashes Blender for some reason. Either way - this is no big deal. + */ ffmpeg_property_add_string(rd, "video", "coder:vlc"); + + /* + * The other options were taken from the libx264-default.preset + * included in the ffmpeg distribution. + */ ffmpeg_property_add_string(rd, "video", "flags:loop"); ffmpeg_property_add_string(rd, "video", "cmp:chroma"); ffmpeg_property_add_string(rd, "video", "partitions:parti4x4"); ffmpeg_property_add_string(rd, "video", "partitions:partp8x8"); ffmpeg_property_add_string(rd, "video", "partitions:partb8x8"); ffmpeg_property_add_string(rd, "video", "me:hex"); - ffmpeg_property_add_string(rd, "video", "subq:5"); + ffmpeg_property_add_string(rd, "video", "subq:6"); ffmpeg_property_add_string(rd, "video", "me_range:16"); + ffmpeg_property_add_string(rd, "video", "qdiff:4"); ffmpeg_property_add_string(rd, "video", "keyint_min:25"); ffmpeg_property_add_string(rd, "video", "sc_threshold:40"); ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71"); ffmpeg_property_add_string(rd, "video", "b_strategy:1"); - + ffmpeg_property_add_string(rd, "video", "bf:3"); + ffmpeg_property_add_string(rd, "video", "refs:2"); + ffmpeg_property_add_string(rd, "video", "qcomp:0.6"); + ffmpeg_property_add_string(rd, "video", "directpred:3"); + ffmpeg_property_add_string(rd, "video", "trellis:0"); + ffmpeg_property_add_string(rd, "video", "flags2:wpred"); + ffmpeg_property_add_string(rd, "video", "flags2:dct8x8"); + ffmpeg_property_add_string(rd, "video", "flags2:fastpskip"); + ffmpeg_property_add_string(rd, "video", "wpredp:2"); + + // This makes x264 output lossless. Will be a separate option later. + //ffmpeg_property_add_string(rd, "video", "cqp:0"); break; case FFMPEG_PRESET_THEORA: diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index b0c05c31fa1..3cb3d7e038b 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -47,10 +47,12 @@ #include "DNA_userdef_types.h" +#include "BLI_utildefines.h" + +#include "BKE_writeframeserver.h" #include "BKE_global.h" #include "BKE_report.h" - #include "DNA_scene_types.h" static int sock; @@ -61,31 +63,31 @@ static int render_height; #if defined(_WIN32) -static int startup_socket_system() +static int startup_socket_system(void) { WSADATA wsa; return (WSAStartup(MAKEWORD(2,0),&wsa) == 0); } -static void shutdown_socket_system() +static void shutdown_socket_system(void) { WSACleanup(); } -static int select_was_interrupted_by_signal() +static int select_was_interrupted_by_signal(void) { return (WSAGetLastError() == WSAEINTR); } #else -static int startup_socket_system() +static int startup_socket_system(void) { return 1; } -static void shutdown_socket_system() +static void shutdown_socket_system(void) { } -static int select_was_interrupted_by_signal() +static int select_was_interrupted_by_signal(void) { return (errno == EINTR); } @@ -96,10 +98,12 @@ static int closesocket(int fd) } #endif -int start_frameserver(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) +int start_frameserver(struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports) { struct sockaddr_in addr; int arg = 1; + + (void)scene; /* unused */ if (!startup_socket_system()) { BKE_report(reports, RPT_ERROR, "Can't startup socket system"); @@ -243,7 +247,7 @@ static int handle_request(RenderData *rd, char * req) return -1; } -int frameserver_loop(RenderData *rd, ReportList *reports) +int frameserver_loop(RenderData *rd, ReportList *UNUSED(reports)) { fd_set readfds; struct timeval tv; @@ -350,7 +354,7 @@ static void serve_ppm(int *pixels, int rectx, int recty) connsock = -1; } -int append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) +int append_frameserver(RenderData *UNUSED(rd), int frame, int *pixels, int rectx, int recty, ReportList *UNUSED(reports)) { fprintf(stderr, "Serving frame: %d\n", frame); if (write_ppm) { @@ -364,7 +368,7 @@ int append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int re return 0; } -void end_frameserver() +void end_frameserver(void) { if (connsock != -1) { closesocket(connsock); diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index ebacfa82b11..bd760646053 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -1,4 +1,4 @@ -/** +/* * $Id: nla_private.h 21537 2009-07-11 22:22:53Z gsrb3d $ * * ***** BEGIN GPL LICENSE BLOCK ***** |