Merging r59081 through r59082 from trunk into soc-2013-depsgraph_mt
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 12 Aug 2013 12:19:41 +0000 (12:19 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 12 Aug 2013 12:19:41 +0000 (12:19 +0000)
92 files changed:
intern/guardedalloc/intern/mallocn.c
release/datafiles/startup.blend
release/scripts/startup/bl_ui/properties_data_curve.py
release/scripts/startup/bl_ui/properties_render.py
source/blender/blenkernel/BKE_anim.h
source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/BKE_depsgraph.h
source/blender/blenkernel/BKE_displist.h
source/blender/blenkernel/BKE_key.h
source/blender/blenkernel/BKE_lattice.h
source/blender/blenkernel/BKE_mball.h
source/blender/blenkernel/BKE_modifier.h
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/depsgraph_private.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/font.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mball.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/object_deform.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/scene.c
source/blender/blenlib/BLI_task.h [new file with mode: 0644]
source/blender/blenlib/BLI_threads.h
source/blender/blenlib/CMakeLists.txt
source/blender/blenlib/PIL_time.h
source/blender/blenlib/intern/BLI_mempool.c
source/blender/blenlib/intern/task.c [new file with mode: 0644]
source/blender/blenlib/intern/threads.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/armature/armature_skinning.c
source/blender/editors/curve/curve_intern.h
source/blender/editors/curve/curve_ops.c
source/blender/editors/curve/editcurve.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/mesh/meshtools.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_modifier.c
source/blender/editors/render/render_internal.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_info/info_stats.c
source/blender/editors/space_view3d/drawarmature.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_iterators.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/editors/util/crazyspace.c
source/blender/gpu/intern/gpu_buffers.c
source/blender/makesdna/DNA_curve_types.h
source/blender/makesdna/DNA_key_types.h
source/blender/makesdna/DNA_lattice_types.h
source/blender/makesdna/DNA_meta_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/makesrna/intern/rna_main_api.c
source/blender/makesrna/intern/rna_mesh.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_scene_api.c
source/blender/modifiers/intern/MOD_array.c
source/blender/modifiers/intern/MOD_explode.c
source/blender/modifiers/intern/MOD_particleinstance.c
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/pointdensity.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_init_exit.c
source/creator/creator.c
source/gameengine/Converter/BL_ShapeDeformer.cpp
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
source/gameengine/Rasterizer/RAS_MeshObject.cpp
source/gameengine/Rasterizer/RAS_MeshObject.h

index 08ac2ce6effefea7cecc91346ccd6b185722dfbf..1d5ba91db9df3e0ee549efa6f9a3199e351dd2ce 100644 (file)
@@ -280,6 +280,12 @@ static void mem_lock_thread(void)
 
 static void mem_unlock_thread(void)
 {
+#ifdef DEBUG_THREADS
+       if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
+               assert(!"Thread lock was removed while allocation from thread is in progress");
+       }
+#endif
+
        if (thread_unlock_callback)
                thread_unlock_callback();
 }
index c604d16829ce6a5106e895002102e33bd2a83707..8b58493fe3a4a1b8e404ee214d1610104aabbab8 100644 (file)
Binary files a/release/datafiles/startup.blend and b/release/datafiles/startup.blend differ
index 117a662cd072421c59b908f6bfbb99ea4f8ff472..1d90535b46f9c80789a11904cc76f69205062696 100644 (file)
@@ -140,6 +140,8 @@ class DATA_PT_curve_texture_space(CurveButtonsPanel, Panel):
         row.column().prop(curve, "texspace_location", text="Location")
         row.column().prop(curve, "texspace_size", text="Size")
 
+        layout.operator("curve.match_texture_space")
+
 
 class DATA_PT_geometry_curve(CurveButtonsPanel, Panel):
     bl_label = "Geometry"
index 799c109ae0cd0606ce2260c4dc6b786277538132..bf4975f2e43ab4f3b2f54e6cc41cc3a507a76e21 100644 (file)
@@ -70,6 +70,7 @@ class RENDER_PT_render(RenderButtonsPanel, Panel):
         row.operator("render.play_rendered_anim", text="Play", icon='PLAY')
 
         layout.prop(rd, "display_mode", text="Display")
+        layout.prop(rd, "use_lock_interface")
 
 
 class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
index 539c5780cd51ace7cd09ee131f20232217ff288e..7de7a745ed638f57ad1e95f33ca5454de2f0c23c 100644 (file)
@@ -59,7 +59,7 @@ void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets);
 /* Curve Paths */
 
 void free_path(struct Path *path);
-void calc_curvepath(struct Object *ob);
+void calc_curvepath(struct Object *ob, struct ListBase *nurbs);
 int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius, float *weight);
 
 /* ---------------------------------------------------- */
index fb9e9f4e691b84f1c3f31691a5264e663a24c94d..6e566778a8aa2565113abc8a4d47f9728d5c2de2 100644 (file)
@@ -124,11 +124,13 @@ void BKE_pchan_to_pose_mat(struct bPoseChannel *pchan, float rotscale_mat[4][4],
 void BKE_rotMode_change_values(float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode);
 
 /* B-Bone support */
+#define MAX_BBONE_SUBDIV    32
+
 typedef struct Mat4 {
        float mat[4][4];
 } Mat4;
 
-Mat4 *b_bone_spline_setup(struct bPoseChannel *pchan, int rest);
+void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV]);
 
 /* like EBONE_VISIBLE */
 #define PBONE_VISIBLE(arm, bone) ( \
index 93f9ec276aa483516fe8c1badff07c2269413c72..6e78cf681e136cf6e57ff2ceed2ad6f8a95327c5 100644 (file)
@@ -42,6 +42,13 @@ struct Main;
 struct Nurb;
 struct Object;
 struct Scene;
+struct Path;
+
+typedef struct CurveCache {
+       ListBase disp;
+       ListBase bev;
+       struct Path *path;
+} CurveCache;
 
 #define KNOTSU(nu)      ( (nu)->orderu + (nu)->pntsu + (((nu)->flagu & CU_NURB_CYCLIC) ? ((nu)->orderu - 1) : 0) )
 #define KNOTSV(nu)      ( (nu)->orderv + (nu)->pntsv + (((nu)->flagv & CU_NURB_CYCLIC) ? ((nu)->orderv - 1) : 0) )
@@ -63,9 +70,13 @@ void BKE_curve_make_local(struct Curve *cu);
 short BKE_curve_type_get(struct Curve *cu);
 void BKE_curve_type_test(struct Object *ob);
 void BKE_curve_curve_dimension_update(struct Curve *cu);
+
+void BKE_curve_boundbox_calc(struct Curve *cu, float r_loc[3], float r_size[3]);
+struct BoundBox *BKE_curve_boundbox_get(struct Object *ob);
 void BKE_curve_texspace_calc(struct Curve *cu);
+void BKE_curve_texspace_get(struct Curve *cu, float r_loc[3], float r_rot[3], float r_size[3]);
 
-bool BKE_curve_minmax(struct Curve *cu, float min[3], float max[3]);
+bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max[3]);
 bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
 bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
 void BKE_curve_translate(struct Curve *cu, float offset[3], int do_keys);
@@ -73,11 +84,11 @@ void BKE_curve_delete_material_index(struct Curve *cu, int index);
 
 ListBase *BKE_curve_nurbs_get(struct Curve *cu);
 
-float (*BKE_curve_vertexCos_get(struct Curve *cu, struct ListBase *lb, int *numVerts_r))[3];
-void BK_curve_vertexCos_apply(struct Curve *cu, struct ListBase *lb, float (*vertexCos)[3]);
+float (*BKE_curve_nurbs_vertexCos_get(struct ListBase *lb, int *numVerts_r))[3];
+void BK_curve_nurbs_vertexCos_apply(struct ListBase *lb, float (*vertexCos)[3]);
 
-float (*BKE_curve_keyVertexCos_get(struct Curve *cu, struct ListBase *lb, float *key))[3];
-void BKE_curve_keyVertexTilts_apply(struct Curve *cu, struct ListBase *lb, float *key);
+float (*BKE_curve_nurbs_keyVertexCos_get(struct ListBase *lb, float *key))[3];
+void BKE_curve_nurbs_keyVertexTilts_apply(struct ListBase *lb, float *key);
 
 void BKE_curve_editNurb_keyIndex_free(struct EditNurb *editnurb);
 void BKE_curve_editNurb_free(struct Curve *cu);
@@ -86,7 +97,7 @@ struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
 float *BKE_curve_make_orco(struct Scene *scene, struct Object *ob, int *r_numVerts);
 float *BKE_curve_surf_make_orco(struct Object *ob);
 
-void BKE_curve_bevelList_make(struct Object *ob);
+void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render);
 void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob,  struct ListBase *disp, int forRender, int renderResolution);
 
 void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
@@ -108,7 +119,7 @@ void BKE_nurb_free(struct Nurb *nu);
 struct Nurb *BKE_nurb_duplicate(struct Nurb *nu);
 
 void BKE_nurb_test2D(struct Nurb *nu);
-void BKE_nurb_minmax(struct Nurb *nu, float min[3], float max[3]);
+void BKE_nurb_minmax(struct Nurb *nu, bool use_radius, float min[3], float max[3]);
 
 void BKE_nurb_makeFaces(struct Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv);
 void BKE_nurb_makeCurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride);
index 6baf20aeb2c89e4423cbbe35cbd57c9d8c23cef4..f58790c4a1f826a7fa45912891393838ceab842a 100644 (file)
@@ -48,6 +48,7 @@ struct ID;
 struct Main;
 struct Object;
 struct Scene;
+struct ListBase;
 
 /* Build and Update
  *
@@ -115,6 +116,24 @@ void DAG_pose_sort(struct Object *ob);
 void DAG_editors_update_cb(void (*id_func)(struct Main *bmain, struct ID *id),
                            void (*scene_func)(struct Main *bmain, struct Scene *scene, int updated));
 
+/* ** Threaded update ** */
+
+/* Initialize the DAG for threaded update. */
+void DAG_threaded_update_begin(struct Scene *scene);
+
+/* Run a callback for every node which is ready for update. */
+void DAG_threaded_update_foreach_ready_node(struct Scene *scene,
+                                            void (*func)(void *node, void *user_data),
+                                            void *user_data);
+
+struct Object *DAG_threaded_update_get_node_object(void *node_v);
+
+const char *DAG_threaded_update_get_node_name(void *node_v);
+
+void DAG_threaded_update_handle_node_updated(void *node_v,
+                                             void (*func)(void *node, void *user_data),
+                                             void *user_data);
+
 /* Debugging: print dependency graph for scene or armature object to console */
 
 void DAG_print_dependencies(struct Main *bmain, struct Scene *scene, struct Object *ob);
index 1cf77c68345e637d1b89a1a1fe18fc62f65ff435..e82d3dbf1a8387b41de497df464095151a0be7d9 100644 (file)
@@ -28,6 +28,8 @@
 #ifndef __BKE_DISPLIST_H__
 #define __BKE_DISPLIST_H__
 
+struct ListBase;
+
 /** \file BKE_displist.h
  *  \ingroup bke
  *  \brief display list (or rather multi purpose list) stuff.
@@ -102,4 +104,6 @@ float BKE_displist_calc_taper(struct Scene *scene, struct Object *taperobj, int
 /* add Orco layer to the displist object which has got derived mesh and return orco */
 float *BKE_displist_make_orco(struct Scene *scene, struct Object *ob, struct DerivedMesh *derivedFinal, int forRender, int renderResolution);
 
+void BKE_displist_minmax(struct ListBase *dispbase, float min[3], float max[3]);
+
 #endif
index de60d316426936b5aaa0f314cd84728588398f72..19264feaf489f9d7e58c20bd2092b3241554f004 100644 (file)
@@ -41,6 +41,7 @@ struct Object;
 struct Scene;
 struct Lattice;
 struct Mesh;
+struct WeightsArrayCache;
 
 /* Kernel prototypes */
 #ifdef __cplusplus
@@ -73,8 +74,17 @@ struct KeyBlock *BKE_keyblock_from_key(struct Key *key, int index);
 struct KeyBlock *BKE_keyblock_find_name(struct Key *key, const char name[]);
 void             BKE_keyblock_copy_settings(struct KeyBlock *kb_dst, const struct KeyBlock *kb_src);
 char            *BKE_keyblock_curval_rnapath_get(struct Key *key, struct KeyBlock *kb);
+
 // needed for the GE
-void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, const int mode);
+typedef struct WeightsArrayCache {
+       int num_defgroup_weights;
+       float **defgroup_weights;
+} WeightsArrayCache;
+
+float **BKE_keyblock_get_per_block_weights(struct Object *ob, struct Key *key, struct WeightsArrayCache *cache);
+void BKE_keyblock_free_per_block_weights(struct Key *key, float **per_keyblock_weights, struct WeightsArrayCache *cache);
+void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb,
+                               float **per_keyblock_weights, const int mode);
 
 /* conversion functions */
 void    BKE_key_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me);
index 9b29412675bd00dba7497722edd5d72b0d0fdffe..ba33da7729c5fb5f37210eaf1ef7eb44621831b7 100644 (file)
@@ -49,9 +49,14 @@ void BKE_lattice_free(struct Lattice *lt);
 void BKE_lattice_make_local(struct Lattice *lt);
 void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
 
-void init_latt_deform(struct Object *oblatt, struct Object *ob);
-void calc_latt_deform(struct Object *, float co[3], float weight);
-void end_latt_deform(struct Object *);
+struct LatticeDeformData;
+struct LatticeDeformData *init_latt_deform(struct Object *oblatt, struct Object *ob)
+#ifdef __GNUC__
+__attribute__((warn_unused_result))
+#endif
+;
+void calc_latt_deform(struct LatticeDeformData *lattice_deform_data, float co[3], float weight);
+void end_latt_deform(struct LatticeDeformData *lattice_deform_data);
 
 int object_deform_mball(struct Object *ob, struct ListBase *dispbase);
 void outside_lattice(struct Lattice *lt);
index 44459300c5640b8d7f6574e373b3b0e4ed97636e..7665e1b54dc6df497daf6cb9ff84889f9f329a38 100644 (file)
@@ -47,7 +47,7 @@ void BKE_mball_make_local(struct MetaBall *mb);
 
 void BKE_mball_cubeTable_free(void);
 
-void BKE_mball_polygonize(struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
+void BKE_mball_polygonize(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, bool for_render);
 bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2);
 bool BKE_mball_is_basis(struct Object *ob);
 struct Object *BKE_mball_basis_find(struct Scene *scene, struct Object *ob);
index 0727e11f3978a6f81812aa76e3c316cc3e40e0b5..8f0d612d473f48effe1113cbec5f1c63bcd8eec4 100644 (file)
@@ -304,6 +304,9 @@ typedef struct ModifierTypeInfo {
                               TexWalkFunc walk, void *userData);
 } ModifierTypeInfo;
 
+/* Initialize modifier's global data (type info and some common global storages). */
+void BKE_modifier_init(void);
+
 ModifierTypeInfo *modifierType_getInfo(ModifierType type);
 
 /* Modifier utility calls, do call through type pointer and return
@@ -377,7 +380,15 @@ struct CDMaskLink *modifiers_calcDataMasks(struct Scene *scene,
 struct ModifierData *modifiers_getLastPreview(struct Scene *scene,
                                               struct ModifierData *md,
                                               int required_mode);
-struct ModifierData  *modifiers_getVirtualModifierList(struct Object *ob);
+
+typedef struct VirtualModifierData {
+       ArmatureModifierData amd;
+       CurveModifierData cmd;
+       LatticeModifierData lmd;
+       ShapeKeyModifierData smd;
+} VirtualModifierData;
+
+struct ModifierData  *modifiers_getVirtualModifierList(struct Object *ob, struct VirtualModifierData *data);
 
 /* ensure modifier correctness when changing ob->data */
 void test_object_modifiers(struct Object *ob);
index 992792dcb999b90ff256ef2e9fd8730b3ed8e833..dbd2263cfc9887587cb04d2e587597b6bc75f712 100644 (file)
@@ -60,6 +60,7 @@ void BKE_object_copy_softbody(struct Object *obn, struct Object *ob);
 void BKE_object_free_particlesystems(struct Object *ob);
 void BKE_object_free_softbody(struct Object *ob);
 void BKE_object_free_bulletsoftbody(struct Object *ob);
+void BKE_object_free_curve_cache(struct Object *ob);
 void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob);
 
 void BKE_object_free(struct Object *ob);
index 56b550a6f5d74b7249bf2ff5109b9538a3f4a41d..d4965cf55febc3f935e536518899036058c9da86 100644 (file)
@@ -54,6 +54,7 @@ struct MCol;
 struct MFace;
 struct MVert;
 struct IpoCurve;
+struct LatticeDeformData;
 struct LinkNode;
 struct KDTree;
 struct RNG;
@@ -258,7 +259,7 @@ void psys_set_current_num(Object *ob, int index);
 /* UNUSED */
 // struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys);
 
-struct Object *psys_get_lattice(struct ParticleSimulationData *sim);
+struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim);
 
 int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys);
 int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys);
index 61f665be5860a919ff66448edda356d3111ae369..8242e30ad05e90de55c1c9a5e0ba3d9f7d68dca9 100644 (file)
@@ -111,8 +111,10 @@ float BKE_scene_frame_get(struct Scene *scene);
 float BKE_scene_frame_get_from_ctime(struct Scene *scene, const float frame);
 void  BKE_scene_frame_set(struct Scene *scene, double cfra);
 
+void BKE_scene_update_tagged_ex(struct Main *bmain, struct Scene *scene, bool use_threads);
 void BKE_scene_update_tagged(struct Main *bmain, struct Scene *sce);
 
+void BKE_scene_update_for_newframe_ex(struct Main *bmain, struct Scene *sce, unsigned int lay, bool use_threads);
 void BKE_scene_update_for_newframe(struct Main *bmain, struct Scene *sce, unsigned int lay);
 
 struct SceneRenderLayer *BKE_scene_add_render_layer(struct Scene *sce, const char *name);
index c8ce2bb2a773376e2bfc10280bf235db020c0178..a47d94f1e7275e513e094bda04470e6ae6ed75c7 100644 (file)
@@ -92,6 +92,13 @@ typedef struct DagNode {
        struct DagAdjList *child;
        struct DagAdjList *parent;
        struct DagNode *next;
+
+       /* Threaded evaluation routines */
+       int valency;        /* valency of the node is a number of parents which are not updated yet
+                            * this node has got.
+                            * Used by threaded update for faster detect whether node could be
+                            * updated aready.
+                            */
 } DagNode;
 
 typedef struct DagNodeQueueElem {
index 2ece90183bd10b2b5efccb35c2a2f27d2d480889..32cf7dda3c292a88a5a12a3503dd695478506f31 100644 (file)
@@ -48,6 +48,7 @@
 #include "BLI_memarena.h"
 #include "BLI_utildefines.h"
 #include "BLI_linklist.h"
+#include "BLI_threads.h"
 
 #include "BKE_pbvh.h"
 #include "BKE_cdderivedmesh.h"
@@ -1440,6 +1441,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
        /* XXX Same as above... For now, only weights preview in WPaint mode. */
        const int do_mod_wmcol = do_init_wmcol;
 
+       VirtualModifierData virtualModifierData;
+
        ModifierApplyFlag app_flags = useRenderParams ? MOD_APPLY_RENDER : 0;
        ModifierApplyFlag deform_app_flags = app_flags;
        if (useCache)
@@ -1451,7 +1454,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                has_multires = 0;
 
        if (!skipVirtualArmature) {
-               firstmd = modifiers_getVirtualModifierList(ob);
+               firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        }
        else {
                /* game engine exception */
@@ -1961,6 +1964,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
        int do_init_wmcol = ((((Mesh *)ob->data)->drawflag & ME_DRAWEIGHT) && !do_final_wmcol);
        int do_init_statvis = ((((Mesh *)ob->data)->drawflag & ME_DRAW_STATVIS) && !do_init_wmcol);
        const int do_mod_wmcol = do_init_wmcol;
+       VirtualModifierData virtualModifierData;
 
        modifiers_clearErrors(ob);
 
@@ -1969,7 +1973,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
        }
 
        dm = NULL;
-       md = modifiers_getVirtualModifierList(ob);
+       md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        /* copied from mesh_calc_modifiers */
        if (do_mod_wmcol) {
index ba680147201487fd2aa95b25c44fc52a666d0e56..1b1bcffb4932ca79c830e9bc865001fe35d1da6a 100644 (file)
@@ -488,7 +488,7 @@ void free_path(Path *path)
 /* calculate a curve-deform path for a curve 
  *  - only called from displist.c -> do_makeDispListCurveTypes
  */
-void calc_curvepath(Object *ob)
+void calc_curvepath(Object *ob, ListBase *nurbs)
 {
        BevList *bl;
        BevPoint *bevp, *bevpn, *bevpfirst, *bevplast;
@@ -499,7 +499,6 @@ void calc_curvepath(Object *ob)
        float *fp, *dist, *maxdist, xyz[3];
        float fac, d = 0, fac1, fac2;
        int a, tot, cycl = 0;
-       ListBase *nurbs;
        
        /* in a path vertices are with equal differences: path->len = number of verts */
        /* NOW WITH BEVELCURVE!!! */
@@ -509,19 +508,18 @@ void calc_curvepath(Object *ob)
        }
        cu = ob->data;
 
-       if (cu->path) free_path(cu->path);
-       cu->path = NULL;
+       if (ob->curve_cache->path) free_path(ob->curve_cache->path);
+       ob->curve_cache->path = NULL;
        
        /* weak! can only use first curve */
-       bl = cu->bev.first;
+       bl = ob->curve_cache->bev.first;
        if (bl == NULL || !bl->nr) {
                return;
        }
 
-       nurbs = BKE_curve_nurbs_get(cu);
        nu = nurbs->first;
 
-       cu->path = path = MEM_callocN(sizeof(Path), "calc_curvepath");
+       ob->curve_cache->path = path = MEM_callocN(sizeof(Path), "calc_curvepath");
        
        /* if POLY: last vertice != first vertice */
        cycl = (bl->poly != -1);
@@ -630,15 +628,15 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua
 
        if (ob == NULL || ob->type != OB_CURVE) return 0;
        cu = ob->data;
-       if (cu->path == NULL || cu->path->data == NULL) {
+       if (ob->curve_cache == NULL || ob->curve_cache->path == NULL || ob->curve_cache->path->data == NULL) {
                printf("no path!\n");
                return 0;
        }
-       path = cu->path;
+       path = ob->curve_cache->path;
        pp = path->data;
        
        /* test for cyclic */
-       bl = cu->bev.first;
+       bl = ob->curve_cache->bev.first;
        if (!bl) return 0;
        if (!bl->nr) return 0;
        if (bl->poly > -1) cycl = 1;
@@ -1332,7 +1330,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
 
                psys_check_group_weights(part);
 
-               psys->lattice = psys_get_lattice(&sim);
+               psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
 
                /* gather list of objects or single object */
                if (part->ren_as == PART_DRAW_GR) {
@@ -1569,9 +1567,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
        if (obcopylist)
                MEM_freeN(obcopylist);
 
-       if (psys->lattice) {
-               end_latt_deform(psys->lattice);
-               psys->lattice = NULL;
+       if (psys->lattice_deform_data) {
+               end_latt_deform(psys->lattice_deform_data);
+               psys->lattice_deform_data = NULL;
        }
 }
 
index d37ccae308951ec2380e89d17c66b50b3d9ba733..d2241b337ff8771431c0d7344574fb92642f12bb 100644 (file)
@@ -381,8 +381,6 @@ int bone_autoside_name(char name[MAXBONENAME], int UNUSED(strip_number), short a
 
 /* ************* B-Bone support ******************* */
 
-#define MAX_BBONE_SUBDIV    32
-
 /* data has MAX_BBONE_SUBDIV+1 interpolated points, will become desired amount with equal distances */
 static void equalize_bezier(float *data, int desired)
 {
@@ -426,11 +424,8 @@ static void equalize_bezier(float *data, int desired)
 
 /* returns pointer to static array, filled with desired amount of bone->segments elements */
 /* this calculation is done  within unit bone space */
-Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
+void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV])
 {
-       static Mat4 bbone_array[MAX_BBONE_SUBDIV];
-       static Mat4 bbone_rest_array[MAX_BBONE_SUBDIV];
-       Mat4 *result_array = (rest) ? bbone_rest_array : bbone_array;
        bPoseChannel *next, *prev;
        Bone *bone = pchan->bone;
        float h1[3], h2[3], scale[3], length, hlength1, hlength2, roll1 = 0.0f, roll2;
@@ -587,8 +582,6 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
                        mul_serie_m4(result_array[a].mat, iscalemat, result_array[a].mat, scalemat, NULL, NULL, NULL, NULL, NULL);
                }
        }
-
-       return result_array;
 }
 
 /* ************ Armature Deform ******************* */
@@ -602,13 +595,15 @@ typedef struct 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[MAX_BBONE_SUBDIV], b_bone_rest[MAX_BBONE_SUBDIV];
        Mat4 *b_bone_mats;
        DualQuat *b_bone_dual_quats = NULL;
        float tmat[4][4] = MAT4_UNITY;
        int a;
 
+       b_bone_spline_setup(pchan, 0, b_bone);
+       b_bone_spline_setup(pchan, 1, b_bone_rest);
+
        /* allocate b_bone matrices and dual quats */
        b_bone_mats = MEM_mallocN((1 + bone->segments) * sizeof(Mat4), "BBone defmats");
        pdef_info->b_bone_mats = b_bone_mats;
@@ -1817,18 +1812,16 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
         *     - this is a workaround for a depsgraph bug...
         */
        if (ikData->tar) {
-               Curve *cu = ikData->tar->data;
-
                /* 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)
                 */
 
                /* only happens on reload file, but violates depsgraph still... fix! */
-               if (ELEM(NULL, cu->path, cu->path->data)) {
+               if (ELEM3(NULL,  ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
                        BKE_displist_make_curveTypes(scene, ikData->tar, 0);
                        
                        /* path building may fail in EditMode after removing verts [#33268]*/
-                       if (ELEM(NULL, cu->path, cu->path->data)) {
+                       if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
                                /* BLI_assert(cu->path != NULL); */
                                return;
                        }
@@ -1892,7 +1885,6 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
         * since it's easier to determine the positions of all the joints beforehand this way
         */
        if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (totLength != 0.0f)) {
-               Curve *cu = (Curve *)ikData->tar->data;
                float splineLen, maxScale;
                int i;
 
@@ -1905,7 +1897,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
 
                /* get the current length of the curve */
                /* NOTE: this is assumed to be correct even after the curve was resized */
-               splineLen = cu->path->totdist;
+               splineLen = ikData->tar->curve_cache->path->totdist;
 
                /* calculate the scale factor to multiply all the path values by so that the
                 * bone chain retains its current length, such that
index 6205c8016b6ac86763db7c42ca19246c1b94a82a..00a2c45d8fd07301e85770b6370770c0c41da9fb 100644 (file)
@@ -1814,7 +1814,13 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
 
 DerivedMesh *CDDM_from_curve(Object *ob)
 {
-       return CDDM_from_curve_displist(ob, &ob->disp);
+       ListBase disp = {NULL, NULL};
+
+       if (ob->curve_cache) {
+               disp = ob->curve_cache->disp;
+       }
+
+       return CDDM_from_curve_displist(ob, &disp);
 }
 
 DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
index eda770ddf30ffe04611477d7153901010be3d0ce..a1cb360e0a45b3862d39678bb3a3f367d7f796f6 100644 (file)
@@ -69,6 +69,7 @@
 #include "BKE_bvhutils.h"
 #include "BKE_camera.h"
 #include "BKE_constraint.h"
+#include "BKE_curve.h"
 #include "BKE_displist.h"
 #include "BKE_deform.h"
 #include "BKE_DerivedMesh.h"    /* for geometry targets */
@@ -448,7 +449,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m
 {
        Lattice *lt = (Lattice *)ob->data;
        
-       DispList *dl = BKE_displist_find(&ob->disp, DL_VERTS);
+       DispList *dl = ob->curve_cache ? BKE_displist_find(&ob->curve_cache->disp, DL_VERTS) : NULL;
        float *co = dl ? dl->verts : NULL;
        BPoint *bp = lt->def;
        
@@ -1163,10 +1164,10 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
                 */
                
                /* only happens on reload file, but violates depsgraph still... fix! */
-               if (cu->path == NULL || cu->path->data == NULL)
+               if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL)
                        BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
                
-               if (cu->path && cu->path->data) {
+               if (ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) {
                        float quat[4];
                        if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
                                /* animated position along curve depending on time */
@@ -1933,10 +1934,8 @@ static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTa
        if (VALID_CONS_TARGET(ct)) {
                /* special exception for curves - depsgraph issues */
                if (ct->tar->type == OB_CURVE) {
-                       Curve *cu = ct->tar->data;
-                       
                        /* this check is to make sure curve objects get updated on file load correctly.*/
-                       if (cu->path == NULL || cu->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */
+                       if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */
                                BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
                }
                
@@ -3009,14 +3008,12 @@ static void clampto_flush_tars(bConstraint *con, ListBase *list, short nocopy)
 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;
-               
                /* 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) 
                 */
                
                /* only happens on reload file, but violates depsgraph still... fix! */
-               if (cu->path == NULL || cu->path->data == NULL)
+               if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL)
                        BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
        }
        
@@ -3034,7 +3031,6 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
        
        /* 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], ownLoc[3];
                float curveMin[3], curveMax[3];
                float targetMatrix[4][4] = MAT4_UNITY;
@@ -3047,7 +3043,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
                BKE_object_minmax(ct->tar, curveMin, curveMax, TRUE);
                
                /* get targetmatrix */
-               if (cu->path && cu->path->data) {
+               if (data->tar->curve_cache &&  data->tar->curve_cache->path && data->tar->curve_cache->path->data) {
                        float vec[4], dir[3], totmat[4][4];
                        float curvetime;
                        short clamp_axis;
@@ -3650,14 +3646,12 @@ static void splineik_flush_tars(bConstraint *con, ListBase *list, short nocopy)
 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;
-               
                /* 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) 
                 */
                
                /* only happens on reload file, but violates depsgraph still... fix! */
-               if (cu->path == NULL || cu->path->data == NULL)
+               if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL)
                        BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
        }
        
index 26ae1b94aeea27f13cbb11ecb70afb832124aa8d..ce7d5c280aaa04c1274e3ff4693e598eb063ac82 100644 (file)
@@ -145,8 +145,6 @@ void BKE_curve_editNurb_free(Curve *cu)
 void BKE_curve_free(Curve *cu)
 {
        BKE_nurbList_free(&cu->nurb);
-       BLI_freelistN(&cu->bev);
-       BKE_displist_free(&cu->disp);
        BKE_curve_editfont_free(cu);
 
        BKE_curve_editNurb_free(cu);
@@ -161,8 +159,6 @@ void BKE_curve_free(Curve *cu)
                MEM_freeN(cu->strinfo);
        if (cu->bb)
                MEM_freeN(cu->bb);
-       if (cu->path)
-               free_path(cu->path);
        if (cu->tb)
                MEM_freeN(cu->tb);
 }
@@ -228,10 +224,6 @@ Curve *BKE_curve_copy(Curve *cu)
        cun->key = BKE_key_copy(cu->key);
        if (cun->key) cun->key->from = (ID *)cun;
 
-       cun->disp.first = cun->disp.last = NULL;
-       cun->bev.first = cun->bev.last = NULL;
-       cun->path = NULL;
-
        cun->editnurb = NULL;
        cun->editfont = NULL;
        cun->selboxes = NULL;
@@ -372,60 +364,79 @@ void BKE_curve_type_test(Object *ob)
                BKE_curve_curve_dimension_update((Curve *)ob->data);
 }
 
-void BKE_curve_texspace_calc(Curve *cu)
+void BKE_curve_boundbox_calc(Curve *cu, float r_loc[3], float r_size[3])
 {
-       DispList *dl;
        BoundBox *bb;
-       float *fp, min[3], max[3];
-       int tot, do_it = FALSE;
+       float min[3], max[3];
+       float mloc[3], msize[3];
 
-       if (cu->bb == NULL)
-               cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
+       if (cu->bb == NULL) cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
        bb = cu->bb;
 
-       INIT_MINMAX(min, max);
-
-       dl = cu->disp.first;
-       while (dl) {
-               tot = ELEM(dl->type, DL_INDEX3, DL_INDEX4) ? dl->nr : dl->nr * dl->parts;
+       if (!r_loc) r_loc = mloc;
+       if (!r_size) r_size = msize;
 
-               if (tot) do_it = TRUE;
-               fp = dl->verts;
-               while (tot--) {
-                       minmax_v3v3_v3(min, max, fp);
-                       fp += 3;
-               }
-               dl = dl->next;
-       }
-
-       if (do_it == FALSE) {
+       INIT_MINMAX(min, max);
+       /* TODO(sergey): makecode aware of radius and bevel somehow.. */
+       if (!BKE_curve_minmax(cu, true, min, max)) {
                min[0] = min[1] = min[2] = -1.0f;
                max[0] = max[1] = max[2] = 1.0f;
        }
 
+       mid_v3_v3v3(r_loc, min, max);
+
+       r_size[0] = (max[0] - min[0]) / 2.0f;
+       r_size[1] = (max[1] - min[1]) / 2.0f;
+       r_size[2] = (max[2] - min[2]) / 2.0f;
+
        BKE_boundbox_init_from_minmax(bb, min, max);
 
-       if (cu->texflag & CU_AUTOSPACE) {
-               mid_v3_v3v3(cu->loc, min, max);
-               cu->size[0] = (max[0] - min[0]) / 2.0f;
-               cu->size[1] = (max[1] - min[1]) / 2.0f;
-               cu->size[2] = (max[2] - min[2]) / 2.0f;
+       bb->flag &= ~BOUNDBOX_INVALID;
+}
 
-               zero_v3(cu->rot);
+BoundBox *BKE_curve_boundbox_get(Object *ob)
+{
+       Curve *cu = ob->data;
 
-               if (cu->size[0] == 0.0f) cu->size[0] = 1.0f;
-               else if (cu->size[0] > 0.0f && cu->size[0] < 0.00001f) cu->size[0] = 0.00001f;
-               else if (cu->size[0] < 0.0f && cu->size[0] > -0.00001f) cu->size[0] = -0.00001f;
+       if (ob->bb)
+               return ob->bb;
 
-               if (cu->size[1] == 0.0f) cu->size[1] = 1.0f;
-               else if (cu->size[1] > 0.0f && cu->size[1] < 0.00001f) cu->size[1] = 0.00001f;
-               else if (cu->size[1] < 0.0f && cu->size[1] > -0.00001f) cu->size[1] = -0.00001f;
+       if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_INVALID)) {
+               BKE_curve_texspace_calc(cu);
+       }
+
+       return cu->bb;
+}
 
-               if (cu->size[2] == 0.0f) cu->size[2] = 1.0f;
-               else if (cu->size[2] > 0.0f && cu->size[2] < 0.00001f) cu->size[2] = 0.00001f;
-               else if (cu->size[2] < 0.0f && cu->size[2] > -0.00001f) cu->size[2] = -0.00001f;
+void BKE_curve_texspace_calc(Curve *cu)
+{
+       float loc[3], size[3];
+       int a;
 
+       BKE_curve_boundbox_calc(cu, loc, size);
+
+       if (cu->texflag & CU_AUTOSPACE) {
+               for (a = 0; a < 3; a++) {
+                       if (size[a] == 0.0f) size[a] = 1.0f;
+                       else if (size[a] > 0.0f && size[a] < 0.00001f) size[a] = 0.00001f;
+                       else if (size[a] < 0.0f && size[a] > -0.00001f) size[a] = -0.00001f;
+               }
+
+               copy_v3_v3(cu->loc, loc);
+               copy_v3_v3(cu->size, size);
+               zero_v3(cu->rot);
+       }
+}
+
+void BKE_curve_texspace_get(Curve *cu, float r_loc[3], float r_rot[3], float r_size[3])
+{
+       if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_INVALID)) {
+               BKE_curve_texspace_calc(cu);
        }
+
+       if (r_loc) copy_v3_v3(r_loc,  cu->loc);
+       if (r_rot) copy_v3_v3(r_rot,  cu->rot);
+       if (r_size) copy_v3_v3(r_size, cu->size);
 }
 
 int BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3])
@@ -614,18 +625,34 @@ void BKE_nurb_test2D(Nurb *nu)
        }
 }
 
-void BKE_nurb_minmax(Nurb *nu, float min[3], float max[3])
+/* if use_radius is truth, minmax will take points' radius into account,
+ * which will make boundbox closer to bevelled curve.
+ */
+void BKE_nurb_minmax(Nurb *nu, bool use_radius, float min[3], float max[3])
 {
        BezTriple *bezt;
        BPoint *bp;
        int a;
+       float point[3];
 
        if (nu->type == CU_BEZIER) {
                a = nu->pntsu;
                bezt = nu->bezt;
                while (a--) {
+                       if (use_radius) {
+                               float radius_vector[3];
+                               radius_vector[0] = radius_vector[1] = radius_vector[2] = bezt->radius;
+
+                               add_v3_v3v3(point, bezt->vec[1], radius_vector);
+                               minmax_v3v3_v3(min, max, point);
+
+                               sub_v3_v3v3(point, bezt->vec[1], radius_vector);
+                               minmax_v3v3_v3(min, max, point);
+                       }
+                       else {
+                               minmax_v3v3_v3(min, max, bezt->vec[1]);
+                       }
                        minmax_v3v3_v3(min, max, bezt->vec[0]);
-                       minmax_v3v3_v3(min, max, bezt->vec[1]);
                        minmax_v3v3_v3(min, max, bezt->vec[2]);
                        bezt++;
                }
@@ -634,7 +661,20 @@ void BKE_nurb_minmax(Nurb *nu, float min[3], float max[3])
                a = nu->pntsu * nu->pntsv;
                bp = nu->bp;
                while (a--) {
-                       minmax_v3v3_v3(min, max, bp->vec);
+                       if (nu->pntsv == 1 && use_radius) {
+                               float radius_vector[3];
+                               radius_vector[0] = radius_vector[1] = radius_vector[2] = bp->radius;
+
+                               add_v3_v3v3(point, bp->vec, radius_vector);
+                               minmax_v3v3_v3(min, max, point);
+
+                               sub_v3_v3v3(point, bp->vec, radius_vector);
+                               minmax_v3v3_v3(min, max, point);
+                       }
+                       else {
+                               /* Surfaces doesn't use bevel, so no need to take radius into account. */
+                               minmax_v3v3_v3(min, max, bp->vec);
+                       }
                        bp++;
                }
        }
@@ -1586,10 +1626,10 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, int forRende
                                dl = bevdisp.first;
                        }
                        else {
-                               dl = cu->bevobj->disp.first;
+                               dl = cu->bevobj->curve_cache ? cu->bevobj->curve_cache->disp.first : NULL;
                                if (dl == NULL) {
                                        BKE_displist_make_curveTypes(scene, cu->bevobj, 0);
-                                       dl = cu->bevobj->disp.first;
+                                       dl = cu->bevobj->curve_cache->disp.first;
                                }
                        }
 
@@ -2425,7 +2465,7 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl)
        }
 }
 
-void BKE_curve_bevelList_make(Object *ob)
+void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
 {
        /*
         * - convert all curves to polys, with indication of resol and flags for double-vertices
@@ -2444,24 +2484,23 @@ void BKE_curve_bevelList_make(Object *ob)
        int a, b, nr, poly, resolu = 0, len = 0;
        int do_tilt, do_radius, do_weight;
        int is_editmode = 0;
+       ListBase *bev;
 
        /* this function needs an object, because of tflag and upflag */
        cu = ob->data;
 
+       bev = &ob->curve_cache->bev;
+
        /* do we need to calculate the radius for each point? */
        /* do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 : 1; */
 
        /* STEP 1: MAKE POLYS  */
 
-       BLI_freelistN(&(cu->bev));
+       BLI_freelistN(&(ob->curve_cache->bev));
+       nu = nurbs->first;
        if (cu->editnurb && ob->type != OB_FONT) {
-               ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-               nu = nurbs->first;
                is_editmode = 1;
        }
-       else {
-               nu = cu->nurb.first;
-       }
 
        for (; nu; nu = nu->next) {
                
@@ -2477,12 +2516,12 @@ void BKE_curve_bevelList_make(Object *ob)
                 * enforced in the UI but can go wrong possibly */
                if (!BKE_nurb_check_valid_u(nu)) {
                        bl = MEM_callocN(sizeof(BevList) + 1 * sizeof(BevPoint), "makeBevelList1");
-                       BLI_addtail(&(cu->bev), bl);
+                       BLI_addtail(bev, bl);
                        bl->nr = 0;
                        bl->charidx = nu->charidx;
                }
                else {
-                       if (G.is_rendering && cu->resolu_ren != 0)
+                       if (for_render && cu->resolu_ren != 0)
                                resolu = cu->resolu_ren;
                        else
                                resolu = nu->resolu;
@@ -2490,7 +2529,7 @@ void BKE_curve_bevelList_make(Object *ob)
                        if (nu->type == CU_POLY) {
                                len = nu->pntsu;
                                bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2");
-                               BLI_addtail(&(cu->bev), bl);
+                               BLI_addtail(bev, bl);
 
                                bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
                                bl->nr = len;
@@ -2517,7 +2556,7 @@ void BKE_curve_bevelList_make(Object *ob)
                                /* in case last point is not cyclic */
                                len = resolu * (nu->pntsu + (nu->flagu & CU_NURB_CYCLIC) - 1) + 1;
                                bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints");
-                               BLI_addtail(&(cu->bev), bl);
+                               BLI_addtail(bev, bl);
 
                                bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
                                bl->charidx = nu->charidx;
@@ -2610,7 +2649,7 @@ void BKE_curve_bevelList_make(Object *ob)
                                        len = (resolu * SEGMENTSU(nu));
 
                                        bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3");
-                                       BLI_addtail(&(cu->bev), bl);
+                                       BLI_addtail(bev, bl);
                                        bl->nr = len;
                                        bl->dupe_nr = 0;
                                        bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
@@ -2632,7 +2671,7 @@ void BKE_curve_bevelList_make(Object *ob)
        }
 
        /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */
-       bl = cu->bev.first;
+       bl = bev->first;
        while (bl) {
                if (bl->nr) { /* null bevel items come from single points */
                        nr = bl->nr;
@@ -2654,7 +2693,7 @@ void BKE_curve_bevelList_make(Object *ob)
                }
                bl = bl->next;
        }
-       bl = cu->bev.first;
+       bl = bev->first;
        while (bl) {
                blnext = bl->next;
                if (bl->nr && bl->dupe_nr) {
@@ -2662,8 +2701,8 @@ void BKE_curve_bevelList_make(Object *ob)
                        blnew = MEM_mallocN(sizeof(BevList) + nr * sizeof(BevPoint), "makeBevelList4");
                        memcpy(blnew, bl, sizeof(BevList));
                        blnew->nr = 0;
-                       BLI_remlink(&(cu->bev), bl);
-                       BLI_insertlinkbefore(&(cu->bev), blnext, blnew);    /* to make sure bevlijst is tuned with nurblist */
+                       BLI_remlink(bev, bl);
+                       BLI_insertlinkbefore(bev, blnext, blnew);    /* to make sure bevlijst is tuned with nurblist */
                        bevp0 = (BevPoint *)(bl + 1);
                        bevp1 = (BevPoint *)(blnew + 1);
                        nr = bl->nr;
@@ -2682,7 +2721,7 @@ void BKE_curve_bevelList_make(Object *ob)
        }
 
        /* STEP 3: POLYS COUNT AND AUTOHOLE */
-       bl = cu->bev.first;
+       bl = bev->first;
        poly = 0;
        while (bl) {
                if (bl->nr && bl->poly >= 0) {
@@ -2696,7 +2735,7 @@ void BKE_curve_bevelList_make(Object *ob)
        /* find extreme left points, also test (turning) direction */
        if (poly > 0) {
                sd = sortdata = MEM_mallocN(sizeof(struct bevelsort) * poly, "makeBevelList5");
-               bl = cu->bev.first;
+               bl = bev->first;
                while (bl) {
                        if (bl->poly > 0) {
 
@@ -2776,7 +2815,7 @@ void BKE_curve_bevelList_make(Object *ob)
        /* STEP 4: 2D-COSINES or 3D ORIENTATION */
        if ((cu->flag & CU_3D) == 0) {
                /* 2D Curves */
-               for (bl = cu->bev.first; bl; bl = bl->next) {
+               for (bl = bev->first; bl; bl = bl->next) {
                        if (bl->nr < 2) {
                                /* do nothing */
                        }
@@ -2790,7 +2829,7 @@ void BKE_curve_bevelList_make(Object *ob)
        }
        else {
                /* 3D Curves */
-               for (bl = cu->bev.first; bl; bl = bl->next) {
+               for (bl = bev->first; bl; bl = bl->next) {
                        if (bl->nr < 2) {
                                /* do nothing */
                        }
@@ -3379,7 +3418,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
 }
 
 
-float (*BKE_curve_vertexCos_get(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r))[3]
+float (*BKE_curve_nurbs_vertexCos_get(ListBase *lb, int *numVerts_r))[3]
 {
        int i, numVerts = *numVerts_r = BKE_nurbList_verts_count(lb);
        float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "cu_vcos");
@@ -3408,7 +3447,7 @@ float (*BKE_curve_vertexCos_get(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r
        return cos;
 }
 
-void BK_curve_vertexCos_apply(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos)[3])
+void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3])
 {
        float *co = vertexCos[0];
        Nurb *nu;
@@ -3436,7 +3475,7 @@ void BK_curve_vertexCos_apply(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos
        }
 }
 
-float (*BKE_curve_keyVertexCos_get(Curve *UNUSED(cu), ListBase *lb, float *key))[3]
+float (*BKE_curve_nurbs_keyVertexCos_get(ListBase *lb, float *key))[3]
 {
        int i, numVerts = BKE_nurbList_verts_count(lb);
        float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "cu_vcos");
@@ -3467,7 +3506,7 @@ float (*BKE_curve_keyVertexCos_get(Curve *UNUSED(cu), ListBase *lb, float *key))
        return cos;
 }
 
-void BKE_curve_keyVertexTilts_apply(Curve *UNUSED(cu), ListBase *lb, float *key)
+void BKE_curve_nurbs_keyVertexTilts_apply(ListBase *lb, float *key)
 {
        Nurb *nu;
        int i;
@@ -3718,13 +3757,13 @@ ListBase *BKE_curve_nurbs_get(Curve *cu)
 
 
 /* basic vertex data functions */
-bool BKE_curve_minmax(Curve *cu, float min[3], float max[3])
+bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
 {
        ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
        Nurb *nu;
 
        for (nu = nurb_lb->first; nu; nu = nu->next)
-               BKE_nurb_minmax(nu, min, max);
+               BKE_nurb_minmax(nu, use_radius, min, max);
 
        return (nurb_lb->first != NULL);
 }
@@ -3771,7 +3810,7 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3])
 {
        float min[3], max[3];
        INIT_MINMAX(min, max);
-       if (BKE_curve_minmax(cu, min, max)) {
+       if (BKE_curve_minmax(cu, false, min, max)) {
                mid_v3_v3v3(cent, min, max);
                return true;
        }
index 4ce06623baec8f31dbac01188934478ec66c7c2d..f3a824665e0e08e5348760cde1c5de1a26c94b91 100644 (file)
@@ -29,6 +29,7 @@
 
  
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <math.h>
 
@@ -2653,6 +2654,98 @@ void DAG_pose_sort(Object *ob)
        ugly_hack_sorry = 1;
 }
 
+/* ************************  DAG FOR THREADED UPDATE  ********************* */
+
+/* Initialize the DAG for threaded update.
+ *
+ * Sets up all the data needed for faster check whether DAG node is
+ * updatable already (whether all the dependencies are met).
+ */
+void DAG_threaded_update_begin(Scene *scene)
+{
+       DagNode *node;
+
+       /* We reset valency to zero first... */
+       for (node = scene->theDag->DagNode.first; node; node = node->next) {
+               node->valency = 0;
+       }
+
+       /* ... and then iterate over all the nodes and
+        * increase valency for node childs.
+        */
+       for (node = scene->theDag->DagNode.first; node; node = node->next) {
+               DagAdjList *itA;
+
+               for (itA = node->child; itA; itA = itA->next) {
+                       if (itA->node != node) {
+                               itA->node->valency++;
+                       }
+               }
+       }
+}
+
+/* Call functor for every node in the graph which is ready for
+ * update (all it's dependencies are met). Quick check for this
+ * is valency == 0.
+ */
+void DAG_threaded_update_foreach_ready_node(Scene *scene,
+                                            void (*func)(void *node, void *user_data),
+                                            void *user_data)
+{
+       DagNode *node;
+
+       for (node = scene->theDag->DagNode.first; node; node = node->next) {
+               if (node->valency == 0) {
+                       func(node, user_data);
+               }
+       }
+}
+
+/* Will return Object ID if node represents Object,
+ * and will return NULL otherwise.
+ */
+Object *DAG_threaded_update_get_node_object(void *node_v)
+{
+       DagNode *node = node_v;
+
+       if (node->type == ID_OB) {
+               return node->ob;
+       }
+
+       return NULL;
+}
+
+/* Returns node name, used for debug output only, atm. */
+const char *DAG_threaded_update_get_node_name(void *node_v)
+{
+       DagNode *node = node_v;
+
+       return dag_node_name(node);
+}
+
+/* This function is called when handling node is done.
+ *
+ * This function updates valency for all childs and
+ * schedules them if they're ready.
+ */
+void DAG_threaded_update_handle_node_updated(void *node_v,
+                                             void (*func)(void *node, void *user_data),
+                                             void *user_data)
+{
+       DagNode *node = node_v;
+       DagAdjList *itA;
+
+       for (itA = node->child; itA; itA = itA->next) {
+               if (itA->node != node) {
+                       itA->node->valency--;
+
+                       if (itA->node->valency == 0) {
+                               func(itA->node, user_data);
+                       }
+               }
+       }
+}
+
 /* ************************ DAG DEBUGGING ********************* */
 
 void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
@@ -2671,4 +2764,3 @@ void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
        
        dag_print_dependencies = 0;
 }
-
index 38a0b8483397a4e9c588b7e0a60e1f08146a307e..5089cb84fe739991ff79c03a8e9fd9ffaf495fcb 100644 (file)
@@ -62,8 +62,7 @@
 
 #include "BLI_sys_types.h" // for intptr_t support
 
-static void boundbox_displist(Object *ob);
-static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase);
+static void boundbox_displist_object(Object *ob);
 
 void BKE_displist_elem_free(DispList *dl)
 {
@@ -667,10 +666,10 @@ static float displist_calc_taper(Scene *scene, Object *taperobj, float fac)
        if (taperobj == NULL || taperobj->type != OB_CURVE)
                return 1.0;
 
-       dl = taperobj->disp.first;
+       dl = taperobj->curve_cache ? taperobj->curve_cache->disp.first : NULL;
        if (dl == NULL) {
                BKE_displist_make_curveTypes(scene, taperobj, 0);
-               dl = taperobj->disp.first;
+               dl = taperobj->curve_cache->disp.first;
        }
        if (dl) {
                float minx, dx, *fp;
@@ -712,29 +711,28 @@ void BKE_displist_make_mball(Scene *scene, Object *ob)
        if (!ob || ob->type != OB_MBALL)
                return;
 
-       /* XXX: mball stuff uses plenty of global variables
-        *      while this is unchanged updating during render is unsafe
-        */
-       if (G.is_rendering)
-               return;
-
-       BKE_displist_free(&(ob->disp));
+       if (ob->curve_cache) {
+               BKE_displist_free(&(ob->curve_cache->disp));
+       }
+       else {
+               ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+       }
 
        if (ob->type == OB_MBALL) {
                if (ob == BKE_mball_basis_find(scene, ob)) {
-                       BKE_mball_polygonize(scene, ob, &ob->disp);
+                       BKE_mball_polygonize(scene, ob, &ob->curve_cache->disp, false);
                        BKE_mball_texspace_calc(ob);
 
-                       object_deform_mball(ob, &ob->disp);
+                       object_deform_mball(ob, &ob->curve_cache->disp);
                }
-       }
 
-       boundbox_displist(ob);
+               boundbox_displist_object(ob);
+       }
 }
 
 void BKE_displist_make_mball_forRender(Scene *scene, Object *ob, ListBase *dispbase)
 {
-       BKE_mball_polygonize(scene, ob, dispbase);
+       BKE_mball_polygonize(scene, ob, dispbase, true);
        BKE_mball_texspace_calc(ob);
 
        object_deform_mball(ob, dispbase);
@@ -742,7 +740,8 @@ void BKE_displist_make_mball_forRender(Scene *scene, Object *ob, ListBase *dispb
 
 static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int renderResolution, int editmode)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        ModifierData *pretessellatePoint;
        int required_mode;
 
@@ -780,18 +779,16 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int re
        return pretessellatePoint;
 }
 
-static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, int renderResolution,
-                                     float (**originalVerts_r)[3],
-                                     float (**deformedVerts_r)[3], int *numVerts_r)
+static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
+                                     int forRender, int renderResolution)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        ModifierData *pretessellatePoint;
        Curve *cu = ob->data;
-       ListBase *nurb = BKE_curve_nurbs_get(cu);
        int numVerts = 0;
        const int editmode = (!forRender && (cu->editnurb || cu->editfont));
        ModifierApplyFlag app_flag = 0;
-       float (*originalVerts)[3] = NULL;
        float (*deformedVerts)[3] = NULL;
        float *keyVerts = NULL;
        int required_mode;
@@ -818,8 +815,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in
                         * tilts, which is passed through in the modifier stack.
                         * this is also the reason curves do not use a virtual
                         * shape key modifier yet. */
-                       deformedVerts = BKE_curve_keyVertexCos_get(cu, nurb, keyVerts);
-                       originalVerts = MEM_dupallocN(deformedVerts);
+                       deformedVerts = BKE_curve_nurbs_keyVertexCos_get(nurb, keyVerts);
                        BLI_assert(BKE_nurbList_verts_count(nurb) == numVerts);
                }
        }
@@ -836,8 +832,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in
                                continue;
 
                        if (!deformedVerts) {
-                               deformedVerts = BKE_curve_vertexCos_get(cu, nurb, &numVerts);
-                               originalVerts = MEM_dupallocN(deformedVerts);
+                               deformedVerts = BKE_curve_nurbs_vertexCos_get(nurb, &numVerts);
                        }
 
                        mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, app_flag);
@@ -847,17 +842,15 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in
                }
        }
 
-       if (deformedVerts)
-               BK_curve_vertexCos_apply(cu, nurb, deformedVerts);
+       if (deformedVerts) {
+               BK_curve_nurbs_vertexCos_apply(nurb, deformedVerts);
+               MEM_freeN(deformedVerts);
+       }
        if (keyVerts) /* these are not passed through modifier stack */
-               BKE_curve_keyVertexTilts_apply(cu, nurb, keyVerts);
+               BKE_curve_nurbs_keyVertexTilts_apply(nurb, keyVerts);
 
        if (keyVerts)
                MEM_freeN(keyVerts);
-
-       *originalVerts_r = originalVerts;
-       *deformedVerts_r = deformedVerts;
-       *numVerts_r = numVerts;
 }
 
 static float (*displist_get_allverts(ListBase *dispbase, int *totvert))[3]
@@ -894,14 +887,14 @@ static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
        }
 }
 
-static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase, DerivedMesh **derivedFinal,
-                                      int forRender, int renderResolution,
-                                      float (*originalVerts)[3], float (*deformedVerts)[3])
+static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
+                                      ListBase *dispbase, DerivedMesh **derivedFinal,
+                                      int forRender, int renderResolution)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        ModifierData *pretessellatePoint;
        Curve *cu = ob->data;
-       ListBase *nurb = BKE_curve_nurbs_get(cu);
        int required_mode = 0, totvert = 0;
        int editmode = (!forRender && (cu->editnurb || cu->editfont));
        DerivedMesh *dm = NULL, *ndm;
@@ -1046,12 +1039,6 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
                }
                (*derivedFinal) = dm;
        }
-
-       if (deformedVerts) {
-               BK_curve_vertexCos_apply(ob->data, nurb, originalVerts);
-               MEM_freeN(originalVerts);
-               MEM_freeN(deformedVerts);
-       }
 }
 
 static void displist_surf_indices(DispList *dl)
@@ -1142,8 +1129,8 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina
        /* this function represents logic of mesh's orcodm calculation
         * for displist-based objects
         */
-
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        ModifierData *pretessellatePoint;
        Curve *cu = ob->data;
        int required_mode;
@@ -1201,25 +1188,24 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina
 void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
                             DerivedMesh **derivedFinal, int forRender, int forOrco, int renderResolution)
 {
-       ListBase *nubase;
+       ListBase nubase = {NULL, NULL};
        Nurb *nu;
        Curve *cu = ob->data;
        DispList *dl;
        float *data;
        int len;
-       int numVerts;
-       float (*originalVerts)[3];
-       float (*deformedVerts)[3];
 
-       if (!forRender && cu->editnurb)
-               nubase = BKE_curve_editNurbs_get(cu);
-       else
-               nubase = &cu->nurb;
+       if (!forRender && cu->editnurb) {
+               BKE_nurbList_duplicate(&nubase, BKE_curve_editNurbs_get(cu));
+       }
+       else {
+               BKE_nurbList_duplicate(&nubase, &cu->nurb);
+       }
 
        if (!forOrco)
-               curve_calc_modifiers_pre(scene, ob, forRender, renderResolution, &originalVerts, &deformedVerts, &numVerts);
+               curve_calc_modifiers_pre(scene, ob, &nubase, forRender, renderResolution);
 
-       for (nu = nubase->first; nu; nu = nu->next) {
+       for (nu = nubase.first; nu; nu = nu->next) {
                if (forRender || nu->hide == 0) {
                        int resolu = nu->resolu, resolv = nu->resolv;
 
@@ -1282,20 +1268,12 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
                }
        }
 
-       /* make copy of 'undeformed" displist for texture space calculation
-        * actually, it's not totally undeformed -- pre-tessellation modifiers are
-        * already applied, thats how it worked for years, so keep for compatibility (sergey) */
-       BKE_displist_copy(&cu->disp, dispbase);
-
-       if (!forRender) {
-               BKE_curve_texspace_calc(cu);
-       }
-
        if (!forOrco) {
-               curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal,
-                                         forRender, renderResolution,
-                                         originalVerts, deformedVerts);
+               curve_calc_modifiers_post(scene, ob, &nubase, dispbase, derivedFinal,
+                                         forRender, renderResolution);
        }
+
+       BKE_nurbList_free(&nubase);
 }
 
 static void rotateBevelPiece(Curve *cu, BevPoint *bevp, BevPoint *nbevp, DispList *dlb, float bev_blend, float widfac, float fac, float **data_r)
@@ -1389,37 +1367,34 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
        }
        else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
                ListBase dlbev;
-               ListBase *nubase;
-               float (*originalVerts)[3];
-               float (*deformedVerts)[3];
-               int numVerts;
+               ListBase nubase = {NULL, NULL};
 
-               nubase = BKE_curve_nurbs_get(cu);
+               BKE_nurbList_duplicate(&nubase, BKE_curve_nurbs_get(cu));
 
-               BLI_freelistN(&(cu->bev));
+               BLI_freelistN(&(ob->curve_cache->bev));
 
-               if (cu->path) free_path(cu->path);
-               cu->path = NULL;
+               if (ob->curve_cache->path) free_path(ob->curve_cache->path);
+               ob->curve_cache->path = NULL;
 
                if (ob->type == OB_FONT)
                        BKE_vfont_to_curve(G.main, scene, ob, 0);
 
                if (!forOrco)
-                       curve_calc_modifiers_pre(scene, ob, forRender, renderResolution, &originalVerts, &deformedVerts, &numVerts);
+                       curve_calc_modifiers_pre(scene, ob, &nubase, forRender, renderResolution);
 
-               BKE_curve_bevelList_make(ob);
+               BKE_curve_bevelList_make(ob, &nubase, forRender != FALSE);
 
                /* If curve has no bevel will return nothing */
                BKE_curve_bevel_make(scene, ob, &dlbev, forRender, renderResolution);
 
                /* no bevel or extrude, and no width correction? */
                if (!dlbev.first && cu->width == 1.0f) {
-                       curve_to_displist(cu, nubase, dispbase, forRender, renderResolution);
+                       curve_to_displist(cu, &nubase, dispbase, forRender, renderResolution);
                }
                else {
                        float widfac = cu->width - 1.0f;
-                       BevList *bl = cu->bev.first;
-                       Nurb *nu = nubase->first;
+                       BevList *bl = ob->curve_cache->bev.first;
+                       Nurb *nu = nubase.first;
 
                        for (; bl && nu; bl = bl->next, nu = nu->next) {
                                DispList *dl;
@@ -1586,33 +1561,25 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
                }
 
                if (!(cu->flag & CU_DEFORM_FILL)) {
-                       curve_to_filledpoly(cu, nubase, dispbase);
+                       curve_to_filledpoly(cu, &nubase, dispbase);
                }
 
                if ((cu->flag & CU_PATH) && !forOrco)
-                       calc_curvepath(ob);
-
-               /* make copy of 'undeformed" displist for texture space calculation
-                * actually, it's not totally undeformed -- pre-tessellation modifiers are
-                * already applied, thats how it worked for years, so keep for compatibility (sergey) */
-               BKE_displist_copy(&cu->disp, dispbase);
-
-               if (!forRender) {
-                       BKE_curve_texspace_calc(cu);
-               }
+                       calc_curvepath(ob, &nubase);
 
                if (!forOrco)
-                       curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, renderResolution, originalVerts, deformedVerts);
+                       curve_calc_modifiers_post(scene, ob, &nubase, dispbase, derivedFinal, forRender, renderResolution);
 
                if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) {
-                       curve_to_filledpoly(cu, nubase, dispbase);
+                       curve_to_filledpoly(cu, &nubase, dispbase);
                }
+
+               BKE_nurbList_free(&nubase);
        }
 }
 
 void BKE_displist_make_curveTypes(Scene *scene, Object *ob, int forOrco)
 {
-       Curve *cu = ob->data;
        ListBase *dispbase;
 
        /* The same check for duplis as in do_makeDispListCurveTypes.
@@ -1621,27 +1588,17 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, int forOrco)
        if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT))
                return;
 
-       BKE_displist_free(&(ob->disp));
-       dispbase = &(ob->disp);
-       BKE_displist_free(dispbase);
-
-       /* free displist used for textspace */
-       BKE_displist_free(&cu->disp);
+       BKE_object_free_derived_caches(ob);
 
-       do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco, 0);
+       if (!ob->curve_cache) {
+               ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
+       }
 
-       if (ob->derivedFinal) {
-               DM_set_object_boundbox(ob, ob->derivedFinal);
+       dispbase = &(ob->curve_cache->disp);
 
-               /* always keep curve's  BB in sync with non-deformed displist */
-               if (cu->bb == NULL)
-                       cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
+       do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco, 0);
 
-               boundbox_dispbase(cu->bb, &cu->disp);
-       }
-       else {
-               boundbox_displist(ob);
-       }
+       boundbox_displist_object(ob);
 }
 
 void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase,
@@ -1676,16 +1633,13 @@ float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *derivedFina
        return orco;
 }
 
-static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase)
+void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3])
 {
-       float min[3], max[3];
        DispList *dl;
        float *vert;
        int a, tot = 0;
        int doit = 0;
 
-       INIT_MINMAX(min, max);
-
        for (dl = dispbase->first; dl; dl = dl->next) {
                tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts;
                vert = dl->verts;
@@ -1700,26 +1654,29 @@ static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase)
                zero_v3(min);
                zero_v3(max);
        }
-
-       BKE_boundbox_init_from_minmax(bb, min, max);
 }
 
 /* this is confusing, there's also min_max_object, appplying the obmat... */
-static void boundbox_displist(Object *ob)
+static void boundbox_displist_object(Object *ob)
 {
        if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
-               Curve *cu = ob->data;
-
-               /* calculate curve's BB based on non-deformed displist */
-               if (cu->bb == NULL)
-                       cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
-
-               boundbox_dispbase(cu->bb, &cu->disp);
+               /* Curver's BB is already calculated as a part of modifier stack,
+                * here we only calculate object BB based on final display list.
+                */
 
                /* object's BB is calculated from final displist */
                if (ob->bb == NULL)
                        ob->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
 
-               boundbox_dispbase(ob->bb, &ob->disp);
+               if (ob->derivedFinal) {
+                       DM_set_object_boundbox(ob, ob->derivedFinal);
+               }
+               else {
+                       float min[3], max[3];
+
+                       INIT_MINMAX(min, max);
+                       BKE_displist_minmax(&ob->curve_cache->disp, min, max);
+                       BKE_boundbox_init_from_minmax(ob->bb, min, max);
+               }
        }
 }
index 0df8684044a082efb64133faedfa810eb6a50b20..81b0de9fd32c59bd0ed63b6ef058161388c91a93 100644 (file)
@@ -67,6 +67,7 @@
 #include "BKE_blender.h"
 #include "BKE_collision.h"
 #include "BKE_constraint.h"
+#include "BKE_curve.h"
 #include "BKE_deform.h"
 #include "BKE_depsgraph.h"
 #include "BKE_displist.h"
@@ -176,10 +177,10 @@ static void precalculate_effector(EffectorCache *eff)
        if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) {
                Curve *cu= eff->ob->data;
                if (cu->flag & CU_PATH) {
-                       if (cu->path==NULL || cu->path->data==NULL)
+                       if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL)
                                BKE_displist_make_curveTypes(eff->scene, eff->ob, 0);
 
-                       if (cu->path && cu->path->data) {
+                       if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) {
                                where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
                                mul_m4_v3(eff->ob->obmat, eff->guide_loc);
                                mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir);
index 7c23438f93d1f7186d7123e2afb3ea4ad5298750..c899ae1f16c5b86d78666b6d1bd9fabf5e13d1cb 100644 (file)
@@ -1,4 +1,5 @@
 /*
+
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -41,6 +42,7 @@
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
+#include "BLI_threads.h"
 #include "BLI_vfontdata.h"
 #include "BLI_utildefines.h"
 
@@ -59,6 +61,7 @@
 #include "BKE_curve.h"
 #include "BKE_displist.h"
 
+static ThreadMutex vfont_mutex = BLI_MUTEX_INITIALIZER;
 
 /* The vfont code */
 void BKE_vfont_free_data(struct VFont *vfont)
@@ -138,6 +141,18 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
        if (!vfont->data) {
                PackedFile *pf;
 
+               BLI_mutex_lock(&vfont_mutex);
+
+               if (vfont->data) {
+                       /* Check data again, since it might have been already
+                        * initialized from other thread (previous check is
+                        * not accurate or threading, just prevents unneeded
+                        * lock if all the data is here for sure).
+                        */
+                       BLI_mutex_unlock(&vfont_mutex);
+                       return vfont->data;
+               }
+
                if (BKE_vfont_is_builtin(vfont)) {
                        pf = get_builtin_packedfile();
                }
@@ -175,8 +190,10 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
                                freePackedFile(pf);
                        }
                }
+
+               BLI_mutex_unlock(&vfont_mutex);
        }
-       
+
        return vfont->data;
 }
 
@@ -819,8 +836,10 @@ makebreak:
                
                cucu->flag |= (CU_PATH + CU_FOLLOW);
                
-               if (cucu->path == NULL) BKE_displist_make_curveTypes(scene, cu->textoncurve, 0);
-               if (cucu->path) {
+               if (cu->textoncurve->curve_cache == NULL || cu->textoncurve->curve_cache->path == NULL) {
+                       BKE_displist_make_curveTypes(scene, cu->textoncurve, 0);
+               }
+               if (cu->textoncurve->curve_cache->path) {
                        float distfac, imat[4][4], imat3[3][3], cmat[3][3];
                        float minx, maxx, miny, maxy;
                        float timeofs, sizefac;
@@ -845,7 +864,7 @@ makebreak:
                        /* we put the x-coordinaat exact at the curve, the y is rotated */
                        
                        /* length correction */
-                       distfac = sizefac * cucu->path->totdist / (maxx - minx);
+                       distfac = sizefac * cu->textoncurve->curve_cache->path->totdist / (maxx - minx);
                        timeofs = 0.0f;
                        
                        if (distfac > 1.0f) {
index d2d2cb1c2d002705e6812c31f35d72493e029825..aaac17ac1edb34829e0f73869b3923bd1a2a7f07 100644 (file)
@@ -734,12 +734,13 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const
        }
 }
 
-void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode)
+void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb,
+                               float **per_keyblock_weights, const int mode)
 {
        KeyBlock *kb;
        int *ofsp, ofs[3], elemsize, b;
        char *cp, *poin, *reffrom, *from, elemstr[8];
-       int poinsize;
+       int poinsize, keyblock_index;
 
        /* currently always 0, in future key_pointer_size may assign */
        ofs[1] = 0;
@@ -763,14 +764,14 @@ void BKE_key_evaluate_relative(const int start, int end, const int tot, char *ba
        
        /* step 2: do it */
        
-       for (kb = key->block.first; kb; kb = kb->next) {
+       for (kb = key->block.first, keyblock_index = 0; kb; kb = kb->next, keyblock_index++) {
                if (kb != key->refkey) {
                        float icuval = kb->curval;
                        
                        /* only with value, and no difference allowed */
                        if (!(kb->flag & KEYBLOCK_MUTE) && icuval != 0.0f && kb->totelem == tot) {
                                KeyBlock *refb;
-                               float weight, *weights = kb->weights;
+                               float weight, *weights = per_keyblock_weights ? per_keyblock_weights[keyblock_index] : NULL;
                                char *freefrom = NULL, *freereffrom = NULL;
 
                                /* reference now can be any block */
@@ -1058,7 +1059,7 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
        if (freek4) MEM_freeN(freek4);
 }
 
-static float *get_weights_array(Object *ob, char *vgroup)
+static float *get_weights_array(Object *ob, char *vgroup, WeightsArrayCache *cache)
 {
        MDeformVert *dvert = NULL;
        BMEditMesh *em = NULL;
@@ -1091,7 +1092,21 @@ static float *get_weights_array(Object *ob, char *vgroup)
        if (defgrp_index != -1) {
                float *weights;
                int i;
-               
+
+               if (cache) {
+                       if (cache->defgroup_weights == NULL) {
+                               int num_defgroup = BLI_countlist(&ob->defbase);
+                               cache->defgroup_weights =
+                                   MEM_callocN(sizeof(*cache->defgroup_weights) * num_defgroup,
+                                               "cached defgroup weights");
+                               cache->num_defgroup_weights = num_defgroup;
+                       }
+
+                       if (cache->defgroup_weights[defgrp_index]) {
+                               return cache->defgroup_weights[defgrp_index];
+                       }
+               }
+
                weights = MEM_mallocN(totvert * sizeof(float), "weights");
 
                if (em) {
@@ -1107,11 +1122,61 @@ static float *get_weights_array(Object *ob, char *vgroup)
                        }
                }
 
+               if (cache) {
+                       cache->defgroup_weights[defgrp_index] = weights;
+               }
+
                return weights;
        }
        return NULL;
 }
 
+float **BKE_keyblock_get_per_block_weights(Object *ob, Key *key, WeightsArrayCache *cache)
+{
+       KeyBlock *keyblock;
+       float **per_keyblock_weights;
+       int keyblock_index;
+
+       per_keyblock_weights =
+               MEM_mallocN(sizeof(*per_keyblock_weights) * key->totkey,
+                           "per keyblock weights");
+
+       for (keyblock = key->block.first, keyblock_index = 0;
+            keyblock;
+            keyblock = keyblock->next, keyblock_index++)
+       {
+               per_keyblock_weights[keyblock_index] = get_weights_array(ob, keyblock->vgroup, cache);
+       }
+
+       return per_keyblock_weights;
+}
+
+void BKE_keyblock_free_per_block_weights(Key *key, float **per_keyblock_weights, WeightsArrayCache *cache)
+{
+       int a;
+
+       if (cache) {
+               if (cache->num_defgroup_weights) {
+                       for (a = 0; a < cache->num_defgroup_weights; a++) {
+                               if (cache->defgroup_weights[a]) {
+                                       MEM_freeN(cache->defgroup_weights[a]);
+                               }
+                       }
+                       MEM_freeN(cache->defgroup_weights);
+               }
+               cache->defgroup_weights = NULL;
+       }
+       else {
+               for (a = 0; a < key->totkey; a++) {
+                       if (per_keyblock_weights[a]) {
+                               MEM_freeN(per_keyblock_weights[a]);
+                       }
+               }
+       }
+
+       MEM_freeN(per_keyblock_weights);
+}
+
 static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
 {
        KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
@@ -1144,17 +1209,11 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int
        }
        else {
                if (key->type == KEY_RELATIVE) {
-                       KeyBlock *kb;
-                       for (kb = key->block.first; kb; kb = kb->next) {
-                               kb->weights = get_weights_array(ob, kb->vgroup);
-                       }
-
-                       BKE_key_evaluate_relative(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);
-                               kb->weights = NULL;
-                       }
+                       WeightsArrayCache cache = {0, NULL};
+                       float **per_keyblock_weights;
+                       per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, &cache);
+                       BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
+                       BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, &cache);
                }
                else {
                        const float ctime_scaled = key->ctime / 100.0f;
@@ -1197,11 +1256,11 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const
        for (a = 0, nu = cu->nurb.first; nu; nu = nu->next, a += step) {
                if (nu->bp) {
                        step = nu->pntsu * nu->pntsv;
-                       BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BPOINT);
+                       BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, NULL, KEY_MODE_BPOINT);
                }
                else if (nu->bezt) {
                        step = 3 * nu->pntsu;
-                       BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE);
+                       BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, NULL, KEY_MODE_BEZTRIPLE);
                }
                else {
                        step = 0;
@@ -1315,17 +1374,10 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int
        }
        else {
                if (key->type == KEY_RELATIVE) {
-                       KeyBlock *kb;
-                       
-                       for (kb = key->block.first; kb; kb = kb->next)
-                               kb->weights = get_weights_array(ob, kb->vgroup);
-                       
-                       BKE_key_evaluate_relative(0, tot, tot, out, key, actkb, KEY_MODE_DUMMY);
-                       
-                       for (kb = key->block.first; kb; kb = kb->next) {
-                               if (kb->weights) MEM_freeN(kb->weights);
-                               kb->weights = NULL;
-                       }
+                       float **per_keyblock_weights;
+                       per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, NULL);
+                       BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
+                       BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, NULL);
                }
                else {
                        const float ctime_scaled = key->ctime / 100.0f;
@@ -1415,7 +1467,7 @@ float *BKE_key_evaluate_object_ex(Scene *scene, Object *ob, int *r_totelem,
                }
                
                if (OB_TYPE_SUPPORT_VGROUP(ob->type)) {
-                       float *weights = get_weights_array(ob, kb->vgroup);
+                       float *weights = get_weights_array(ob, kb->vgroup, NULL);
 
                        cp_key(0, tot, tot, out, key, actkb, kb, weights, 0);
 
index a4892253c63b2b86d16e8ebd811d7fbffb416b47..60b4db6aa9b4e5e26bf4fb9b9453b7a524810bac 100644 (file)
@@ -51,6 +51,7 @@
 #include "BKE_animsys.h"
 #include "BKE_anim.h"
 #include "BKE_cdderivedmesh.h"
+#include "BKE_curve.h"
 #include "BKE_displist.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
@@ -164,7 +165,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
                lt->typeu = lt->typev = lt->typew = KEY_LINEAR;
 
                /* prevent using deformed locations */
-               BKE_displist_free(&ltOb->disp);
+               BKE_displist_free(&ltOb->curve_cache->disp);
 
                copy_m4_m4(mat, ltOb->obmat);
                unit_m4(ltOb->obmat);
@@ -306,37 +307,46 @@ void BKE_lattice_make_local(Lattice *lt)
        }
 }
 
-void init_latt_deform(Object *oblatt, Object *ob)
+typedef struct LatticeDeformData {
+       Object *object;
+       float *latticedata;
+       float latmat[4][4];
+} LatticeDeformData;
+
+LatticeDeformData *init_latt_deform(Object *oblatt, Object *ob)
 {
        /* we make an array with all differences */
        Lattice *lt = oblatt->data;
        BPoint *bp;
-       DispList *dl = BKE_displist_find(&oblatt->disp, DL_VERTS);
+       DispList *dl = oblatt->curve_cache ? BKE_displist_find(&oblatt->curve_cache->disp, DL_VERTS) : NULL;
        float *co = dl ? dl->verts : NULL;
        float *fp, imat[4][4];
        float fu, fv, fw;
        int u, v, w;
+       float *latticedata;
+       float latmat[4][4];
+       LatticeDeformData *lattice_deform_data;
 
        if (lt->editlatt) lt = lt->editlatt->latt;
        bp = lt->def;
        
-       fp = lt->latticedata = MEM_mallocN(sizeof(float) * 3 * lt->pntsu * lt->pntsv * lt->pntsw, "latticedata");
+       fp = latticedata = MEM_mallocN(sizeof(float) * 3 * lt->pntsu * lt->pntsv * lt->pntsw, "latticedata");
        
        /* for example with a particle system: (ob == NULL) */
        if (ob == NULL) {
                /* in deformspace, calc matrix  */
-               invert_m4_m4(lt->latmat, oblatt->obmat);
+               invert_m4_m4(latmat, oblatt->obmat);
        
                /* back: put in deform array */
-               invert_m4_m4(imat, lt->latmat);
+               invert_m4_m4(imat, latmat);
        }
        else {
                /* in deformspace, calc matrix */
                invert_m4_m4(imat, oblatt->obmat);
-               mul_m4_m4m4(lt->latmat, imat, ob->obmat);
+               mul_m4_m4m4(latmat, imat, ob->obmat);
        
                /* back: put in deform array */
-               invert_m4_m4(imat, lt->latmat);
+               invert_m4_m4(imat, latmat);
        }
        
        for (w = 0, fw = lt->fw; w < lt->pntsw; w++, fw += lt->dw) {
@@ -357,10 +367,18 @@ void init_latt_deform(Object *oblatt, Object *ob)
                        }
                }
        }
+
+       lattice_deform_data = MEM_mallocN(sizeof(LatticeDeformData), "Lattice Deform Data");
+       lattice_deform_data->latticedata = latticedata;
+       lattice_deform_data->object = oblatt;
+       copy_m4_m4(lattice_deform_data->latmat, latmat);
+
+       return lattice_deform_data;
 }
 
-void calc_latt_deform(Object *ob, float co[3], float weight)
+void calc_latt_deform(LatticeDeformData *lattice_deform_data, float co[3], float weight)
 {
+       Object *ob = lattice_deform_data->object;
        Lattice *lt = ob->data;
        float u, v, w, tu[4], tv[4], tw[4];
        float vec[3];
@@ -374,7 +392,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
 
 
        if (lt->editlatt) lt = lt->editlatt->latt;
-       if (lt->latticedata == NULL) return;
+       if (lattice_deform_data->latticedata == NULL) return;
 
        if (lt->vgroup[0] && dvert) {
                defgrp_index = defgroup_name_index(ob, lt->vgroup);
@@ -382,7 +400,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
        }
 
        /* co is in local coords, treat with latmat */
-       mul_v3_m4v3(vec, lt->latmat, co);
+       mul_v3_m4v3(vec, lattice_deform_data->latmat, co);
 
        /* u v w coords */
 
@@ -455,7 +473,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
                                                                idx_u = idx_v;
                                                        }
 
-                                                       madd_v3_v3fl(co, &lt->latticedata[idx_u * 3], u);
+                                                       madd_v3_v3fl(co, &lattice_deform_data->latticedata[idx_u * 3], u);
 
                                                        if (defgrp_index != -1)
                                                                weight_blend += (u * defvert_find_weight(dvert + idx_u, defgrp_index));
@@ -471,15 +489,12 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
 
 }
 
-void end_latt_deform(Object *ob)
+void end_latt_deform(LatticeDeformData *lattice_deform_data)
 {
-       Lattice *lt = ob->data;
-       
-       if (lt->editlatt) lt = lt->editlatt->latt;
-       
-       if (lt->latticedata)
-               MEM_freeN(lt->latticedata);
-       lt->latticedata = NULL;
+       if (lattice_deform_data->latticedata)
+               MEM_freeN(lattice_deform_data->latticedata);
+
+       MEM_freeN(lattice_deform_data);
 }
 
 /* calculations is in local space of deformed object
@@ -506,13 +521,12 @@ static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd)
  */
 static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius)
 {
-       Curve *cu = ob->data;
        BevList *bl;
        float ctime1;
        int cycl = 0;
        
        /* test for cyclic */
-       bl = cu->bev.first;
+       bl = ob->curve_cache->bev.first;
        if (!bl->nr) return 0;
        if (bl->poly > -1) cycl = 1;
 
@@ -527,7 +541,7 @@ static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir
        if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
                
                if (cycl == 0) {
-                       Path *path = cu->path;
+                       Path *path = ob->curve_cache->path;
                        float dvec[3];
                        
                        if (ctime < 0.0f) {
@@ -565,9 +579,9 @@ static int calc_curve_deform(Scene *scene, Object *par, float co[3],
        const int is_neg_axis = (axis > 2);
 
        /* to be sure, mostly after file load */
-       if (cu->path == NULL) {
+       if (ELEM(NULL, par->curve_cache, par->curve_cache->path)) {
                BKE_displist_make_curveTypes(scene, par, 0);
-               if (cu->path == NULL) return 0;  // happens on append...
+               if (par->curve_cache->path == NULL) return 0;  // happens on append...
        }
        
        /* options */
@@ -576,14 +590,14 @@ static int calc_curve_deform(Scene *scene, Object *par, float co[3],
                if (cu->flag & CU_STRETCH)
                        fac = (-co[index] - cd->dmax[index]) / (cd->dmax[index] - cd->dmin[index]);
                else
-                       fac = -(co[index] - cd->dmax[index]) / (cu->path->totdist);
+                       fac = -(co[index] - cd->dmax[index]) / (par->curve_cache->path->totdist);
        }
        else {
                index = axis;
                if (cu->flag & CU_STRETCH)
                        fac = (co[index] - cd->dmin[index]) / (cd->dmax[index] - cd->dmin[index]);
                else
-                       fac = +(co[index] - cd->dmin[index]) / (cu->path->totdist);
+                       fac = +(co[index] - cd->dmin[index]) / (par->curve_cache->path->totdist);
        }
        
        if (where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) {  /* returns OK */
@@ -815,13 +829,14 @@ void curve_deform_vector(Scene *scene, Object *cuOb, Object *target,
 void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
                           float (*vertexCos)[3], int numVerts, const char *vgroup, float fac)
 {
+       LatticeDeformData *lattice_deform_data;
        int a;
        int use_vgroups;
 
        if (laOb->type != OB_LATTICE)
                return;
 
-       init_latt_deform(laOb, target);
+       lattice_deform_data = init_latt_deform(laOb, target);
 
        /* check whether to use vertex groups (only possible if target is a Mesh)
         * we want either a Mesh with no derived data, or derived data with
@@ -855,16 +870,16 @@ void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
                                weight = defvert_find_weight(dvert, defgrp_index);
 
                                if (weight > 0.0f)
-                                       calc_latt_deform(laOb, vertexCos[a], weight * fac);
+                                       calc_latt_deform(lattice_deform_data, vertexCos[a], weight * fac);
                        }
                }
        }
        else {
                for (a = 0; a < numVerts; a++) {
-                       calc_latt_deform(laOb, vertexCos[a], fac);
+                       calc_latt_deform(lattice_deform_data, vertexCos[a], fac);
                }
        }
-       end_latt_deform(laOb);
+       end_latt_deform(lattice_deform_data);
 }
 
 int object_deform_mball(Object *ob, ListBase *dispbase)
@@ -991,11 +1006,17 @@ void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3])
 void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
 {
        Lattice *lt = ob->data;
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        float (*vertexCos)[3] = NULL;
        int numVerts, editmode = (lt->editlatt != NULL);
 
-       BKE_displist_free(&ob->disp);
+       if (ob->curve_cache) {
+               BKE_displist_free(&ob->curve_cache->disp);
+       }
+       else {
+               ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for lattice");
+       }
 
        for (; md; md = md->next) {
                ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -1021,7 +1042,7 @@ void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
                dl->nr = numVerts;
                dl->verts = (float *) vertexCos;
                
-               BLI_addtail(&ob->disp, dl);
+               BLI_addtail(&ob->curve_cache->disp, dl);
        }
 }
 
index 6dc3c6d7bc63c83930c2d7a2bce5611a9654f0e9..4abeb8389d6566cbd80516a8e7c07ac4f27e6fff 100644 (file)
@@ -1228,7 +1228,9 @@ int object_remove_material_slot(Object *ob)
        /* check indices from mesh */
        if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
                data_delete_material_index_id((ID *)ob->data, actcol - 1);
-               BKE_displist_free(&ob->disp);
+               if (ob->curve_cache) {
+                       BKE_displist_free(&ob->curve_cache->disp);
+               }
        }
 
        return TRUE;
index 173b193b7527ff542c6e5f28fb8b11f5c2128f0c..5d5231ae258148db8e029fb633fafbbcd18b958a 100644 (file)
@@ -56,6 +56,7 @@
 
 /*  #include "BKE_object.h" */
 #include "BKE_animsys.h"
+#include "BKE_curve.h"
 #include "BKE_scene.h"
 #include "BKE_library.h"
 #include "BKE_displist.h"
@@ -199,7 +200,6 @@ void BKE_mball_free(MetaBall *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) BKE_displist_free(&mb->disp);
 }
@@ -233,7 +233,6 @@ MetaBall *BKE_mball_copy(MetaBall *mb)
        for (a = 0; a < mbn->totcol; a++) {
                id_us_plus((ID *)mbn->mat[a]);
        }
-       mbn->bb = MEM_dupallocN(mb->bb);
 
        mbn->editelems = NULL;
        mbn->lastelem = NULL;
@@ -366,7 +365,7 @@ void BKE_mball_texspace_calc(Object *ob)
        (min)[0] = (min)[1] = (min)[2] = 1.0e30f;
        (max)[0] = (max)[1] = (max)[2] = -1.0e30f;
 
-       dl = ob->disp.first;
+       dl = ob->curve_cache->disp.first;
        while (dl) {
                tot = dl->nr;
                if (tot) do_it = TRUE;
@@ -2281,7 +2280,7 @@ static void mball_count(PROCESS *process, Scene *scene, Object *basis)
        }
 }
 
-void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
+void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase, bool for_render)
 {
        MetaBall *mb;
        DispList *dl;
@@ -2294,7 +2293,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
        mball_count(&process, scene, ob);
 
        if (process.totelem == 0) return;
-       if ((G.is_rendering == FALSE) && (mb->flag == MB_UPDATE_NEVER)) return;
+       if ((for_render == FALSE) && (mb->flag == MB_UPDATE_NEVER)) return;
        if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return;
 
        process.thresh = mb->thresh;
@@ -2332,7 +2331,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
        }
 
        /* width is size per polygonize cube */
-       if (G.is_rendering) {
+       if (for_render) {
                width = mb->rendersize;
        }
        else {
index 095957b40d5a83788f08544922ffda35674c1823..f1729b8e098c65ab8f94bdfbbeb83e17fbaa0fc1 100644 (file)
@@ -657,6 +657,8 @@ void BKE_mesh_boundbox_calc(Mesh *me, float r_loc[3], float r_size[3])
        r_size[2] = (max[2] - min[2]) / 2.0f;
        
        BKE_boundbox_init_from_minmax(bb, min, max);
+
+       bb->flag &= ~BOUNDBOX_INVALID;
 }
 
 void BKE_mesh_texspace_calc(Mesh *me)
@@ -686,15 +688,16 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob)
        if (ob->bb)
                return ob->bb;
 
-       if (!me->bb)
+       if (me->bb == NULL || (me->bb->flag & BOUNDBOX_INVALID)) {
                BKE_mesh_texspace_calc(me);
+       }
 
        return me->bb;
 }
 
 void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_size[3])
 {
-       if (!me->bb) {
+       if (me->bb == NULL || (me->bb->flag & BOUNDBOX_INVALID)) {
                BKE_mesh_texspace_calc(me);
        }
 
@@ -1307,7 +1310,13 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
                             MEdge **alledge, int *totedge, MLoop **allloop, MPoly **allpoly,
                             int *totloop, int *totpoly)
 {
-       return BKE_mesh_nurbs_displist_to_mdata(ob, &ob->disp,
+       ListBase disp = {NULL, NULL};
+
+       if (ob->curve_cache) {
+               disp = ob->curve_cache->disp;
+       }
+
+       return BKE_mesh_nurbs_displist_to_mdata(ob, &disp,
                                                allvert, totvert,
                                                alledge, totedge,
                                                allloop, allpoly, NULL,
@@ -1653,8 +1662,13 @@ void BKE_mesh_from_nurbs(Object *ob)
 {
        Curve *cu = (Curve *) ob->data;
        bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
+       ListBase disp = {NULL, NULL};
+
+       if (ob->curve_cache) {
+               disp = ob->curve_cache->disp;
+       }
 
-       BKE_mesh_from_nurbs_displist(ob, &ob->disp, use_orco_uv);
+       BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv);
 }
 
 typedef struct EdgeLink {
index 41e0acf9f7a3bf2290b815d624edb597a32b11fa..780bd9733f5f7a708391d91869335622d07da1fc 100644 (file)
 
 #include "MOD_modifiertypes.h"
 
-ModifierTypeInfo *modifierType_getInfo(ModifierType type)
+static ModifierTypeInfo *modifier_types[NUM_MODIFIER_TYPES] = {NULL};
+static VirtualModifierData virtualModifierCommonData;
+
+void BKE_modifier_init(void)
 {
-       static ModifierTypeInfo *types[NUM_MODIFIER_TYPES] = {NULL};
-       static int types_init = 1;
+       ModifierData *md;
 
-       if (types_init) {
-               modifier_type_init(types); /* MOD_utils.c */
-               types_init = 0;
-       }
+       /* Initialize modifier types */
+       modifier_type_init(modifier_types); /* MOD_utils.c */
+
+       /* Initialize global cmmon storage used for virtual modifier list */
+       md = modifier_new(eModifierType_Armature);
+       virtualModifierCommonData.amd = *((ArmatureModifierData *) md);
+       modifier_free(md);
+
+       md = modifier_new(eModifierType_Curve);
+       virtualModifierCommonData.cmd = *((CurveModifierData *) md);
+       modifier_free(md);
 
+       md = modifier_new(eModifierType_Lattice);
+       virtualModifierCommonData.lmd = *((LatticeModifierData *) md);
+       modifier_free(md);
+
+       md = modifier_new(eModifierType_ShapeKey);
+       virtualModifierCommonData.smd = *((ShapeKeyModifierData *) md);
+       modifier_free(md);
+
+       virtualModifierCommonData.amd.modifier.mode |= eModifierMode_Virtual;
+       virtualModifierCommonData.cmd.modifier.mode |= eModifierMode_Virtual;
+       virtualModifierCommonData.lmd.modifier.mode |= eModifierMode_Virtual;
+       virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual;
+}
+
+ModifierTypeInfo *modifierType_getInfo(ModifierType type)
+{
        /* type unsigned, no need to check < 0 */
-       if (type < NUM_MODIFIER_TYPES && types[type]->name[0] != '\0') {
-               return types[type];
+       if (type < NUM_MODIFIER_TYPES && modifier_types[type]->name[0] != '\0') {
+               return modifier_types[type];
        }
        else {
                return NULL;
@@ -289,7 +314,8 @@ void modifier_setError(ModifierData *md, const char *_format, ...)
  */
 int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *lastPossibleCageIndex_r, int virtual_)
 {
-       ModifierData *md = (virtual_) ? modifiers_getVirtualModifierList(ob) : ob->modifiers.first;
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = (virtual_) ? modifiers_getVirtualModifierList(ob, &virtualModifierData) : ob->modifiers.first;
        int i, cageIndex = -1;
 
        if (lastPossibleCageIndex_r) {
@@ -435,74 +461,43 @@ ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, in
 /* NOTE: This is to support old files from before Blender supported modifiers,
  * in some cases versioning code updates these so for new files this will
  * return an empty list. */
-ModifierData *modifiers_getVirtualModifierList(Object *ob)
+ModifierData *modifiers_getVirtualModifierList(Object *ob, VirtualModifierData *virtualModifierData)
 {
-       /* Kinda hacky, but should be fine since we are never
-        * re-entrant and avoid free hassles.
-        */
-       static ArmatureModifierData amd;
-       static CurveModifierData cmd;
-       static LatticeModifierData lmd;
-       static ShapeKeyModifierData smd;
-       static int init = 1;
        ModifierData *md;
 
-       if (init) {
-               md = modifier_new(eModifierType_Armature);
-               amd = *((ArmatureModifierData *) md);
-               modifier_free(md);
-
-               md = modifier_new(eModifierType_Curve);
-               cmd = *((CurveModifierData *) md);
-               modifier_free(md);
-
-               md = modifier_new(eModifierType_Lattice);
-               lmd = *((LatticeModifierData *) md);
-               modifier_free(md);
-
-               md = modifier_new(eModifierType_ShapeKey);
-               smd = *((ShapeKeyModifierData *) md);
-               modifier_free(md);
-
-               amd.modifier.mode |= eModifierMode_Virtual;
-               cmd.modifier.mode |= eModifierMode_Virtual;
-               lmd.modifier.mode |= eModifierMode_Virtual;
-               smd.modifier.mode |= eModifierMode_Virtual;
-
-               init = 0;
-       }
-
        md = ob->modifiers.first;
 
+       *virtualModifierData = virtualModifierCommonData;
+
        if (ob->parent) {
                if (ob->parent->type == OB_ARMATURE && ob->partype == PARSKEL) {
-                       amd.object = ob->parent;
-                       amd.modifier.next = md;
-                       amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
-                       md = &amd.modifier;
+                       virtualModifierData->amd.object = ob->parent;
+                       virtualModifierData->amd.modifier.next = md;
+                       virtualModifierData->amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
+                       md = &virtualModifierData->amd.modifier;
                }
                else if (ob->parent->type == OB_CURVE && ob->partype == PARSKEL) {
-                       cmd.object = ob->parent;
-                       cmd.defaxis = ob->trackflag + 1;
-                       cmd.modifier.next = md;
-                       md = &cmd.modifier;
+                       virtualModifierData->cmd.object = ob->parent;
+                       virtualModifierData->cmd.defaxis = ob->trackflag + 1;
+                       virtualModifierData->cmd.modifier.next = md;
+                       md = &virtualModifierData->cmd.modifier;
                }
                else if (ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
-                       lmd.object = ob->parent;
-                       lmd.modifier.next = md;
-                       md = &lmd.modifier;
+                       virtualModifierData->lmd.object = ob->parent;
+                       virtualModifierData->lmd.modifier.next = md;
+                       md = &virtualModifierData->lmd.modifier;
                }
        }
 
        /* shape key modifier, not yet for curves */
        if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object(ob)) {
                if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
-                       smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
+                       virtualModifierData->smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
                else
-                       smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage;
+                       virtualModifierData->smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage;
 
-               smd.modifier.next = md;
-               md = &smd.modifier;
+               virtualModifierData->smd.modifier.next = md;
+               md = &virtualModifierData->smd.modifier;
        }
 
        return md;
@@ -513,7 +508,8 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
  */
 Object *modifiers_isDeformedByArmature(Object *ob)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        ArmatureModifierData *amd = NULL;
        
        /* return the first selected armature, this lets us use multiple armatures */
@@ -536,7 +532,8 @@ Object *modifiers_isDeformedByArmature(Object *ob)
  */
 Object *modifiers_isDeformedByLattice(Object *ob)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        LatticeModifierData *lmd = NULL;
        
        /* return the first selected lattice, this lets us use multiple lattices */
@@ -559,7 +556,8 @@ Object *modifiers_isDeformedByLattice(Object *ob)
  */
 Object *modifiers_isDeformedByCurve(Object *ob)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        CurveModifierData *cmd = NULL;
        
        /* return the first selected curve, this lets us use multiple curves */
@@ -579,7 +577,8 @@ Object *modifiers_isDeformedByCurve(Object *ob)
 
 bool modifiers_usesArmature(Object *ob, bArmature *arm)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        for (; md; md = md->next) {
                if (md->type == eModifierType_Armature) {
@@ -604,7 +603,8 @@ bool modifier_isCorrectableDeformed(ModifierData *md)
 
 bool modifiers_isCorrectableDeformed(Object *ob)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        
        for (; md; md = md->next) {
                if (ob->mode == OB_MODE_EDIT && (md->mode & eModifierMode_Editmode) == 0) {
index 150c20d047db2d400b9e8cb5ee96b3be17c43336..714d5d11e32dfab6f9bd58b2485f9fc5c6a2cfb3 100644 (file)
@@ -167,6 +167,19 @@ void BKE_object_free_bulletsoftbody(Object *ob)
        }
 }
 
+void BKE_object_free_curve_cache(Object *ob)
+{
+       if (ob->curve_cache) {
+               BKE_displist_free(&ob->curve_cache->disp);
+               BLI_freelistN(&ob->curve_cache->bev);
+               if (ob->curve_cache->path) {
+                       free_path(ob->curve_cache->path);
+               }
+               MEM_freeN(ob->curve_cache);
+               ob->curve_cache = NULL;
+       }
+}
+
 void BKE_object_free_modifiers(Object *ob)
 {
        while (ob->modifiers.first) {
@@ -246,8 +259,14 @@ void BKE_object_free_derived_caches(Object *ob)
                Mesh *me = ob->data;
 
                if (me->bb) {
-                       MEM_freeN(me->bb);
-                       me->bb = NULL;
+                       me->bb->flag |= BOUNDBOX_INVALID;
+               }
+       }
+       else if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
+               Curve *cu = ob->data;
+
+               if (cu->bb) {
+                       cu->bb->flag |= BOUNDBOX_INVALID;
                }
        }
 
@@ -267,7 +286,9 @@ void BKE_object_free_derived_caches(Object *ob)
                ob->derivedDeform = NULL;
        }
        
-       BKE_displist_free(&ob->disp);
+       if (ob->curve_cache) {
+               BKE_displist_free(&ob->curve_cache->disp);
+       }
 }
 
 /* do not free object itself */
@@ -337,6 +358,14 @@ void BKE_object_free(Object *ob)
        free_sculptsession(ob);
 
        if (ob->pc_ids.first) BLI_freelistN(&ob->pc_ids);
+
+       /* Free runtime curves data. */
+       if (ob->curve_cache) {
+               BLI_freelistN(&ob->curve_cache->bev);
+               if (ob->curve_cache->path)
+                       free_path(ob->curve_cache->path);
+               MEM_freeN(ob->curve_cache);
+       }
 }
 
 static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
@@ -1256,8 +1285,6 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches)
 
        for (a = 0; a < obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
        
-       obn->disp.first = obn->disp.last = NULL;
-       
        if (ob->pd) {
                obn->pd = MEM_dupallocN(ob->pd);
                if (obn->pd->tex)
@@ -1279,7 +1306,10 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches)
        obn->pc_ids.first = obn->pc_ids.last = NULL;
 
        obn->mpath = NULL;
-       
+
+       /* Copy runtime surve data. */
+       obn->curve_cache = NULL;
+
        return obn;
 }
 
@@ -1772,9 +1802,9 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
        unit_m4(mat);
        
        cu = par->data;
-       if (cu->path == NULL || cu->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */
+       if (ELEM3(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */
                BKE_displist_make_curveTypes(scene, par, 0);
-       if (cu->path == NULL) return;
+       if (par->curve_cache->path == NULL) return;
        
        /* catch exceptions: feature for nla stride editing */
        if (ob->ipoflag & OB_DISABLE_PATH) {
@@ -1805,7 +1835,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
        
        /* time calculus is correct, now apply distance offset */
        if (cu->flag & CU_OFFS_PATHDIST) {
-               ctime += timeoffs / cu->path->totdist;
+               ctime += timeoffs / par->curve_cache->path->totdist;
 
                /* restore */
                SWAP(float, sf_orig, ob->sf);
@@ -1962,7 +1992,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
        }
        else if (par->type == OB_LATTICE) {
                Lattice *latt  = par->data;
-               DispList *dl   = BKE_displist_find(&par->disp, DL_VERTS);
+               DispList *dl   = par->curve_cache ? BKE_displist_find(&par->curve_cache->disp, DL_VERTS) : NULL;
                float (*co)[3] = dl ? (float (*)[3])dl->verts : NULL;
                int tot;
 
@@ -2291,7 +2321,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
                bb = BKE_mesh_boundbox_get(ob);
        }
        else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
-               bb = ob->bb ? ob->bb : ((Curve *)ob->data)->bb;
+               bb = BKE_curve_boundbox_get(ob);
        }
        else if (ob->type == OB_MBALL) {
                bb = ob->bb;
@@ -2360,18 +2390,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
                case OB_FONT:
                case OB_SURF:
                {
-                       Curve *cu = ob->data;
-
-                       /* Use the object bounding box so that modifier output
-                        * gets taken into account */
-                       if (ob->bb) {
-                               bb = *(ob->bb);
-                       }
-                       else {
-                               if (cu->bb == NULL)
-                                       BKE_curve_texspace_calc(cu);
-                               bb = *(cu->bb);
-                       }
+                       bb = *BKE_curve_boundbox_get(ob);
 
                        for (a = 0; a < 8; a++) {
                                mul_m4_v3(ob->obmat, bb.vec[a]);
@@ -2519,10 +2538,10 @@ void BKE_object_foreach_display_point(
                        func_cb(co, user_data);
                }
        }
-       else if (ob->disp.first) {
+       else if (ob->curve_cache && ob->curve_cache->disp.first) {
                DispList *dl;
 
-               for (dl = ob->disp.first; dl; dl = dl->next) {
+               for (dl = ob->curve_cache->disp.first; dl; dl = dl->next) {
                        float *v3 = dl->verts;
                        int totvert = dl->nr;
                        int i;
@@ -3158,8 +3177,9 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
        }
        else {
                ModifierData *md;
+               VirtualModifierData virtualModifierData;
                /* cloth */
-               for (md = modifiers_getVirtualModifierList(ob);
+               for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
                     md && (flag != (eModifierMode_Render | eModifierMode_Realtime));
                     md = md->next)
                {
@@ -3180,10 +3200,11 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
 int BKE_object_is_deform_modified(Scene *scene, Object *ob)
 {
        ModifierData *md;
+       VirtualModifierData virtualModifierData;
        int flag = 0;
 
        /* cloth */
-       for (md = modifiers_getVirtualModifierList(ob);
+       for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
             md && (flag != (eModifierMode_Render | eModifierMode_Realtime));
             md = md->next)
        {
@@ -3205,8 +3226,9 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
 bool BKE_object_is_animated(Scene *scene, Object *ob)
 {
        ModifierData *md;
+       VirtualModifierData virtualModifierData;
 
-       for (md = modifiers_getVirtualModifierList(ob); md; md = md->next)
+       for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next)
                if (modifier_dependsOnTime(md) &&
                    (modifier_isEnabled(scene, md, eModifierMode_Realtime) ||
                     modifier_isEnabled(scene, md, eModifierMode_Render)))
index bfec38419f18657f9c2e7f2678276df1cad9c76d..0294ff5645712f6d6c017a4f86e92819092a0d44 100644 (file)
@@ -73,6 +73,7 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
        GHash *gh;
        int i, step1 = 1;
        //int defbase_tot = BLI_countlist(&ob->defbase);
+       VirtualModifierData virtualModifierData;
 
        if (ob->defbase.first == NULL) {
                return NULL;
@@ -88,7 +89,7 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
        BLI_assert(BLI_ghash_size(gh) == defbase_tot);
 
        /* now loop through the armature modifiers and identify deform bones */
-       for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob) : md->next) {
+       for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob, &virtualModifierData) : md->next) {
                if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual)))
                        continue;
 
index 6b754743c111e664010a48f85e72ace2fda41756..216bc94a058d2493d566532dfe22cae56a6b6cae 100644 (file)
@@ -221,12 +221,12 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys)
 }
 #endif
 
-Object *psys_get_lattice(ParticleSimulationData *sim)
+struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData *sim)
 {
-       Object *lattice = NULL;
-       
-       if (psys_in_edit_mode(sim->scene, sim->psys) == 0) {
+       struct LatticeDeformData *lattice_deform_data = NULL;
 
+       if (psys_in_edit_mode(sim->scene, sim->psys) == 0) {
+               Object *lattice = NULL;
                ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys);
 
                for (; md; md = md->next) {
@@ -237,10 +237,10 @@ Object *psys_get_lattice(ParticleSimulationData *sim)
                        }
                }
                if (lattice)
-                       init_latt_deform(lattice, NULL);
+                       lattice_deform_data = init_latt_deform(lattice, NULL);
        }
 
-       return lattice;
+       return lattice_deform_data;
 }
 void psys_disable_all(Object *ob)
 {
@@ -2513,7 +2513,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
        ctx->cfra = cfra;
        ctx->editupdate = editupdate;
 
-       psys->lattice = psys_get_lattice(&ctx->sim);
+       psys->lattice_deform_data = psys_create_lattice_deform_data(&ctx->sim);
 
        /* cache all relevant vertex groups if they exist */
        ctx->vg_length = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_LENGTH);
@@ -2974,7 +2974,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
        psys_free_path_cache(psys, psys->edit);
        cache = psys->pathcache = psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps + 1);
 
-       psys->lattice = psys_get_lattice(sim);
+       psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
        ma = give_current_material(sim->ob, psys->part->omat);
        if (ma && (psys->part->draw_col == PART_DRAW_COL_MAT))
                copy_v3_v3(col, &ma->r);
@@ -3079,9 +3079,9 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
                        }
 
                        /* lattices have to be calculated separately to avoid mixups between effector calculations */
-                       if (psys->lattice) {
+                       if (psys->lattice_deform_data) {
                                for (k = 0, ca = cache[p]; k <= steps; k++, ca++)
-                                       calc_latt_deform(psys->lattice, ca->co, 1.0f);
+                                       calc_latt_deform(psys->lattice_deform_data, ca->co, 1.0f);
                        }
                }
 
@@ -3112,9 +3112,9 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
 
        psys->totcached = totpart;
 
-       if (psys->lattice) {
-               end_latt_deform(psys->lattice);
-               psys->lattice = NULL;
+       if (psys->lattice_deform_data) {
+               end_latt_deform(psys->lattice_deform_data);
+               psys->lattice_deform_data = NULL;
        }
 
        if (vg_effector)
@@ -4166,8 +4166,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
                                                /* TODO: proper velocity handling */
                                        }
 
-                                       if (psys->lattice && edit == 0)
-                                               calc_latt_deform(psys->lattice, state->co, 1.0f);
+                                       if (psys->lattice_deform_data && edit == 0)
+                                               calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
                                }
                        }
                }
@@ -4402,8 +4402,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
                        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);
+                       if (psys->lattice_deform_data)
+                               calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
                }
                else {
                        if (pa->state.time == cfra || ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
@@ -4461,8 +4461,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
                                }
                        }
 
-                       if (sim->psys->lattice)
-                               calc_latt_deform(sim->psys->lattice, state->co, 1.0f);
+                       if (sim->psys->lattice_deform_data)
+                               calc_latt_deform(sim->psys->lattice_deform_data, state->co, 1.0f);
                }
                
                return 1;
@@ -4678,9 +4678,9 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
        sim.psys = psys;
        sim.psmd = psys_get_modifier(ob, psys);
 
-       psys->lattice = psys_get_lattice(&sim);
+       psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
 
-       if (psys->lattice) {
+       if (psys->lattice_deform_data) {
                ParticleData *pa = psys->particles;
                HairKey *hkey;
                int p, h;
@@ -4693,13 +4693,13 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
                        hkey = pa->hair;
                        for (h = 0; h < pa->totkey; h++, hkey++) {
                                mul_m4_v3(hairmat, hkey->co);
-                               calc_latt_deform(psys->lattice, hkey->co, 1.0f);
+                               calc_latt_deform(psys->lattice_deform_data, hkey->co, 1.0f);
                                mul_m4_v3(imat, hkey->co);
                        }
                }
                
-               end_latt_deform(psys->lattice);
-               psys->lattice = NULL;
+               end_latt_deform(psys->lattice_deform_data);
+               psys->lattice_deform_data = NULL;
 
                /* protect the applied shape */
                psys->flag |= PSYS_EDITED;
index 16ea71204ccbe53eb45ee92e99d6f6b68572a02d..ee3f3332ec35297199cca74e39b358ca3ebc8e93 100644 (file)
@@ -1514,9 +1514,9 @@ void psys_threads_free(ParticleThread *threads)
        if (ctx->vg_roughe)
                MEM_freeN(ctx->vg_roughe);
 
-       if (ctx->sim.psys->lattice) {
-               end_latt_deform(ctx->sim.psys->lattice);
-               ctx->sim.psys->lattice= NULL;
+       if (ctx->sim.psys->lattice_deform_data) {
+               end_latt_deform(ctx->sim.psys->lattice_deform_data);
+               ctx->sim.psys->lattice_deform_data = NULL;
        }
 
        /* distribution */
@@ -4108,7 +4108,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
 
        invert_m4_m4(ob->imat, ob->obmat);
        
-       psys->lattice= psys_get_lattice(sim);
+       psys->lattice_deform_data= psys_create_lattice_deform_data(sim);
 
        if (psys->totpart==0) return;
        
@@ -4479,7 +4479,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
                if (part->randsize > 0.0f)
                        pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1);
 
-               psys->lattice= psys_get_lattice(sim);
+               psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
 
                dietime = pa->dietime;
 
@@ -4494,9 +4494,9 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
                else
                        pa->alive = PARS_ALIVE;
 
-               if (psys->lattice) {
-                       end_latt_deform(psys->lattice);
-                       psys->lattice= NULL;
+               if (psys->lattice_deform_data) {
+                       end_latt_deform(psys->lattice_deform_data);
+                       psys->lattice_deform_data = NULL;
                }
 
                if (PSYS_FRAND(p) > disp)
@@ -4777,9 +4777,9 @@ static void system_step(ParticleSimulationData *sim, float cfra)
        update_children(sim);
 
 /* cleanup */
-       if (psys->lattice) {
-               end_latt_deform(psys->lattice);
-               psys->lattice= NULL;
+       if (psys->lattice_deform_data) {
+               end_latt_deform(psys->lattice_deform_data);
+               psys->lattice_deform_data = NULL;
        }
 }
 
index 1874523dac9908ffaf4089999885dbddd2771512..236ff7591321d11bd02b7b1ee305ba0da16c7afc 100644 (file)
@@ -57,6 +57,7 @@
 #include "BLI_callbacks.h"
 #include "BLI_string.h"
 #include "BLI_threads.h"
+#include "BLI_task.h"
 
 #include "BLF_translation.h"
 
@@ -86,6 +87,8 @@
 
 #include "RE_engine.h"
 
+#include "PIL_time.h"
+
 #include "IMB_colormanagement.h"
 
 //XXX #include "BIF_previewrender.h"
@@ -1159,32 +1162,253 @@ static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
                BKE_rigidbody_do_simulation(scene, ctime);
 }
 
-static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent)
+typedef struct StatisicsEntry {
+       struct StatisicsEntry *next, *prev;
+       Object *object;
+       double time;
+} StatisicsEntry;
+
+typedef struct ThreadedObjectUpdateState {
+       Scene *scene;
+       Scene *scene_parent;
+       SpinLock lock;
+
+       /* Execution statistics */
+       ListBase statistics[BLENDER_MAX_THREADS];
+       bool has_updated_objects;
+} ThreadedObjectUpdateState;
+
+static void scene_update_object_add_task(void *node, void *user_data);
+
+static void scene_update_all_bases(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)
-               scene_update_tagged_recursive(bmain, scene->set, scene_parent);
-       
-       /* scene objects */
        for (base = scene->base.first; base; base = base->next) {
-               Object *ob = base->object;
-               
-               BKE_object_handle_update_ex(scene_parent, ob, scene->rigidbody_world);
-               
-               if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP))
-                       BKE_group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
-                       
+               Object *object = base->object;
+
+               BKE_object_handle_update_ex(scene_parent, object, scene->rigidbody_world);
+
+               if (object->dup_group && (object->transflag & OB_DUPLIGROUP))
+                       BKE_group_handle_recalc_and_update(scene_parent, object, object->dup_group);
+
                /* always update layer, so that animating layers works (joshua july 2010) */
                /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes
                 * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */
                // base->lay = ob->lay;
        }
-       
+}
+
+static void scene_update_object_func(TaskPool *pool, void *taskdata, int threadid)
+{
+/* Disable print for now in favor of summary statistics at the end of update. */
+#define PRINT if (false) printf
+
+       ThreadedObjectUpdateState *state = (ThreadedObjectUpdateState *) BLI_task_pool_userdata(pool);
+       void *node = taskdata;
+       Object *object = DAG_threaded_update_get_node_object(node);
+       Scene *scene = state->scene;
+       Scene *scene_parent = state->scene_parent;
+
+       if (object) {
+               double start_time = 0.0;
+
+               PRINT("Thread %d: update object %s\n", threadid, object->id.name);
+
+               if (G.debug & G_DEBUG) {
+                       start_time = PIL_check_seconds_timer();
+
+                       if (object->recalc & OB_RECALC_ALL) {
+                               state->has_updated_objects = true;
+                       }
+               }
+
+               /* We only update object itself here, dupli-group will be updated
+                * separately from main thread because of we've got no idea about
+                * dependnecies inside the group.
+                */
+               BKE_object_handle_update_ex(scene_parent, object, scene->rigidbody_world);
+
+               /* Calculate statistics. */
+               if (G.debug & G_DEBUG) {
+                       StatisicsEntry *entry;
+
+                       entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics");
+                       entry->object = object;
+                       entry->time = PIL_check_seconds_timer() - start_time;
+
+                       BLI_addtail(&state->statistics[threadid], entry);
+               }
+       }
+       else {
+               PRINT("Threda %d: update node %s\n", threadid,
+                     DAG_threaded_update_get_node_name(node));
+       }
+
+       BLI_spin_lock(&state->lock);
+       /* Update will decrease child's valency and schedule child with zero valency. */
+       DAG_threaded_update_handle_node_updated(node,scene_update_object_add_task, pool);
+       BLI_spin_unlock(&state->lock);
+
+#undef PRINT
+}
+
+static void scene_update_object_add_task(void *node, void *user_data)
+{
+       TaskPool *task_pool = user_data;
+
+       BLI_task_pool_push(task_pool, scene_update_object_func, node, false, TASK_PRIORITY_LOW);
+}
+
+static void print_threads_statistics(ThreadedObjectUpdateState *state)
+{
+       int i, tot_thread;
+
+       if ((G.debug & G_DEBUG) == 0) {
+               return;
+       }
+
+       tot_thread = BLI_system_thread_count();
+
+       for (i = 0; i < tot_thread; i++) {
+               int total_objects = 0;
+               double total_time = 0.0;
+               StatisicsEntry *entry;
+
+               if (state->has_updated_objects) {
+                       /* Don't pollute output if no objects were updated. */
+                       for (entry = state->statistics[i].first;
+                            entry;
+                            entry = entry->next)
+                       {
+                               total_objects++;
+                               total_time += entry->time;
+                       }
+
+                       printf("Thread %d: total %d objects in %f sec.\n", i, total_objects, total_time);
+
+                       for (entry = state->statistics[i].first;
+                            entry;
+                            entry = entry->next)
+                       {
+                               printf("  %s in %f sec\n", entry->object->id.name + 2, entry->time);
+                       }
+               }
+
+               BLI_freelistN(&state->statistics[i]);
+       }
+}
+
+static void scene_update_objects(Scene *scene, Scene *scene_parent, bool use_threads)
+{
+       TaskScheduler *task_scheduler = BLI_task_scheduler_get();
+       TaskPool *task_pool;
+       ThreadedObjectUpdateState state;
+
+       if (use_threads == false) {
+               scene_update_all_bases(scene, scene_parent);
+               return;
+       }
+
+       /* Ensure malloc will go go fine from threads,
+        * this is needed because we could be in main thread here
+        * and malloc could be non-threda safe at this point because
+        * no other jobs are running.
+        */
+       BLI_begin_threaded_malloc();
+
+       state.scene = scene;
+       state.scene_parent = scene_parent;
+       memset(state.statistics, 0, sizeof(state.statistics));
+       state.has_updated_objects = false;
+       BLI_spin_init(&state.lock);
+
+       task_pool = BLI_task_pool_create(task_scheduler, &state);
+
+       /* Initialize run-time data in the graph needed for traversing it
+        * from multiple threads.
+        *
+        * This will mark DAG nodes as object/non-object and will calculate
+        * "valency" of nodes (which is how many non-updated parents node
+        * have, which helps a lot checking whether node could be scheduled
+        * already or not).
+        */
+       DAG_threaded_update_begin(scene);
+
+       /* Put all nodes which are already ready for schedule to the task pool.
+        * usually its just a Scene node.
+        *
+        * We do lock here so no tthreads will start updating nodes valency
+        * while we're still fillign the queue in. Otherwise it's possible
+        * to run into situations when the same task is adding twice to the
+        * queue due to non-safe nature of function below.
+        */
+       BLI_spin_lock(&state.lock);
+       DAG_threaded_update_foreach_ready_node(scene, scene_update_object_add_task, task_pool);
+       BLI_spin_unlock(&state.lock);
+
+       /* work and wait until tasks are done */
+       BLI_task_pool_work_and_wait(task_pool);
+
+       /* free */
+       BLI_task_pool_free(task_pool);
+
+       BLI_end_threaded_malloc();
+
+       BLI_spin_end(&state.lock);
+
+       if (G.debug & G_DEBUG) {
+               print_threads_statistics(&state);
+       }
+
+       /* XXX: Weak, very weak!
+        *
+        * We update dupligroups in single thread! :S
+        *
+        * This is because we've got absolutely no idea about dependencies
+        * inside the group and we only know order of objects in which we
+        * need to perform objects update.
+        *
+        * We even can not update different groups in different threads,
+        * because groups could share the objects and detecting whether
+        * object is updating in multiple threads is not so much easy.
+        *
+        * This is solvable with local group dependency graph or expanding
+        * current dependency graph to be aware of dependencies inside
+        * groups.
+        *
+        * P.S. Objects from the dup_group are very much likely in scene's
+        *      dependency graph and were alreayd updated in threaded tasks
+        *      scheduler already.
+        *
+        *      So objects from the dupli_groups are likely don't have
+        *      OB_RECALC_ALL flag here, but it seems they still do have
+        *      non-zero recalc flags, and here we make sure things are
+        *      100% by calling BKE_group_handle_recalc_and_update.
+        */
+       {
+               Base *base;
+               for (base = scene->base.first; base; base = base->next) {
+                       Object *object = base->object;
+
+                       if (object->dup_group && (object->transflag & OB_DUPLIGROUP))
+                               BKE_group_handle_recalc_and_update(scene_parent, object, object->dup_group);
+               }
+       }
+}
+
+static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent, bool use_threads)
+{
+       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)
+               scene_update_tagged_recursive(bmain, scene->set, scene_parent, use_threads);
+
+       /* scene objects */
+       scene_update_objects(scene, scene_parent, use_threads);
+
        /* scene drivers... */
        scene_update_drivers(bmain, scene);
 
@@ -1197,7 +1421,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen
 }
 
 /* this is called in main loop, doing tagged updates before redraw */
-void BKE_scene_update_tagged(Main *bmain, Scene *scene)
+void BKE_scene_update_tagged_ex(Main *bmain, Scene *scene, bool use_threads)
 {
        Scene *sce_iter;
        
@@ -1224,7 +1448,7 @@ void BKE_scene_update_tagged(Main *bmain, Scene *scene)
         *
         * in the future this should handle updates for all datablocks, not
         * only objects and scenes. - brecht */
-       scene_update_tagged_recursive(bmain, scene, scene);
+       scene_update_tagged_recursive(bmain, scene, scene, use_threads);
 
        /* extra call here to recalc scene animation (for sequencer) */
        {
@@ -1243,8 +1467,13 @@ void BKE_scene_update_tagged(Main *bmain, Scene *scene)
        DAG_ids_clear_recalc(bmain);
 }
 
+void BKE_scene_update_tagged(Main *bmain, Scene *scene)
+{
+       BKE_scene_update_tagged_ex(bmain, scene, true);
+}
+
 /* applies changes right away, does all sets too */
-void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
+void BKE_scene_update_for_newframe_ex(Main *bmain, Scene *sce, unsigned int lay, bool use_threads)
 {
        float ctime = BKE_scene_frame_get(sce);
        Scene *sce_iter;
@@ -1302,7 +1531,7 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
        scene_do_rb_simulation_recursive(sce, ctime);
 
        /* BKE_object_handle_update() on all objects, groups and sets */
-       scene_update_tagged_recursive(bmain, sce, sce);
+       scene_update_tagged_recursive(bmain, sce, sce, use_threads);
 
        scene_depsgraph_hack(sce, sce);
 
@@ -1316,6 +1545,11 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
        DAG_ids_clear_recalc(bmain);
 }
 
+void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
+{
+       BKE_scene_update_for_newframe_ex(bmain, sce, lay, true);
+}
+
 /* return default layer, also used to patch old files */
 SceneRenderLayer *BKE_scene_add_render_layer(Scene *sce, const char *name)
 {
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
new file mode 100644 (file)
index 0000000..f57d428
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_TASK_H__
+#define __BLI_TASK_H__ 
+
+/** \file BLI_task.h
+ *  \ingroup bli
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
+/* Task Scheduler
+ * 
+ * Central scheduler that holds running threads ready to execute tasks. A single
+ * queue holds the task from all pools.
+ *
+ * Init/exit must be called before/after any task pools are created/freed, and
+ * must be called from the main threads. All other scheduler and pool functions
+ * are thread-safe. */
+
+typedef struct TaskScheduler TaskScheduler;
+
+enum {
+       TASK_SCHEDULER_AUTO_THREADS = 0,
+       TASK_SCHEDULER_SINGLE_THREAD = 1
+};
+
+TaskScheduler *BLI_task_scheduler_create(int num_threads);
+void BLI_task_scheduler_free(TaskScheduler *scheduler);
+
+int BLI_task_scheduler_num_threads(TaskScheduler *scheduler);
+
+/* Task Pool
+ *
+ * Pool of tasks that will be executed by the central TaskScheduler. For each
+ * pool, we can wait for all tasks to be done, or cancel them before they are
+ * done.
+ *
+ * Running tasks may spawn new tasks.
+ *
+ * Pools may be nested, i.e. a thread running a task can create another task
+ * pool with smaller tasks. When other threads are busy they will continue
+ * working on their own tasks, if not they will join in, no new threads will
+ * be launched.
+ */
+
+typedef enum TaskPriority {
+       TASK_PRIORITY_LOW,
+       TASK_PRIORITY_HIGH
+} TaskPriority;
+
+typedef struct TaskPool TaskPool;
+typedef void (*TaskRunFunction)(TaskPool *pool, void *taskdata, int threadid);
+
+TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata);
+void BLI_task_pool_free(TaskPool *pool);
+
+void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run,
+       void *taskdata, bool free_taskdata, TaskPriority priority);
+
+/* work and wait until all tasks are done */
+void BLI_task_pool_work_and_wait(TaskPool *pool);
+/* cancel all tasks, keep worker threads running */
+void BLI_task_pool_cancel(TaskPool *pool);
+/* stop all worker threads */
+void BLI_task_pool_stop(TaskPool *pool);
+
+/* for worker threads, test if cancelled */
+bool BLI_task_pool_cancelled(TaskPool *pool);
+
+/* optional userdata pointer to pass along to run function */
+void *BLI_task_pool_userdata(TaskPool *pool);
+
+/* optional mutex to use from run function */
+ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool);
+
+/* number of tasks done, for stats, don't use this to make decisions */
+size_t BLI_task_pool_tasks_done(TaskPool *pool);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
index 154986936a29f5416f2ba95d73b759e932ed96e4..3e2e819a1e6d177c46c3427ead336485954f9ed8 100644 (file)
@@ -45,11 +45,15 @@ extern "C" {
 #define BLENDER_MAX_THREADS     64
 
 struct ListBase;
+struct TaskScheduler;
 
 /* Threading API */
 
 /*this is run once at startup*/
 void BLI_threadapi_init(void);
+void BLI_threadapi_exit(void);
+
+struct TaskScheduler *BLI_task_scheduler_get(void);
 
 void    BLI_init_threads(struct ListBase *threadbase, void *(*do_thread)(void *), int tot);
 int     BLI_available_threads(struct ListBase *threadbase);
@@ -100,6 +104,7 @@ ThreadMutex *BLI_mutex_alloc(void);
 void BLI_mutex_free(ThreadMutex *mutex);
 
 void BLI_mutex_lock(ThreadMutex *mutex);
+bool BLI_mutex_trylock(ThreadMutex *mutex);
 void BLI_mutex_unlock(ThreadMutex *mutex);
 
 /* Spin Lock */
@@ -182,6 +187,16 @@ int BLI_thread_queue_size(ThreadQueue *queue);
 void BLI_thread_queue_wait_finish(ThreadQueue *queue);
 void BLI_thread_queue_nowait(ThreadQueue *queue);
 
+/* Condition */
+
+typedef pthread_cond_t ThreadCondition;
+
+void BLI_condition_init(ThreadCondition *cond);
+void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex);
+void BLI_condition_notify_one(ThreadCondition *cond);
+void BLI_condition_notify_all(ThreadCondition *cond);
+void BLI_condition_end(ThreadCondition *cond);
+
 #ifdef __cplusplus
 }
 #endif
index b6b69116e67778b21880bcb10a5acebbb262151b..f5d6af107a51f6d996508755d14418a416ce83b5 100644 (file)
@@ -91,6 +91,7 @@ set(SRC
        intern/string.c
        intern/string_cursor_utf8.c
        intern/string_utf8.c
+       intern/task.c
        intern/threads.c
        intern/time.c
        intern/uvproject.c
@@ -151,6 +152,7 @@ set(SRC
        BLI_string_cursor_utf8.h
        BLI_string_utf8.h
        BLI_sys_types.h
+       BLI_task.h
        BLI_threads.h
        BLI_utildefines.h
        BLI_uvproject.h
index c3e7e8486d91359dfcf10a1495e48d8c7f433bfe..3983b5099ff98b2bbb6d90eee30266821dad6171 100644 (file)
@@ -87,6 +87,26 @@ void    PIL_sleep_ms(int ms);
                TIMEIT_END(id);                                                       \
        } (void)0
 
+#define TIMEIT_BLOCK_INIT(what) \
+       double _timeit_var_##what = 0; \
+       (void) 0
+
+#define TIMEIT_BLOCK_BEGIN(what) \
+       { \
+               double _timeit_block_start_##what = PIL_check_seconds_timer();  \
+               { (void)0
+
+#define TIMEIT_BLOCK_END(what) \
+               } \
+               _timeit_var_##what += PIL_check_seconds_timer() - _timeit_block_start_##what; \
+       } (void)0
+
+#define TIMEIT_BLOCK_STATS(what) \
+       { \
+               printf("%s time (in seconds): %f\n", #what, _timeit_var_##what); \
+               fflush(stdout); \
+       } (void)0
+
 #ifdef __cplusplus
 }
 #endif
index bb326a23d590ae39c3d736e600b5988623ee9dbf..ea63dd81ab217acccc32a13d6cd2f40e1f1c99ed 100644 (file)
@@ -258,6 +258,22 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr)
 {
        BLI_freenode *newhead = addr;
 
+#ifndef NDEBUG
+       {
+               BLI_mempool_chunk *chunk;
+               bool found = false;
+               for (chunk = pool->chunks.first; chunk; chunk = chunk->next) {
+                       if ((char*)addr >= (char*)chunk->data && (char*)addr < (char*)chunk->data + pool->csize) {
+                               found = true;
+                               break;
+                       }
+               }
+               if (!found) {
+                       BLI_assert(!"Attempt to free data which is not in pool.\n");
+               }
+       }
+#endif
+
        if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
 #ifndef NDEBUG
                /* this will detect double free's */
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
new file mode 100644 (file)
index 0000000..5d0b5ff
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_task.h"
+#include "BLI_threads.h"
+
+/* Types */
+
+typedef struct Task {
+       struct Task *next, *prev;
+
+       TaskRunFunction run;
+       void *taskdata;
+       bool free_taskdata;
+       TaskPool *pool;
+} Task;
+
+struct TaskPool {
+       TaskScheduler *scheduler;
+
+       volatile size_t num;
+       volatile size_t done;
+       ThreadMutex num_mutex;
+       ThreadCondition num_cond;
+
+       void *userdata;
+       ThreadMutex user_mutex;
+
+       volatile bool do_cancel;
+};
+
+struct TaskScheduler {
+       pthread_t *threads;
+       struct TaskThread *task_threads;
+       int num_threads;
+
+       ListBase queue;
+       ThreadMutex queue_mutex;
+       ThreadCondition queue_cond;
+
+       volatile bool do_exit;
+};
+
+typedef struct TaskThread {
+       TaskScheduler *scheduler;
+       int id;
+} TaskThread;
+
+/* Task Scheduler */
+
+static void task_pool_num_decrease(TaskPool *pool, size_t done)
+{
+       BLI_mutex_lock(&pool->num_mutex);
+
+       BLI_assert(pool->num >= done);
+
+       pool->num -= done;
+       pool->done += done;
+
+       if (pool->num == 0)
+               BLI_condition_notify_all(&pool->num_cond);
+
+       BLI_mutex_unlock(&pool->num_mutex);
+}
+
+static void task_pool_num_increase(TaskPool *pool)
+{
+       BLI_mutex_lock(&pool->num_mutex);
+
+       pool->num++;
+       BLI_condition_notify_all(&pool->num_cond);
+
+       BLI_mutex_unlock(&pool->num_mutex);
+}
+
+static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task)
+{
+       BLI_mutex_lock(&scheduler->queue_mutex);
+
+       while (!scheduler->queue.first && !scheduler->do_exit)
+               BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex);
+
+       if (!scheduler->queue.first) {
+               BLI_mutex_unlock(&scheduler->queue_mutex);
+               BLI_assert(scheduler->do_exit);
+               return false;
+       }
+       
+       *task = scheduler->queue.first;
+       BLI_remlink(&scheduler->queue, *task);
+
+       BLI_mutex_unlock(&scheduler->queue_mutex);
+
+       return true;
+}
+
+static void *task_scheduler_thread_run(void *thread_p)
+{
+       TaskThread *thread = (TaskThread *) thread_p;
+       TaskScheduler *scheduler = thread->scheduler;
+       int thread_id = thread->id;
+       Task *task;
+
+       /* keep popping off tasks */
+       while (task_scheduler_thread_wait_pop(scheduler, &task)) {
+               TaskPool *pool = task->pool;
+
+               /* run task */
+               task->run(pool, task->taskdata, thread_id);
+
+               /* delete task */
+               if (task->free_taskdata)
+                       MEM_freeN(task->taskdata);
+               MEM_freeN(task);
+
+               /* notify pool task was done */
+               task_pool_num_decrease(pool, 1);
+       }
+
+       return NULL;
+}
+
+TaskScheduler *BLI_task_scheduler_create(int num_threads)
+{
+       TaskScheduler *scheduler = MEM_callocN(sizeof(TaskScheduler), "TaskScheduler");
+
+       /* multiple places can use this task scheduler, sharing the same
+        * threads, so we keep track of the number of users. */
+       scheduler->do_exit = false;
+
+       scheduler->queue.first = scheduler->queue.last = NULL;
+       BLI_mutex_init(&scheduler->queue_mutex);
+       BLI_condition_init(&scheduler->queue_cond);
+
+       if (num_threads == 0) {
+               /* automatic number of threads will be main thread + num cores */
+               num_threads = BLI_system_thread_count();
+       }
+
+       /* main thread will also work, so we count it too */
+       num_threads -= 1;
+
+       /* launch threads that will be waiting for work */
+       if (num_threads > 0) {
+               int i;
+
+               scheduler->num_threads = num_threads;
+               scheduler->threads = MEM_callocN(sizeof(pthread_t) * num_threads, "TaskScheduler threads");
+               scheduler->task_threads = MEM_callocN(sizeof(TaskThread) * num_threads, "TaskScheduler task threads");
+
+               for (i = 0; i < num_threads; i++) {
+                       TaskThread *thread = &scheduler->task_threads[i];
+                       thread->scheduler = scheduler;
+                       thread->id = i + 1;
+
+                       if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) {
+                               fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads);
+                               MEM_freeN(thread);
+                       }
+               }
+       }
+       
+       return scheduler;
+}
+
+void BLI_task_scheduler_free(TaskScheduler *scheduler)
+{
+       Task *task;
+
+       /* stop all waiting threads */
+       BLI_mutex_lock(&scheduler->queue_mutex);
+       scheduler->do_exit = true;
+       BLI_condition_notify_all(&scheduler->queue_cond);
+       BLI_mutex_unlock(&scheduler->queue_mutex);
+
+       /* delete threads */
+       if (scheduler->threads) {
+               int i;
+
+               for (i = 0; i < scheduler->num_threads; i++) {
+                       if (pthread_join(scheduler->threads[i], NULL) != 0)
+                               fprintf(stderr, "TaskScheduler failed to join thread %d/%d\n", i, scheduler->num_threads);
+               }
+
+               MEM_freeN(scheduler->threads);
+       }
+
+       /* Delete task thread data */
+       if (scheduler->task_threads) {
+               MEM_freeN(scheduler->task_threads);
+       }
+
+       /* delete leftover tasks */
+       for (task = scheduler->queue.first; task; task = task->next) {
+               if (task->free_taskdata)
+                       MEM_freeN(task->taskdata);
+       }
+       BLI_freelistN(&scheduler->queue);
+
+       /* delete mutex/condition */
+       BLI_mutex_end(&scheduler->queue_mutex);
+       BLI_condition_end(&scheduler->queue_cond);
+
+       MEM_freeN(scheduler);
+}
+
+int BLI_task_scheduler_num_threads(TaskScheduler *scheduler)
+{
+       return scheduler->num_threads + 1;
+}
+
+static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriority priority)
+{
+       task_pool_num_increase(task->pool);
+
+       /* add task to queue */
+       BLI_mutex_lock(&scheduler->queue_mutex);
+
+       if (priority == TASK_PRIORITY_HIGH)
+               BLI_addhead(&scheduler->queue, task);
+       else
+               BLI_addtail(&scheduler->queue, task);
+
+       BLI_condition_notify_one(&scheduler->queue_cond);
+       BLI_mutex_unlock(&scheduler->queue_mutex);
+}
+
+static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool)
+{
+       Task *task, *nexttask;
+       size_t done = 0;
+
+       BLI_mutex_lock(&scheduler->queue_mutex);
+
+       /* free all tasks from this pool from the queue */
+       for (task = scheduler->queue.first; task; task = nexttask) {
+               nexttask = task->next;
+
+               if (task->pool == pool) {
+                       if (task->free_taskdata)
+                               MEM_freeN(task->taskdata);
+                       BLI_freelinkN(&scheduler->queue, task);
+
+                       done++;
+               }
+       }
+
+       BLI_mutex_unlock(&scheduler->queue_mutex);
+
+       /* notify done */
+       task_pool_num_decrease(pool, done);
+}
+
+/* Task Pool */
+
+TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata)
+{
+       TaskPool *pool = MEM_callocN(sizeof(TaskPool), "TaskPool");
+
+       pool->scheduler = scheduler;
+       pool->num = 0;
+       pool->do_cancel = false;
+
+       BLI_mutex_init(&pool->num_mutex);
+       BLI_condition_init(&pool->num_cond);
+
+       pool->userdata = userdata;
+       BLI_mutex_init(&pool->user_mutex);
+
+       return pool;
+}
+
+void BLI_task_pool_free(TaskPool *pool)
+{
+       BLI_task_pool_stop(pool);
+
+       BLI_mutex_end(&pool->num_mutex);
+       BLI_condition_end(&pool->num_cond);
+
+       BLI_mutex_end(&pool->user_mutex);
+
+       MEM_freeN(pool);
+}
+
+void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run,
+       void *taskdata, bool free_taskdata, TaskPriority priority)
+{
+       Task *task = MEM_callocN(sizeof(Task), "Task");
+
+       task->run = run;
+       task->taskdata = taskdata;
+       task->free_taskdata = free_taskdata;
+       task->pool = pool;
+
+       task_scheduler_push(pool->scheduler, task, priority);
+}
+
+void BLI_task_pool_work_and_wait(TaskPool *pool)
+{
+       TaskScheduler *scheduler = pool->scheduler;
+
+       BLI_mutex_lock(&pool->num_mutex);
+
+       while (pool->num != 0) {
+               Task *task, *work_task = NULL;
+               bool found_task = false;
+
+               BLI_mutex_unlock(&pool->num_mutex);
+
+               BLI_mutex_lock(&scheduler->queue_mutex);
+
+               /* find task from this pool. if we get a task from another pool,
+                * we can get into deadlock */
+
+               for (task = scheduler->queue.first; task; task = task->next) {
+                       if (task->pool == pool) {
+                               work_task = task;
+                               found_task = true;
+                               BLI_remlink(&scheduler->queue, task);
+                               break;
+                       }
+               }
+
+               BLI_mutex_unlock(&scheduler->queue_mutex);
+
+               /* if found task, do it, otherwise wait until other tasks are done */
+               if (found_task) {
+                       /* run task */
+                       work_task->run(pool, work_task->taskdata, 0);
+
+                       /* delete task */
+                       if (work_task->free_taskdata)
+                               MEM_freeN(work_task->taskdata);
+                       MEM_freeN(work_task);
+
+                       /* notify pool task was done */
+                       task_pool_num_decrease(pool, 1);
+               }
+
+               BLI_mutex_lock(&pool->num_mutex);
+               if (pool->num == 0)
+                       break;
+
+               if (!found_task)
+                       BLI_condition_wait(&pool->num_cond, &pool->num_mutex);
+       }
+
+       BLI_mutex_unlock(&pool->num_mutex);
+}
+
+void BLI_task_pool_cancel(TaskPool *pool)
+{
+       pool->do_cancel = true;
+
+       task_scheduler_clear(pool->scheduler, pool);
+
+       /* wait until all entries are cleared */
+       BLI_mutex_lock(&pool->num_mutex);
+       while (pool->num)
+               BLI_condition_wait(&pool->num_cond, &pool->num_mutex);
+       BLI_mutex_unlock(&pool->num_mutex);
+
+       pool->do_cancel = false;
+}
+
+void BLI_task_pool_stop(TaskPool *pool)
+{
+       task_scheduler_clear(pool->scheduler, pool);
+
+       BLI_assert(pool->num == 0);
+}
+
+bool BLI_task_pool_cancelled(TaskPool *pool)
+{
+       return pool->do_cancel;
+}
+
+void *BLI_task_pool_userdata(TaskPool *pool)
+{
+       return pool->userdata;
+}
+
+ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool)
+{
+       return &pool->user_mutex;
+}
+
+size_t BLI_task_pool_tasks_done(TaskPool *pool)
+{
+       return pool->done;
+}
+
index 2b6fb52c49c296f9debda3c421d271669383870d..ab4516dd2b5606a5ba9e3bb12d3a14b08a667174 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "BLI_listbase.h"
 #include "BLI_gsqueue.h"
+#include "BLI_task.h"
 #include "BLI_threads.h"
 
 #include "PIL_time.h"
@@ -63,6 +64,9 @@ extern pthread_key_t gomp_tls_key;
 static void *thread_tls_data;
 #endif
 
+/* We're using one global task scheduler for all kind of tasks. */
+static TaskScheduler *task_scheduler = NULL;
+
 /* ********** basic thread control API ************ 
  * 
  * Many thread cases have an X amount of jobs, and only an Y amount of
@@ -147,6 +151,25 @@ void BLI_threadapi_init(void)
        mainid = pthread_self();
 }
 
+void BLI_threadapi_exit(void)
+{
+       BLI_task_scheduler_free(task_scheduler);
+}
+
+TaskScheduler *BLI_task_scheduler_get(void)
+{
+       if (task_scheduler == NULL) {
+               int tot_thread = BLI_system_thread_count();
+
+               /* Do a lazy initialization, so it happes after
+                * command line arguments parsing
+                */
+               task_scheduler = BLI_task_scheduler_create(tot_thread);
+       }
+
+       return task_scheduler;
+}
+
 /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c)
  * problem otherwise: scene render will kill of the mutex!
  */
@@ -412,6 +435,11 @@ void BLI_mutex_unlock(ThreadMutex *mutex)
        pthread_mutex_unlock(mutex);
 }
 
+bool BLI_mutex_trylock(ThreadMutex *mutex)
+{
+       return (pthread_mutex_trylock(mutex) == 0);
+}
+
 void BLI_mutex_end(ThreadMutex *mutex)
 {
        pthread_mutex_destroy(mutex);
@@ -818,6 +846,32 @@ void BLI_thread_queue_wait_finish(ThreadQueue *queue)
        pthread_mutex_unlock(&queue->mutex);
 }
 
+/* Condition */
+void BLI_condition_init(ThreadCondition *cond)
+{
+       pthread_cond_init(cond, NULL);
+}
+
+void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
+{
+       pthread_cond_wait(cond, mutex);
+}
+
+void BLI_condition_notify_one(ThreadCondition *cond)
+{
+       pthread_cond_signal(cond);
+}
+
+void BLI_condition_notify_all(ThreadCondition *cond)
+{
+       pthread_cond_broadcast(cond);
+}
+
+void BLI_condition_end(ThreadCondition *cond)
+{
+       pthread_cond_destroy(cond);
+}
+
 /* ************************************************ */
 
 void BLI_begin_threaded_malloc(void)
@@ -840,4 +894,3 @@ void BLI_end_threaded_malloc(void)
        if (thread_levels == 0)
                MEM_set_lock_callback(NULL, NULL);
 }
-
index 1f8bbfbec8894fec25360e81b20fb698d8e48f8a..2c642403c077827891442fa5c264cccabe817ca1 100644 (file)
@@ -3123,7 +3123,6 @@ static void direct_link_mball(FileData *fd, MetaBall *mb)
        
        mb->disp.first = mb->disp.last = NULL;
        mb->editelems = NULL;
-       mb->bb = NULL;
 /*     mb->edit_elems.first= mb->edit_elems.last= NULL;*/
        mb->lastelem = NULL;
 }
@@ -3399,11 +3398,8 @@ static void direct_link_curve(FileData *fd, Curve *cu)
                if (cu->wordspace == 0.0f) cu->wordspace = 1.0f;
        }
 
-       cu->bev.first = cu->bev.last = NULL;
-       cu->disp.first = cu->disp.last = NULL;
        cu->editnurb = NULL;
        cu->lastsel = NULL;
-       cu->path = NULL;
        cu->editfont = NULL;
        
        for (nu = cu->nurb.first; nu; nu = nu->next) {
@@ -4829,8 +4825,6 @@ static void direct_link_object(FileData *fd, Object *ob)
                ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT);
        }
        
-       ob->disp.first = ob->disp.last = NULL;
-       
        ob->adt = newdataadr(fd, ob->adt);
        direct_link_animdata(fd, ob->adt);
        
@@ -5025,6 +5019,9 @@ static void direct_link_object(FileData *fd, Object *ob)
        ob->gpulamp.first= ob->gpulamp.last = NULL;
        link_list(fd, &ob->pc_ids);
 
+       /* Runtime curve data  */
+       ob->curve_cache = NULL;
+
        /* in case this value changes in future, clamp else we get undefined behavior */
        CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
 
@@ -5527,6 +5524,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
        wm->winactive = NULL;
        wm->initialized = 0;
        wm->op_undo_depth = 0;
+       wm->is_interface_locked = 0;
 }
 
 static void lib_link_windowmanager(FileData *fd, Main *main)
index 22bd22c8561c4317759cbd15b210e7b002d02cc8..0301db4b4cfe9a94454fb8c2fc929d1c4c5050c2 100644 (file)
@@ -255,7 +255,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
        bDeformGroup *dgroup;
        bPoseChannel *pchan;
        Mesh *mesh;
-       Mat4 *bbone = NULL;
+       Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
        float (*root)[3], (*tip)[3], (*verts)[3];
        int *selected;
        int numbones, vertsfilled = 0, i, j, segments = 0;
@@ -309,7 +309,8 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
                                if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
                                        if (bone->segments > 1) {
                                                segments = bone->segments;
-                                               bbone = b_bone_spline_setup(pchan, 1);
+                                               b_bone_spline_setup(pchan, 1, bbone_array);
+                                               bbone = bbone_array;
                                        }
                                }
                        }
index d197697e60b5f027c7f1fcc479c4bb34facd81e8..bee31be0de29e2c03961c94bc12c888746e459e0 100644 (file)
@@ -126,5 +126,7 @@ void CURVE_OT_vertex_add(struct wmOperatorType *ot);
 void CURVE_OT_extrude(struct wmOperatorType *ot);
 void CURVE_OT_cyclic_toggle(struct wmOperatorType *ot);
 
+void CURVE_OT_match_texture_space(struct wmOperatorType *ot);
+
 #endif /* ED_UTIL_INTERN_H */
 
index 2452a5d1a4bb6b7d5321a21467d3ff36d8f9695f..217ec57297ffe700f64aee942837163d722a0e48 100644 (file)
@@ -136,6 +136,8 @@ void ED_operatortypes_curve(void)
        WM_operatortype_append(CURVE_OT_vertex_add);
        WM_operatortype_append(CURVE_OT_extrude);
        WM_operatortype_append(CURVE_OT_cyclic_toggle);
+
+       WM_operatortype_append(CURVE_OT_match_texture_space);
 }
 
 void ED_operatormacros_curve(void)
index 660f8098a38fae73876dfc9a0a89da09f9f6baf1..6d573c5e13c190d0c3d33bdcf4655e05b65dace0 100644 (file)
@@ -59,6 +59,7 @@
 #include "BKE_context.h"
 #include "BKE_curve.h"
 #include "BKE_depsgraph.h"
+#include "BKE_displist.h"
 #include "BKE_fcurve.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
@@ -7178,3 +7179,65 @@ int ED_curve_actSelection(Curve *cu, float center[3])
 
        return 1;
 }
+
+/******************** Match texture space operator ***********************/
+
+static int match_texture_space_poll(bContext *C)
+{
+       Object *object = CTX_data_active_object(C);
+
+       return object && ELEM3(object->type, OB_CURVE, OB_SURF, OB_FONT);
+}
+
+static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *object = CTX_data_active_object(C);
+       Curve *curve = (Curve *) object->data;
+       float min[3], max[3], size[3], loc[3];
+       int a;
+
+       if (ELEM(NULL, object->curve_cache, object->curve_cache->disp.first)) {
+               BKE_displist_make_curveTypes(scene, object, FALSE);
+       }
+
+       INIT_MINMAX(min, max);
+       BKE_displist_minmax(&object->curve_cache->disp, min, max);
+
+       mid_v3_v3v3(loc, min, max);
+
+       size[0] = (max[0] - min[0]) / 2.0f;
+       size[1] = (max[1] - min[1]) / 2.0f;
+       size[2] = (max[2] - min[2]) / 2.0f;
+
+       for (a = 0; a < 3; a++) {
+               if (size[a] == 0.0f) size[a] = 1.0f;
+               else if (size[a] > 0.0f && size[a] < 0.00001f) size[a] = 0.00001f;
+               else if (size[a] < 0.0f && size[a] > -0.00001f) size[a] = -0.00001f;
+       }
+
+       copy_v3_v3(curve->loc, loc);
+       copy_v3_v3(curve->size, size);
+       zero_v3(curve->rot);
+
+       curve->texflag &= ~CU_AUTOSPACE;
+
+       WM_event_add_notifier(C, NC_GEOM | ND_DATA, curve);
+
+       return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_match_texture_space(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Match Texture Space";
+       ot->idname = "CURVE_OT_match_texture_space";
+       ot->description = "Match texture space to object's bounding box";
+
+       /* api callbacks */
+       ot->exec = match_texture_space_exec;
+       ot->poll = match_texture_space_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
index 61cc021800e0d1d3c19fb8ced6123be7c51cd6fd..3e82e8da40e7f4fb04611ffa0166f049b918a720 100644 (file)
@@ -1,4 +1,5 @@
 /*
+
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -1017,6 +1018,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
        Scene *scene = CTX_data_scene(C);
        Object *ob;
        ModifierData *md, *vmd;
+       VirtualModifierData virtualModifierData;
        int i, lastCageIndex, cageIndex;
 
        /* verify we have valid data */
@@ -1039,7 +1041,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
        cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
 
        /* XXX virtual modifiers are not accesible for python */
-       vmd = modifiers_getVirtualModifierList(ob);
+       vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        for (i = 0; vmd; i++, vmd = vmd->next) {
                if (md == vmd)
index d012a8ac656d4447d1721e3c40c040c8fb9192bf..4ae48b99bb8d487922174de154f53f5c66f9a7db 100644 (file)
@@ -178,7 +178,6 @@ int join_mesh_exec(bContext *C, wmOperator *op)
                        if (kb->data) MEM_freeN(kb->data);
                        kb->data = MEM_callocN(sizeof(float) * 3 * totvert, "join_shapekey");
                        kb->totelem = totvert;
-                       kb->weights = NULL;
                }
        }
        else if (haskey) {
index ce61b4fce502f4c3accf9dfcd475a10db32a304f..b907cba33e2ef4e566411b95d9444bc887ff7b8e 100644 (file)
@@ -1243,7 +1243,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
 
                ob->parent = NULL;
                ob->constraints.first = ob->constraints.last = NULL;
-               ob->disp.first = ob->disp.last = NULL;
+               ob->curve_cache = NULL;
                ob->transflag &= ~OB_DUPLI;
                ob->lay = base->lay;
 
@@ -1385,7 +1385,7 @@ static EnumPropertyItem convert_target_items[] = {
 
 static void curvetomesh(Scene *scene, Object *ob) 
 {
-       if (ob->disp.first == NULL)
+       if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first))
                BKE_displist_make_curveTypes(scene, ob, 0);  /* force creation */
 
        BKE_mesh_from_nurbs(ob); /* also does users */
@@ -1553,7 +1553,7 @@ static int convert_exec(bContext *C, wmOperator *op)
 
                        cu = newob->data;
 
-                       if (!newob->disp.first)
+                       if ( !newob->curve_cache || !newob->curve_cache->disp.first)
                                BKE_displist_make_curveTypes(scene, newob, 0);
 
                        newob->type = OB_CURVE;
@@ -1595,7 +1595,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                curvetomesh(scene, newob);
 
                                /* meshes doesn't use displist */
-                               BKE_displist_free(&newob->disp);
+                               BKE_object_free_curve_cache(newob);
                        }
                }
                else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
@@ -1616,7 +1616,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                        newob = ob;
 
                                        /* meshes doesn't use displist */
-                                       BKE_displist_free(&newob->disp);
+                                       BKE_object_free_curve_cache(newob);
                                }
 
                                curvetomesh(scene, newob);
@@ -1635,7 +1635,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                ob->flag |= OB_DONE;
                        }
 
-                       if (!baseob->disp.first) {
+                       if (!baseob->curve_cache || !baseob->curve_cache->disp.first) {
                                BKE_displist_make_mball(scene, baseob);
                        }
 
@@ -1658,7 +1658,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                        for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]);
                                }
 
-                               BKE_mesh_from_metaball(&baseob->disp, newob->data);
+                               BKE_mesh_from_metaball(&baseob->curve_cache->disp, newob->data);
 
                                if (obact->type == OB_MBALL) {
                                        basact = basen;
index 7f7a0777bbf80354dc07b0f11c4e1b5ce08b2ec6..47e13f0293419aca2908096f5c7b9e34e5aff634 100644 (file)
@@ -1417,8 +1417,9 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
                                                                        space = size[0] / size[1];
                                                                }
                                                                else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
-                                                                       Curve *cu = ob->data;
-                                                                       space = cu->size[0] / cu->size[1];
+                                                                       float size[3];
+                                                                       BKE_curve_texspace_get(ob->data, NULL, NULL, size);
+                                                                       space = size[0] / size[1];
                                                                }
                                                        
                                                                x = ibuf->x / space;
index 03d51fcbe82dd3a18893bb1ed62909633aca7fe1..0ba84e274201210457b30c2021cf357930e1d233 100644 (file)
@@ -637,9 +637,9 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob,
                cu = ob->data;
                BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
 
-               vertexCos = BKE_curve_vertexCos_get(cu, &cu->nurb, &numVerts);
+               vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts);
                mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0);
-               BK_curve_vertexCos_apply(cu, &cu->nurb, vertexCos);
+               BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos);
 
                MEM_freeN(vertexCos);
 
index 3a6bd05df0bd1eacd3e5bc0f8323cd01c0633e27..4b081d41ef3d9193940aee683d853920d231051d 100644 (file)
@@ -274,6 +274,7 @@ typedef struct RenderJob {
        short *do_update;
        float *progress;
        ReportList *reports;
+       bool interface_locked;
 } RenderJob;
 
 static void render_freejob(void *rjv)
@@ -501,6 +502,15 @@ static void render_endjob(void *rjv)
 
                BKE_image_release_ibuf(ima, ibuf, lock);
        }
+
+       /* Finally unlock the user interface (if it was locked). */
+       if (rj->interface_locked) {
+               /* Interface was locked, so window manager couldn't have been changed
+                * and using one from Global will unlock exactly the same manager as
+                * was locked before running the job.
+                */
+               WM_set_locked_interface(G.main->wm.first, false);
+       }
 }
 
 /* called by render, check job 'stop' value or the global */
@@ -526,10 +536,14 @@ static int render_break(void *UNUSED(rjv))
 
 /* runs in thread, no cursor setting here works. careful with notifiers too (malloc conflicts) */
 /* maybe need a way to get job send notifer? */
-static void render_drawlock(void *UNUSED(rjv), int lock)
+static void render_drawlock(void *rjv, int lock)
 {
-       BKE_spacedata_draw_locks(lock);
-       
+       RenderJob *rj = rjv;
+
+       /* If interface is locked, renderer callback shall do nothing. */
+       if (!rj->interface_locked) {
+               BKE_spacedata_draw_locks(lock);
+       }
 }
 
 /* catch esc */
@@ -657,6 +671,23 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
                        rj->lay |= v3d->localvd->lay;
        }
 
+       /* Lock the user interface depending on render settings. */
+       if (scene->r.use_lock_interface) {
+               WM_set_locked_interface(CTX_wm_manager(C), true);
+
+               /* Set flag interface need to be unlocked.
+                *
+                * This is so because we don't have copy of render settings
+                * accessible from render job and copy is needed in case
+                * of non-locked rendering, so we wouldn't try to unlock
+                * anything if option was initially unset but then was
+                * enabled during rendering.
+                */
+               rj->interface_locked = true;
+
+               /* TODO(sergey): clean memory used by viewport? */
+       }
+
        /* setup job */
        if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render";
        else name = "Render";
index 2edd00c015d2b339ae0460b50c8fe3ad16ec57ba..1ecd33b68772f839421bb374d29ac72d6bcc50f2 100644 (file)
@@ -150,6 +150,7 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
 {
        Mesh *me = (Mesh *)ob->data;
        ModifierData *md;
+       VirtualModifierData virtualModifierData;
 
        if (ob->sculpt && ob->sculpt->bm) {
                /* can't combine multires and dynamic topology */
@@ -161,7 +162,7 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
                return NULL;
        }
 
-       for (md = modifiers_getVirtualModifierList(ob); md; md = md->next) {
+       for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next) {
                if (md->type == eModifierType_Multires) {
                        MultiresModifierData *mmd = (MultiresModifierData *)md;
 
@@ -180,8 +181,9 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
 static int sculpt_has_active_modifiers(Scene *scene, Object *ob)
 {
        ModifierData *md;
+       VirtualModifierData virtualModifierData;
 
-       md = modifiers_getVirtualModifierList(ob);
+       md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        /* exception for shape keys because we can edit those */
        for (; md; md = md->next) {
@@ -198,6 +200,7 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
        ModifierData *md;
        Mesh *me = (Mesh *)ob->data;
        MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
+       VirtualModifierData virtualModifierData;
 
        if (mmd || ob->sculpt->bm)
                return 0;
@@ -206,7 +209,7 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
        if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr)
                return 1;
 
-       md = modifiers_getVirtualModifierList(ob);
+       md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        /* exception for shape keys because we can edit those */
        for (; md; md = md->next) {
index 2da3f3adb67ead60332ee3a2890703ca01c13f8f..a32ab4c56578593d8321f15d7dc723247ff18f46 100644 (file)
@@ -360,7 +360,7 @@ void IMAGE_OT_view_pan(wmOperatorType *ot)
        ot->poll = space_image_main_area_poll;
 
        /* flags */
-       ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+       ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_ALLOW_LOCKED;
        
        /* properties */
        RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
@@ -575,7 +575,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
        ot->poll = space_image_main_area_poll;
 
        /* flags */
-       ot->flag = OPTYPE_BLOCKING;
+       ot->flag = OPTYPE_BLOCKING | OPTYPE_ALLOW_LOCKED;
        
        /* properties */
        RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX,
@@ -638,6 +638,9 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot)
        
        /* api callbacks */
        ot->invoke = image_view_ndof_invoke;
+
+       /* flags */
+       ot->flag = OPTYPE_ALLOW_LOCKED;
 }
 
 /********************** view all operator *********************/
@@ -693,6 +696,9 @@ void IMAGE_OT_view_all(wmOperatorType *ot)
        /* api callbacks */
        ot->exec = image_view_all_exec;
        ot->poll = space_image_main_area_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_GRAB_POINTER;
 }
 
 /********************** view selected operator *********************/
@@ -755,6 +761,9 @@ void IMAGE_OT_view_selected(wmOperatorType *ot)
        /* api callbacks */
        ot->exec = image_view_selected_exec;
        ot->poll = image_view_selected_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_GRAB_POINTER;
 }
 
 /********************** view zoom in/out operator *********************/
@@ -797,6 +806,9 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
        ot->exec = image_view_zoom_in_exec;
        ot->poll = space_image_main_area_poll;
 
+       /* flags */
+       ot->flag = OPTYPE_ALLOW_LOCKED;
+
        /* properties */
        RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
 }
@@ -839,6 +851,9 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
        ot->exec = image_view_zoom_out_exec;
        ot->poll = space_image_main_area_poll;
 
+       /* flags */
+       ot->flag = OPTYPE_ALLOW_LOCKED;
+
        /* properties */
        RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
 }
@@ -880,7 +895,10 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
        /* api callbacks */
        ot->exec = image_view_zoom_ratio_exec;
        ot->poll = space_image_main_area_poll;
-       
+
+       /* flags */
+       ot->flag = OPTYPE_ALLOW_LOCKED;
+
        /* properties */
        RNA_def_float(ot->srna, "ratio", 0.0f, -FLT_MAX, FLT_MAX,
                      "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX);
index 98c9c8d15fe3a2a459bec6dea1b5cd8b3836ff16..c1cddf092aa0429a577f3b3119a70c748667414d 100644 (file)
@@ -115,8 +115,8 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
                {
                        int totv = 0, totf = 0, tottri = 0;
 
-                       if (ob->disp.first)
-                               BKE_displist_count(&ob->disp, &totv, &totf, &tottri);
+                       if (ob->curve_cache && ob->curve_cache->disp.first)
+                               BKE_displist_count(&ob->curve_cache->disp, &totv, &totf, &tottri);
 
                        totv   *= totob;
                        totf   *= totob;
index d3d8868520d36b14a888fc74bf3b21ed98c8cf08..05a280ae762ef1ec8705c9afd53fd5e0dd2916d7 100644 (file)
@@ -34,6 +34,7 @@
 #include <string.h>
 #include <math.h>
 
+#include "MEM_guardedalloc.h"
 
 #include "DNA_anim_types.h"
 #include "DNA_armature_types.h"
@@ -1099,12 +1100,14 @@ static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, float xwidth,
        
        if ((segments > 1) && (pchan)) {
                float dlen = length / (float)segments;
-               Mat4 *bbone = b_bone_spline_setup(pchan, 0);
+               Mat4 bbone[MAX_BBONE_SUBDIV];
                int a;
-               
-               for (a = 0; a < segments; a++, bbone++) {
+
+               b_bone_spline_setup(pchan, 0, bbone);
+
+               for (a = 0; a < segments; a++) {
                        glPushMatrix();
-                       glMultMatrixf(bbone->mat);
+                       glMultMatrixf(bbone[a].mat);
                        if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
                        else drawcube_size(xwidth, dlen, zwidth);
                        glPopMatrix();
@@ -1235,6 +1238,7 @@ static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float len
 static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
                            bPoseChannel *pchan, EditBone *ebone)
 {
+       Mat4 bbones_array[MAX_BBONE_SUBDIV];
        Mat4 *bbones = NULL;
        int segments = 0;
        float length;
@@ -1243,8 +1247,10 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
                segments = pchan->bone->segments;
                length = pchan->bone->length;
                
-               if (segments > 1)
-                       bbones = b_bone_spline_setup(pchan, 0);
+               if (segments > 1) {
+                       b_bone_spline_setup(pchan, 0, bbones_array);
+                       bbones = bbones_array;
+               }
        }
        else 
                length = ebone->length;
index 62e3f8471a38d1117d0996e78fe2cc1a3f5d9c55..a40e32af3669c7ec8ad288c8ab3801dbd9e3ccd4 100644 (file)
@@ -1900,9 +1900,9 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
        const bool is_edit = (lt->editlatt != NULL);
 
        /* now we default make displist, this will modifiers work for non animated case */
-       if (ob->disp.first == NULL)
+       if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first))
                BKE_lattice_modifiers_calc(scene, ob);
-       dl = BKE_displist_find(&ob->disp, DL_VERTS);
+       dl = BKE_displist_find(&ob->curve_cache->disp, DL_VERTS);
        
        if (is_edit) {
                lt = lt->editlatt->latt;
@@ -3971,7 +3971,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
                case OB_CURVE:
                        cu = ob->data;
 
-                       lb = &ob->disp;
+                       lb = &ob->curve_cache->disp;
 
                        if (solid) {
                                dl = lb->first;
@@ -4021,7 +4021,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
                        break;
                case OB_SURF:
 
-                       lb = &ob->disp;
+                       lb = &ob->curve_cache->disp;
 
                        if (solid) {
                                dl = lb->first;
@@ -4049,8 +4049,11 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
                case OB_MBALL:
 
                        if (BKE_mball_is_basis(ob)) {
-                               lb = &ob->disp;
-                               if (lb->first == NULL) BKE_displist_make_mball(scene, ob);
+                               lb = ob->curve_cache ? &ob->curve_cache->disp : NULL;
+                               if (lb->first == NULL) {
+                                       BKE_displist_make_mball(scene, ob);
+                                       lb = &ob->curve_cache->disp;
+                               }
                                if (lb->first == NULL) {
                                        return true;
                                }
@@ -4566,7 +4569,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                pdd->ma_col = ma_col;
        }
 
-       psys->lattice = psys_get_lattice(&sim);
+       psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
 
        /* circles don't use drawdata, so have to add a special case here */
        if ((pdd || draw_as == PART_DRAW_CIRC) && draw_as != PART_DRAW_PATH) {
@@ -4892,9 +4895,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
        }
 
-       if (psys->lattice) {
-               end_latt_deform(psys->lattice);
-               psys->lattice = NULL;
+       if (psys->lattice_deform_data) {
+               end_latt_deform(psys->lattice_deform_data);
+               psys->lattice_deform_data = NULL;
        }
 
        if (pdd) {
@@ -5642,7 +5645,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
        if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) {
 
                UI_ThemeColor(TH_WIRE_EDIT);
-               for (bl = cu->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
+               for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
                        BevPoint *bevp = (BevPoint *)(bl + 1);
                        int nr = bl->nr;
                        int skip = nu->resolu / 16;
@@ -6065,7 +6068,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
        }
        else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) {
                Curve *cu = ob->data;
-               if ((cu->flag & CU_PATH) && cu->path && cu->path->data) {
+               if ((cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) {
                        float mindist, guidevec1[4], guidevec2[3];
 
                        //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
@@ -6248,7 +6251,7 @@ static void draw_bounding_volume(Scene *scene, Object *ob, char type)
                bb = BKE_mesh_boundbox_get(ob);
        }
        else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
-               bb = ob->bb ? ob->bb : ( (Curve *)ob->data)->bb;
+               bb = BKE_curve_boundbox_get(ob);
        }
        else if (ob->type == OB_MBALL) {
                if (BKE_mball_is_basis(ob)) {
@@ -6283,9 +6286,7 @@ static void drawtexspace(Object *ob)
                BKE_mesh_texspace_get(ob->data, loc, NULL, size);
        }
        else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
-               Curve *cu = ob->data;
-               copy_v3_v3(size, cu->size);
-               copy_v3_v3(loc, cu->loc);
+               BKE_curve_texspace_get(ob->data, loc, NULL, size);
        }
        else if (ob->type == OB_MBALL) {
                MetaBall *mb = ob->data;
@@ -6323,7 +6324,6 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
        glDepthMask(0);
        
        if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
-               Curve *cu = ob->data;
                DerivedMesh *dm = ob->derivedFinal;
                bool has_faces = false;
 
@@ -6331,16 +6331,16 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
                        has_faces = dm->getNumTessFaces(dm);
                }
                else {
-                       has_faces = BKE_displist_has_faces(&ob->disp);
+                       has_faces = BKE_displist_has_faces(&ob->curve_cache->disp);
                }
 
-               if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+               if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
                        draw_index_wire = false;
                        if (dm) {
                                draw_mesh_object_outline(v3d, ob, dm);
                        }
                        else {
-                               drawDispListwire(&ob->disp);
+                               drawDispListwire(&ob->curve_cache->disp);
                        }
                        draw_index_wire = true;
                }
@@ -6348,7 +6348,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
        else if (ob->type == OB_MBALL) {
                if (BKE_mball_is_basis(ob)) {
                        if ((base->flag & OB_FROMDUPLI) == 0)
-                               drawDispListwire(&ob->disp);
+                               drawDispListwire(&ob->curve_cache->disp);
                }
        }
        else if (ob->type == OB_ARMATURE) {
@@ -6375,8 +6375,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
                glDepthMask(0);  /* disable write in zbuffer, selected edge wires show better */
 
                if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
-                       Curve *cu = ob->data;
-                       if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+                       if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
                                if (ob->type == OB_CURVE)
                                        draw_index_wire = false;
 
@@ -6384,7 +6383,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
                                        drawCurveDMWired(ob);
                                }
                                else {
-                                       drawDispListwire(&ob->disp);
+                                       drawDispListwire(&ob->curve_cache->disp);
                                }
 
                                if (ob->type == OB_CURVE)
@@ -6393,7 +6392,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
                }
                else if (ob->type == OB_MBALL) {
                        if (BKE_mball_is_basis(ob)) {
-                               drawDispListwire(&ob->disp);
+                               drawDispListwire(&ob->curve_cache->disp);
                        }
                }
 
@@ -6703,7 +6702,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
        /* bad exception, solve this! otherwise outline shows too late */
        if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
                /* still needed for curves hidden in other layers. depgraph doesnt handle that yet */
-               if (ob->disp.first == NULL) BKE_displist_make_curveTypes(scene, ob, 0);
+               if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first)) {
+                       BKE_displist_make_curveTypes(scene, ob, 0);
+               }
        }
        
        /* draw outline for selected objects, mesh does itself */
@@ -6807,7 +6808,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                                        draw_bounding_volume(scene, ob, ob->boundtype);
                                }
                        }
-                       else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+                       else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
                                empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
                        }
 
@@ -6825,7 +6826,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                                        draw_bounding_volume(scene, ob, ob->boundtype);
                                }
                        }
-                       else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+                       else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
                                empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
 
 //XXX old animsys                              if (cu->path)
index fa8d43b175659cadcac159ed7a1b67e04d308597..9f6ad4a2d397d9b4af530e4228529f35274c38bd 100644 (file)
@@ -2073,7 +2073,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
                                bb = *bb_tmp; /* must make a copy  */
 
                                /* disable boundbox check for list creation */
-                               BKE_object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
+                               BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1);
                                /* need this for next part of code */
                                unit_m4(dob->ob->obmat);    /* obmat gets restored */
 
@@ -2083,7 +2083,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
                                glEndList();
 
                                use_displist = true;
-                               BKE_object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
+                               BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0);
                        }
                }
                if (use_displist) {
index d13ab15d8371cd142fa4fb403bf0ce99d18dab92..2023513ad920fc78f11fdffd3623daab6ff2df93 100644 (file)
@@ -368,7 +368,7 @@ void lattice_foreachScreenVert(
        Object *obedit = vc->obedit;
        Lattice *lt = obedit->data;
        BPoint *bp = lt->editlatt->latt->def;
-       DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS);
+       DispList *dl = obedit->curve_cache ? BKE_displist_find(&obedit->curve_cache->disp, DL_VERTS) : NULL;
        float *co = dl ? dl->verts : NULL;
        int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
 
index 4a14aa79e4171f0d4b2c1002330c698e46c18a02..de95388437673c682d95f57199722a1aea350c5b 100644 (file)
@@ -622,7 +622,7 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[4][4], const BoundB
        int a, flag = -1, fl;
 
        if (bb == NULL) return true;
-       if (bb->flag & OB_BB_DISABLED) return true;
+       if (bb->flag & BOUNDBOX_DISABLED) return true;
 
        mul_m4_m4m4(mat, rv3d->persmat, obmat);
 
index bed8aaaddf2d89d2c47c66135cb8ee0cf6d449a9..721a7a3b855ead9c61f5b7a1d32cbbc7a32746e5 100644 (file)
@@ -260,11 +260,12 @@ int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em
        int i, a, numleft = 0, numVerts = 0;
        int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
        float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
+       VirtualModifierData virtualModifierData;
 
        modifiers_clearErrors(ob);
 
        dm = NULL;
-       md = modifiers_getVirtualModifierList(ob);
+       md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        /* compute the deformation matrices and coordinates for the first
         * modifiers with on cage editing that are enabled and support computing
@@ -314,6 +315,7 @@ int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformma
        MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
        int has_multires = mmd != NULL && mmd->sculptlvl > 0;
        int numleft = 0;
+       VirtualModifierData virtualModifierData;
 
        if (has_multires) {
                *deformmats = NULL;
@@ -322,7 +324,7 @@ int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformma
        }
 
        dm = NULL;
-       md = modifiers_getVirtualModifierList(ob);
+       md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        for (; md; md = md->next) {
                ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -375,7 +377,8 @@ void crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3
                float (*origVerts)[3] = MEM_dupallocN(deformedVerts);
                float *quats = NULL;
                int i, deformed = 0;
-               ModifierData *md = modifiers_getVirtualModifierList(ob);
+               VirtualModifierData virtualModifierData;
+               ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
                Mesh *me = (Mesh *)ob->data;
 
                for (; md; md = md->next) {
index c54f937f4a917f0c994725192c678fc18cd75ca5..4420c260eedf434fb277579b70039db541a955fe 100644 (file)
@@ -77,6 +77,8 @@ static int useVBOs = -1;
 static GPUBufferState GLStates = 0;
 static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
 
+static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
+
 /* stores recently-deleted buffers so that new buffers won't have to
  * be recreated as often
  *
@@ -203,8 +205,11 @@ void GPU_global_buffer_pool_free_unused(void)
 }
 
 /* get a GPUBuffer of at least `size' bytes; uses one from the buffer
- * pool if possible, otherwise creates a new one */
-GPUBuffer *GPU_buffer_alloc(int size)
+ * pool if possible, otherwise creates a new one
+ *
+ * Thread-unsafe version for internal usage only.
+ */
+static GPUBuffer *gpu_buffer_alloc_intern(int size)
 {
        GPUBufferPool *pool;
        GPUBuffer *buf;
@@ -284,10 +289,30 @@ GPUBuffer *GPU_buffer_alloc(int size)
        return buf;
 }
 
+/* Same as above, but safe for threading. */
+GPUBuffer *GPU_buffer_alloc(int size)
+{
+       GPUBuffer *buffer;
+
+       if (size == 0) {
+               /* Early out, no lock needed in this case. */
+               return NULL;
+       }
+
+       BLI_mutex_lock(&buffer_mutex);
+       buffer = gpu_buffer_alloc_intern(size);
+       BLI_mutex_unlock(&buffer_mutex);
+
+       return buffer;
+}
+
 /* release a GPUBuffer; does not free the actual buffer or its data,
  * but rather moves it to the pool of recently-freed buffers for
- * possible re-use*/
-void GPU_buffer_free(GPUBuffer *buffer)
+ * possible re-use
+ *
+ * Thread-unsafe version for internal usage only.
+ */
+static void gpu_buffer_free_intern(GPUBuffer *buffer)
 {
        GPUBufferPool *pool;
        int i;
@@ -326,6 +351,19 @@ void GPU_buffer_free(GPUBuffer *buffer)
        pool->totbuf++;
 }
 
+/* Same as above, but safe for threading. */
+void GPU_buffer_free(GPUBuffer *buffer)
+{
+       if (!buffer) {
+               /* Early output, no need to lock in this case, */
+               return;
+       }
+
+       BLI_mutex_lock(&buffer_mutex);
+       gpu_buffer_free_intern(buffer);
+       BLI_mutex_unlock(&buffer_mutex);
+}
+
 typedef struct GPUVertPointLink {
        struct GPUVertPointLink *next;
        /* -1 means uninitialized */
@@ -510,13 +548,17 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
 
        pool = gpu_get_global_buffer_pool();
 
+       BLI_mutex_lock(&buffer_mutex);
+
        /* alloc a GPUBuffer; fall back to legacy mode on failure */
-       if (!(buffer = GPU_buffer_alloc(size)))
+       if (!(buffer = gpu_buffer_alloc_intern(size)))
                dm->drawObject->legacy = 1;
 
        /* nothing to do for legacy mode */
-       if (dm->drawObject->legacy)
+       if (dm->drawObject->legacy) {
+               BLI_mutex_unlock(&buffer_mutex);
                return NULL;
+       }
 
        cur_index_per_mat = MEM_mallocN(sizeof(int) * object->totmaterial,
                                        "GPU_buffer_setup.cur_index_per_mat");
@@ -541,7 +583,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
                        /* attempt to map the buffer */
                        if (!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) {
                                /* failed to map the buffer; delete it */
-                               GPU_buffer_free(buffer);
+                               gpu_buffer_free_intern(buffer);
                                gpu_buffer_pool_delete_last(pool);
                                buffer = NULL;
 
@@ -549,7 +591,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
                                 * and reallocating the buffer */
                                if (pool->totbuf > 0) {
                                        gpu_buffer_pool_delete_last(pool);
-                                       buffer = GPU_buffer_alloc(size);
+                                       buffer = gpu_buffer_alloc_intern(size);
                                }
 
                                /* allocation still failed; fall back
@@ -591,6 +633,8 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
 
        MEM_freeN(cur_index_per_mat);
 
+       BLI_mutex_unlock(&buffer_mutex);
+
        return buffer;
 }
 
index 7ff8667f90eb5b58caa7a972decbc841a6d01cd5..1c99f9ac827bb5c9de742dc988ce5aa476a22a6c 100644 (file)
@@ -178,18 +178,14 @@ typedef struct Curve {
        struct BoundBox *bb;
        
        ListBase nurb;          /* actual data, called splines in rna */
-       ListBase disp;          /* undeformed display list, used mostly for texture space calculation */
        
        EditNurb *editnurb;     /* edited data, not in file, use pointer so we can check for it */
        
        struct Object *bevobj, *taperobj, *textoncurve;
        struct Ipo *ipo    DNA_DEPRECATED;  /* old animation system, deprecated for 2.5 */
-       Path *path;
        struct Key *key;
        struct Material **mat;
        
-       ListBase bev;
-       
        /* texture space, copied as one block in editobject.c */
        float loc[3];
        float size[3];
index 0a09a82b2bb7ceefaa8eb84aaba2f92e1e7ea7d6..f5ce3c8d8c1decded8392418acaaadc0d057f156 100644 (file)
@@ -60,7 +60,6 @@ typedef struct KeyBlock {
        int uid;           /* for meshes only, match the unique number with the customdata layer */
        
        void  *data;       /* array of shape key values, size is (Key->elemsize * KeyBlock->totelem) */
-       float *weights;    /* store an aligned array of weights from 'vgroup' */
        char   name[64];   /* MAX_NAME (unique name, user assigned) */
        char   vgroup[64]; /* MAX_VGROUP_NAME (optional vertex group), array gets allocated into 'weights' when set */
 
index 837f0c354e6246e61524bf03350d28fd098ee02e..242d6f0feeb42159aa452701671cd6588607ab61 100644 (file)
@@ -68,10 +68,6 @@ typedef struct Lattice {
        struct MDeformVert *dvert;
        char vgroup[64]; /* multiply the influence, MAX_VGROUP_NAME */
        
-       /* used while deforming, always free and NULL after use */
-       float *latticedata;
-       float latmat[4][4];
-       
        struct EditLatt *editlatt;
 } Lattice;
 
index 56683bf47971f17d8fef74366bbba8daae6993ef..8bbe53b33a641e5ca07e32cf2358bd6029d6b70c 100644 (file)
@@ -65,8 +65,6 @@ typedef struct MetaBall {
        ID id;
        struct AnimData *adt;
        
-       struct BoundBox *bb;
-
        ListBase elems;
        ListBase disp;
        ListBase *editelems;            /* not saved in files, note we use pointer for editmode check */
index de34f101c3155c11a1eb44c0632f95314371560a..d897428415577312fd0d85421f584864724300c1 100644 (file)
@@ -100,7 +100,10 @@ typedef struct BoundBox {
 } BoundBox;
 
 /* boundbox flag */
-#define OB_BB_DISABLED 1
+enum {
+       BOUNDBOX_DISABLED = (1 << 0),
+       BOUNDBOX_INVALID  = (1 << 1),
+};
 
 typedef struct Object {
        ID id;
@@ -130,7 +133,6 @@ typedef struct Object {
        
        ListBase constraintChannels  DNA_DEPRECATED; // XXX deprecated... old animation system
        ListBase effect  DNA_DEPRECATED;             // XXX deprecated... keep for readfile
-       ListBase disp;      /* list of DispList, used by lattice, metaballs curve & surfaces */
        ListBase defbase;   /* list of bDeformGroup (vertex groups) names and flag only */
        ListBase modifiers; /* list of ModifierData structures */
 
@@ -276,6 +278,9 @@ typedef struct Object {
        struct RigidBodyCon *rigidbody_constraint;      /* settings for Bullet constraint */
 
        float ima_ofs[2];               /* offset for image empties */
+
+       /* Runtime valuated curve-specific data, not stored in the file */
+       struct CurveCache *curve_cache;
 } Object;
 
 /* Warning, this is not used anymore because hooks are now modifiers */
index 29fcaf3bf735a434c3df2fed137ec9b892e3f0cc..b7ca3066b4f8338ef14c78193afffcedc1011acd 100644 (file)
@@ -272,7 +272,9 @@ typedef struct ParticleSystem {
        struct DerivedMesh *hair_in_dm, *hair_out_dm;   /* input/output for cloth simulation */
 
        struct Object *target_ob;
-       struct Object *lattice;
+
+       struct LatticeDeformData *lattice_deform_data;          /* run-time only lattice deformation data */
+
        struct Object *parent;                                  /* particles from global space -> parent space */
 
        struct ListBase targets;                                /* used for keyed and boid physics */
index ceb745cf90a4f65a4af0c2baf6bf72e7bdde5531..e055374502592de80f6fc2c016334a48f4ee5413 100644 (file)
@@ -431,7 +431,8 @@ typedef struct RenderData {
         * Render to image editor, fullscreen or to new window.
         */
        short displaymode;
-       short pad7;
+       char use_lock_interface;
+       char pad7;
 
        /**
         * Flags for render settings. Use bit-masking to access the settings.
index 27aef3b8ec63715969d37b88dfa05bdc4dd999d8..29fac36ddd078030b854496a8c44a605704b2474 100644 (file)
@@ -151,6 +151,9 @@ typedef struct wmWindowManager {
 
        ListBase timers;                                        /* active timers */
        struct wmTimer *autosavetimer;          /* timer for auto save */
+
+       char is_interface_locked;               /* indicates whether interface is locked for user interaction */
+       char par[7];
 } wmWindowManager;
 
 /* wmWindowManager.initialized */
index fd9312629040ad9a405b995c3e78de99dcdf92ca..8104fc169f606b85be32a3b871a14de2cc943861 100644 (file)
@@ -361,8 +361,13 @@ Mesh *rna_Main_meshes_new_from_object(
                                BKE_mesh_from_metaball(&disp, tmpmesh);
                                BKE_displist_free(&disp);
                        }
-                       else
-                               BKE_mesh_from_metaball(&ob->disp, tmpmesh);
+                       else {
+                               ListBase disp = {NULL, NULL};
+                               if (ob->curve_cache) {
+                                       disp = ob->curve_cache->disp;
+                               }
+                               BKE_mesh_from_metaball(&disp, tmpmesh);
+                       }
 
                        BKE_mesh_texspace_copy_from_object(tmpmesh, ob);
 
index 35d8a0fb43378e505291e1d0a94d4b1ef92cc966..d217fc285c3fa055c7917b4575b26633508714fc 100644 (file)
@@ -575,8 +575,9 @@ static void rna_Mesh_texspace_size_get(PointerRNA *ptr, float values[3])
 {
        Mesh *me = (Mesh *)ptr->data;
 
-       if (!me->bb)
+       if (me->bb == NULL || (me->bb->flag & BOUNDBOX_INVALID)) {
                BKE_mesh_texspace_calc(me);
+       }
 
        copy_v3_v3(values, me->size);
 }
@@ -585,8 +586,9 @@ static void rna_Mesh_texspace_loc_get(PointerRNA *ptr, float values[3])
 {
        Mesh *me = (Mesh *)ptr->data;
 
-       if (!me->bb)
+       if (me->bb == NULL || (me->bb->flag & BOUNDBOX_INVALID)) {
                BKE_mesh_texspace_calc(me);
+       }
 
        copy_v3_v3(values, me->loc);
 }
index 83dbd79024e246ecdab2451c3bb8056a6b2d97f6..49098a1d8c4b9e298317d0bea69addceca8debfd 100644 (file)
@@ -4558,7 +4558,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
        RNA_def_property_enum_items(prop, display_mode_items);
        RNA_def_property_ui_text(prop, "Display", "Select where rendered images will be displayed");
        RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-       
+
+       prop = RNA_def_property(srna, "use_lock_interface", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "use_lock_interface", 1);
+       RNA_def_property_ui_text(prop, "Lock Interface", "Lock interface during rendering in favor of giving more memory to the renderer");
+       RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
        prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
        RNA_def_property_string_sdna(prop, NULL, "pic");
        RNA_def_property_ui_text(prop, "Output Path",
index 375b31e058612a67431d62197c65dd3373eff093..502f959ce2c09105dfecb991e68ecf17bb468b53 100644 (file)
@@ -61,7 +61,7 @@ static void rna_Scene_frame_set(Scene *scene, int frame, float subframe)
        CLAMP(cfra, MINAFRAME, MAXFRAME);
        BKE_scene_frame_set(scene, cfra);
 
-       BKE_scene_update_for_newframe(G.main, scene, (1 << 20) - 1);
+       BKE_scene_update_for_newframe_ex(G.main, scene, (1 << 20) - 1, false);
        BKE_scene_camera_switch_update(scene);
 
        /* don't do notifier when we're rendering, avoid some viewport crashes
@@ -78,7 +78,7 @@ static void rna_Scene_frame_set(Scene *scene, int frame, float subframe)
 
 static void rna_Scene_update_tagged(Scene *scene)
 {
-       BKE_scene_update_tagged(G.main, scene);
+       BKE_scene_update_tagged_ex(G.main, scene, false);
 }
 
 static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, char *name)
index e09fa18ffc5ff85a53d24f676a78475264788031..3478ec6e3b4221c4914147a5d468e2fd0a8e1b79 100644 (file)
@@ -50,6 +50,7 @@
 
 #include "BKE_cdderivedmesh.h"
 #include "BKE_displist.h"
+#include "BKE_curve.h"
 #include "BKE_mesh.h"
 #include "BKE_modifier.h"
 #include "BKE_object.h"
@@ -387,12 +388,12 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
                        BKE_object_to_mat3(amd->curve_ob, tmp_mat);
                        scale = mat3_to_scale(tmp_mat);
                                
-                       if (!cu->path) {
+                       if (!amd->curve_ob->curve_cache || !amd->curve_ob->curve_cache->path) {
                                cu->flag |= CU_PATH; // needed for path & bevlist
                                BKE_displist_make_curveTypes(scene, amd->curve_ob, 0);
                        }
-                       if (cu->path)
-                               length = scale * cu->path->totdist;
+                       if (amd->curve_ob->curve_cache->path)
+                               length = scale * amd->curve_ob->curve_cache->path->totdist;
                }
        }
 
index fe680041197796abec5a4c06033b2f9a098ec101..c4aa41cd566485ef4321172ceb69e0078053fc65 100644 (file)
@@ -869,7 +869,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
        /* getting back to object space */
        invert_m4_m4(imat, ob->obmat);
 
-       psmd->psys->lattice = psys_get_lattice(&sim);
+       psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
 
        /* duplicate & displace vertices */
        ehi = BLI_edgehashIterator_new(vertpahash);
@@ -973,9 +973,9 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
        CDDM_tessfaces_to_faces(explode);
        explode->dirty |= DM_DIRTY_NORMALS;
 
-       if (psmd->psys->lattice) {
-               end_latt_deform(psmd->psys->lattice);
-               psmd->psys->lattice = NULL;
+       if (psmd->psys->lattice_deform_data) {
+               end_latt_deform(psmd->psys->lattice_deform_data);
+               psmd->psys->lattice_deform_data = NULL;
        }
 
        return explode;
index e846ce11262b8d0a294da57a069b729f56d3c90a..c51fa329df22fc7eb810bdf9d3922fe1249a01bd 100644 (file)
@@ -261,7 +261,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                maxloop += totloop;
        }
 
-       psys->lattice = psys_get_lattice(&sim);
+       psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
 
        if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
                float min_r[3], max_r[3];
@@ -378,9 +378,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
 
        CDDM_calc_edges(result);
 
-       if (psys->lattice) {
-               end_latt_deform(psys->lattice);
-               psys->lattice = NULL;
+       if (psys->lattice_deform_data) {
+               end_latt_deform(psys->lattice_deform_data);
+               psys->lattice_deform_data = NULL;
        }
 
        if (size)
index e29cea279cec4497402378e22295ddd7873a0aae..90432ddb5b5a21d09a3f89ebfd9220443758ef06 100644 (file)
@@ -1741,7 +1741,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
        }
 
        if (path_nbr == 0)
-               psys->lattice = psys_get_lattice(&sim);
+               psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
 
 /* 3. start creating renderable things */
        for (a=0, pa=pars; a<totpart+totchild; a++, pa++, seed++) {
@@ -2094,9 +2094,9 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 
        psys->flag &= ~PSYS_DRAWING;
 
-       if (psys->lattice) {
-               end_latt_deform(psys->lattice);
-               psys->lattice= NULL;
+       if (psys->lattice_deform_data) {
+               end_latt_deform(psys->lattice_deform_data);
+               psys->lattice_deform_data = NULL;
        }
 
        if (path_nbr && (ma->mode_l & MA_TANGENT_STR)==0)
index d4d6bfa5b7f10294490dcb78ea8a762505fc45b1..ce87888b6a0aac1ed8222216e0d650f2ac6c50ef 100644 (file)
@@ -140,7 +140,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa
        invert_m4_m4(ob->imat, ob->obmat);
        
        total_particles = psys->totpart+psys->totchild;
-       psys->lattice=psys_get_lattice(&sim);
+       psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
        
        pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
        alloc_point_data(pd, total_particles, data_used);
@@ -215,9 +215,9 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa
        BLI_bvhtree_balance(pd->point_tree);
        dm->release(dm);
        
-       if (psys->lattice) {
-               end_latt_deform(psys->lattice);
-               psys->lattice = NULL;
+       if (psys->lattice_deform_data) {
+               end_latt_deform(psys->lattice_deform_data);
+               psys->lattice_deform_data = NULL;
        }
        
        psys_render_restore(ob, psys);
index 8894be111e7e08ff09c7bfa9c2ee2ce481e32cb7..ac92e733028928cbc5912eb338b2e669a728a53f 100644 (file)
@@ -425,6 +425,9 @@ void        WM_main_playanim(int argc, const char **argv);
 /* debugging only, convenience function to write on crash */
 int write_crash_blend(void);
 
+                       /* Lock the interface for any communication */
+void        WM_set_locked_interface(struct wmWindowManager *wm, bool lock);
+
 #ifdef __cplusplus
 }
 #endif
index f1932c8aa97f2bbb6a205482150c2403765d581d..2364c4b13bb71ad78f53d54732224d1093275400 100644 (file)
@@ -133,6 +133,7 @@ struct ImBuf;
                                                                 * and don't make sense to be accessed from the
                                                                 * search menu, even if poll() returns TRUE.
                                                                 * currently only used for the search toolbox */
+#define OPTYPE_ALLOW_LOCKED    128     /* Allow operator to run when interface is locked */
 
 /* context to call operator in for WM_operator_name_call */
 /* rna_ui.c contains EnumPropertyItem's of these, keep in sync */
index b4f193bdbe6256a16291d34e053a5b2b1db78f1a..8d7152fb98b756603da8400e1773643c8630b522 100644 (file)
@@ -1463,6 +1463,22 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve
        }
 }
 
+/* Check whether operator is allowed to run in case interface is locked,
+ * If interface is unlocked, will always return truth.
+ */
+static bool wm_operator_check_locked_interface(bContext *C, wmOperatorType *ot)
+{
+       wmWindowManager *wm = CTX_wm_manager(C);
+
+       if (wm->is_interface_locked) {
+               if ((ot->flag & OPTYPE_ALLOW_LOCKED) == 0) {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
 /* bad hacking event system... better restore event type for checking of KM_CLICK for example */
 /* XXX modal maps could use different method (ton) */
 static void wm_event_modalmap_end(wmEvent *event)
@@ -1489,7 +1505,12 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
                wmOperator *op = handler->op;
                wmOperatorType *ot = op->type;
 
-               if (ot->modal) {
+               if (!wm_operator_check_locked_interface(C, ot)) {
+                       /* Interface is locked and pperator is not allowed to run,
+                        * nothing to do in this case.
+                        */
+               }
+               else if (ot->modal) {
                        /* we set context to where modal handler came from */
                        wmWindowManager *wm = CTX_wm_manager(C);
                        ScrArea *area = CTX_wm_area(C);
@@ -1561,7 +1582,9 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
                wmOperatorType *ot = WM_operatortype_find(event->keymap_idname, 0);
 
                if (ot) {
-                       retval = wm_operator_invoke(C, ot, event, properties, NULL, FALSE);
+                       if (wm_operator_check_locked_interface(C, ot)) {
+                               retval = wm_operator_invoke(C, ot, event, properties, NULL, FALSE);
+                       }
                }
        }
        /* Finished and pass through flag as handled */
@@ -1767,7 +1790,11 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
                /* comment this out to flood the console! (if you really want to test) */
                !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)
                ;
+#    define PRINT if (do_debug_handler) printf
+#else
+#  define PRINT(format, ...)
 #endif
+
        wmWindowManager *wm = CTX_wm_manager(C);
        wmEventHandler *handler, *nexthandler;
        int action = WM_HANDLER_CONTINUE;
@@ -1803,28 +1830,16 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
                                wmKeyMap *keymap = WM_keymap_active(wm, handler->keymap);
                                wmKeyMapItem *kmi;
 
-#ifndef NDEBUG
-                               if (do_debug_handler) {
-                                       printf("%s:   checking '%s' ...", __func__, keymap->idname);
-                               }
-#endif
+                               PRINT("%s:   checking '%s' ...", __func__, keymap->idname);
 
                                if (!keymap->poll || keymap->poll(C)) {
 
-#ifndef NDEBUG
-                                       if (do_debug_handler) {
-                                               printf("pass\n");
-                                       }
-#endif
+                                       PRINT("pass\n");
 
                                        for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
                                                if (wm_eventmatch(event, kmi)) {
 
-#ifndef NDEBUG
-                                                       if (do_debug_handler) {
-                                                               printf("%s:     item matched '%s'\n", __func__, kmi->idname);
-                                                       }
-#endif
+                                                       PRINT("%s:     item matched '%s'\n", __func__, kmi->idname);
 
                                                        /* weak, but allows interactive callback to not use rawkey */
                                                        event->keymap_idname = kmi->idname;
@@ -1843,32 +1858,28 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
                                                                        if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS))
                                                                                printf("%s:       handled - and pass on! '%s'\n", __func__, kmi->idname);
                                                                
-#ifndef NDEBUG
-                                                               if (do_debug_handler) {
-                                                                       printf("%s:       un-handled '%s'...", __func__, kmi->idname);
-                                                               }
-#endif
+                                                                       PRINT("%s:       un-handled '%s'...", __func__, kmi->idname);
                                                        }
                                                }
                                        }
                                }
                                else {
-#ifndef NDEBUG
-                                       if (do_debug_handler) {
-                                               printf("fail\n");
-                                       }
-#endif
+                                       PRINT("fail\n");
                                }
                        }
                        else if (handler->ui_handle) {
-                               action |= wm_handler_ui_call(C, handler, event, always_pass);
+                               if (!wm->is_interface_locked) {
+                                       action |= wm_handler_ui_call(C, handler, event, always_pass);
+                               }
                        }
                        else if (handler->type == WM_HANDLER_FILESELECT) {
-                               /* screen context changes here */
-                               action |= wm_handler_fileselect_call(C, handlers, handler, event);
+                               if (!wm->is_interface_locked) {
+                                       /* screen context changes here */
+                                       action |= wm_handler_fileselect_call(C, handlers, handler, event);
+                               }
                        }
                        else if (handler->dropboxes) {
-                               if (event->type == EVT_DROP) {
+                               if (!wm->is_interface_locked && event->type == EVT_DROP) {
                                        wmDropBox *drop = handler->dropboxes->first;
                                        for (; drop; drop = drop->next) {
                                                /* other drop custom types allowed */
@@ -1934,6 +1945,8 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
        if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL))
                wm_cursor_arrow_move(CTX_wm_window(C), event);
 
+#undef PRINT
+
        return action;
 }
 
@@ -3243,3 +3256,24 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
        WM_event_print(&event);
 #endif
 }
+
+void WM_set_locked_interface(wmWindowManager *wm, bool lock)
+{
+       /* This will prevent events from being handled while interface is locked
+        *
+        * Use a "local" flag for now, because currently no other areas could
+        * benefit of locked interface anyway (aka using G.is_interface_locked
+        * wouldn't be useful anywhere outside of window manager, so let's not
+        * pollute global context with such an information for now).
+        */
+       wm->is_interface_locked = lock ? 1 : 0;
+
+       /* This will prevent drawing regions which uses non-threadsafe data.
+        * Currently it'll be just a 3D viewport.
+        *
+        * TODO(sergey): Make it different locked states, so different jobs
+        *               could lock different areas of blender and allow
+        *               interation with others?
+        */
+       BKE_spacedata_draw_locks(lock);
+}
index 63cf1eeb40d9d3b0ee6813414169407245e3a2fd..2663b3e8c7645837d36b3aa4fa99073f05edda39 100644 (file)
@@ -51,6 +51,7 @@
 #include "BLI_listbase.h"
 #include "BLI_path_util.h"
 #include "BLI_string.h"
+#include "BLI_threads.h"
 #include "BLI_utildefines.h"
 
 #include "BKE_blender.h"
@@ -510,12 +511,14 @@ void WM_exit_ext(bContext *C, const short do_python)
        
        GHOST_DisposeSystemPaths();
 
+       BLI_threadapi_exit();
+
        if (MEM_get_memory_blocks_in_use() != 0) {
                printf("Error: Not freed memory blocks: %d\n", MEM_get_memory_blocks_in_use());
                MEM_printmemlist();
        }
        wm_autosave_delete();
-       
+
        printf("\nBlender quit\n");
        
 #ifdef WIN32   
index a710c07f34b1c000234dca583ffeb6349fa872eb..27fd9427da781270a3409d722d9d664bd87be04c 100644 (file)
@@ -92,6 +92,7 @@
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
+#include "BKE_modifier.h"
 #include "BKE_packedFile.h"
 #include "BKE_scene.h"
 #include "BKE_node.h"
@@ -1517,6 +1518,7 @@ int main(int argc, const char **argv)
 
        IMB_init();
        BKE_images_init();
+       BKE_modifier_init();
 
        BKE_brush_system_init();
 
index 59cf10d326a422a8bca83d87858e8307732fd536..5aec3c9e965b7ed5949abab433d03a94943d471d 100644 (file)
@@ -159,16 +159,20 @@ bool BL_ShapeDeformer::Update(void)
                /* the key coefficient have been set already, we just need to blend the keys */
                Object* blendobj = m_gameobj->GetBlendObject();
                
-               // make sure the vertex weight cache is in line with this object
-               m_pMeshObject->CheckWeightCache(blendobj);
-
                /* we will blend the key directly in m_transverts array: it is used by armature as the start position */
                /* m_key can be NULL in case of Modifier deformer */
                if (m_key) {
+                       WeightsArrayCache cache = {0, NULL};
+                       float **per_keyblock_weights;
+
                        /* store verts locally */
                        VerifyStorage();
 
-                       BKE_key_evaluate_relative(0, m_bmesh->totvert, m_bmesh->totvert, (char *)(float *)m_transverts, m_key, NULL, 0); /* last arg is ignored */
+                       per_keyblock_weights = BKE_keyblock_get_per_block_weights(blendobj, m_key, &cache);
+                       BKE_key_evaluate_relative(0, m_bmesh->totvert, m_bmesh->totvert, (char *)(float *)m_transverts,
+                                                 m_key, NULL, per_keyblock_weights, 0); /* last arg is ignored */
+                       BKE_keyblock_free_per_block_weights(m_key, per_keyblock_weights, &cache);
+
                        m_bDynamic = true;
                }
 
index ccbcdd256393039346887a2ab2f52bed07857324..aa7d41cc410f575e1a044be1a0d2efbc5240e223 100644 (file)
@@ -64,6 +64,7 @@ extern "C"
 #include "BKE_node.h"
 #include "BKE_report.h"
 #include "BKE_library.h"
+#include "BKE_modifier.h"
 #include "BLI_threads.h"
 #include "BLI_blenlib.h"
 #include "DNA_scene_types.h"
@@ -456,6 +457,7 @@ int main(int argc, char** argv)
 
        IMB_init();
        BKE_images_init();
+       BKE_modifier_init();
 
 #ifdef WITH_FFMPEG
        IMB_ffmpeg_init();
index 2af71c5efa997dc72c9fd172854050ea394d6d0b..92f134c17020e3ee4942752bf451d3c31e0bdb55 100644 (file)
@@ -125,17 +125,6 @@ RAS_MeshObject::~RAS_MeshObject()
 {
        vector<RAS_Polygon*>::iterator it;
 
-       if (m_mesh && m_mesh->key) 
-       {
-               KeyBlock *kb;
-               // remove the weight cache to avoid memory leak 
-               for (kb = (KeyBlock *)m_mesh->key->block.first; kb; kb = (KeyBlock *)kb->next) {
-                       if (kb->weights) 
-                               MEM_freeN(kb->weights);
-                       kb->weights= NULL;
-               }
-       }
-
        for (it=m_Polygons.begin(); it!=m_Polygons.end(); it++)
                delete (*it);
 
@@ -571,49 +560,3 @@ static int get_def_index(Object* ob, const char* vgroup)
 
        return -1;
 }
-
-void RAS_MeshObject::CheckWeightCache(Object* obj)
-{
-       KeyBlock *kb;
-       int kbindex, defindex;
-       MDeformVert *dv= NULL;
-       int totvert, i;
-       float *weights;
-
-       if (!m_mesh->key)
-               return;
-
-       for (kbindex = 0, kb = (KeyBlock *)m_mesh->key->block.first; kb; kb = kb->next, kbindex++)
-       {
-               // first check the cases where the weight must be cleared
-               if (kb->vgroup[0] == 0 ||
-                       m_mesh->dvert == NULL ||
-                       (defindex = get_def_index(obj, kb->vgroup)) == -1) {
-                       if (kb->weights) {
-                               MEM_freeN(kb->weights);
-                               kb->weights = NULL;
-                       }
-                       m_cacheWeightIndex[kbindex] = -1;
-               } else if (m_cacheWeightIndex[kbindex] != defindex) {
-                       // a weight array is required but the cache is not matching
-                       if (kb->weights) {
-                               MEM_freeN(kb->weights);
-                               kb->weights = NULL;
-                       }
-
-                       dv= m_mesh->dvert;
-                       totvert= m_mesh->totvert;
-               
-                       weights= (float*)MEM_mallocN(totvert*sizeof(float), "weights");
-               
-                       for (i=0; i < totvert; i++, dv++) {
-                               weights[i] = defvert_find_weight(dv, defindex);
-                       }
-
-                       kb->weights = weights;
-                       m_cacheWeightIndex[kbindex] = defindex;
-               }
-       }
-}
-
-
index d77d048302499fd9a0c63904b84d695c5015bb87..e5ae78d006e09cf8d77dc536abaa82dcea8272dd 100644 (file)
@@ -83,9 +83,6 @@ public:
        virtual ~RAS_MeshObject();
 
 
-       // for shape keys, 
-       void CheckWeightCache(struct Object* obj);
-       
        /* materials */
        int                                     NumMaterials();
 &nb