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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_animsys.h4
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h4
-rw-r--r--source/blender/blenkernel/BKE_cloth.h20
-rw-r--r--source/blender/blenkernel/BKE_collection.h2
-rw-r--r--source/blender/blenkernel/BKE_collision.h5
-rw-r--r--source/blender/blenkernel/BKE_displist_tangent.h26
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h28
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h1
-rw-r--r--source/blender/blenkernel/BKE_idprop.h2
-rw-r--r--source/blender/blenkernel/BKE_lightprobe.h1
-rw-r--r--source/blender/blenkernel/BKE_mesh.h1
-rw-r--r--source/blender/blenkernel/BKE_node.h3
-rw-r--r--source/blender/blenkernel/BKE_object.h1
-rw-r--r--source/blender/blenkernel/BKE_paint.h48
-rw-r--r--source/blender/blenkernel/BKE_scene.h2
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h7
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt24
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c21
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c22
-rw-r--r--source/blender/blenkernel/intern/armature.c8
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c10
-rw-r--r--source/blender/blenkernel/intern/cloth.c118
-rw-r--r--source/blender/blenkernel/intern/collection.c5
-rw-r--r--source/blender/blenkernel/intern/collision.c703
-rw-r--r--source/blender/blenkernel/intern/constraint.c66
-rw-r--r--source/blender/blenkernel/intern/curve.c137
-rw-r--r--source/blender/blenkernel/intern/deform.c2
-rw-r--r--source/blender/blenkernel/intern/displist_tangent.c279
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c6
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c548
-rw-r--r--source/blender/blenkernel/intern/editmesh.c93
-rw-r--r--source/blender/blenkernel/intern/fcurve.c107
-rw-r--r--source/blender/blenkernel/intern/fluid.c850
-rw-r--r--source/blender/blenkernel/intern/gpencil.c14
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c8
-rw-r--r--source/blender/blenkernel/intern/idprop.c15
-rw-r--r--source/blender/blenkernel/intern/image.c52
-rw-r--r--source/blender/blenkernel/intern/library_query.c36
-rw-r--r--source/blender/blenkernel/intern/lightprobe.c24
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c27
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c2
-rw-r--r--source/blender/blenkernel/intern/multires.c18
-rw-r--r--source/blender/blenkernel/intern/nla.c4
-rw-r--r--source/blender/blenkernel/intern/node.c16
-rw-r--r--source/blender/blenkernel/intern/object.c70
-rw-r--r--source/blender/blenkernel/intern/object_update.c3
-rw-r--r--source/blender/blenkernel/intern/paint.c27
-rw-r--r--source/blender/blenkernel/intern/particle.c49
-rw-r--r--source/blender/blenkernel/intern/particle_system.c68
-rw-r--r--source/blender/blenkernel/intern/pbvh.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c48
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c12
-rw-r--r--source/blender/blenkernel/intern/seqprefetch.c4
-rw-r--r--source/blender/blenkernel/intern/sequencer.c108
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c77
-rw-r--r--source/blender/blenkernel/intern/softbody.c6
-rw-r--r--source/blender/blenkernel/intern/sound.c14
-rw-r--r--source/blender/blenkernel/intern/studiolight.c5
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c2
-rw-r--r--source/blender/blenkernel/intern/workspace.c8
62 files changed, 1871 insertions, 2006 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 963e3158d46..9da17d777cd 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -249,6 +249,10 @@ typedef enum eAnimData_Recalc {
ADT_RECALC_ALL = (ADT_RECALC_DRIVERS | ADT_RECALC_ANIM),
} eAnimData_Recalc;
+bool BKE_animsys_store_rna_setting(struct PointerRNA *ptr,
+ const char *rna_path,
+ const int array_index,
+ struct PathResolvedRNA *r_result);
bool BKE_animsys_read_rna_setting(struct PathResolvedRNA *anim_rna, float *r_value);
bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float value);
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 9855c2202cc..2acef7847bc 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -26,8 +26,8 @@
*
* \note Use #STRINGIFY() rather than defining with quotes.
*/
-#define BLENDER_VERSION 282
-#define BLENDER_SUBVERSION 6
+#define BLENDER_VERSION 283
+#define BLENDER_SUBVERSION 2
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 17de53be42a..2862dda8ead 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -74,11 +74,11 @@ typedef struct ClothSolverResult {
* own connectivity of the mesh based on the actual edges in the mesh.
*/
typedef struct Cloth {
- struct ClothVertex *verts; /* The vertices that represent this cloth. */
- struct LinkNode *springs; /* The springs connecting the mesh. */
- unsigned int numsprings; /* The count of springs. */
- unsigned int mvert_num; /* The number of verts == m * n. */
- unsigned int tri_num;
+ struct ClothVertex *verts; /* The vertices that represent this cloth. */
+ struct LinkNode *springs; /* The springs connecting the mesh. */
+ unsigned int numsprings; /* The count of springs. */
+ unsigned int mvert_num; /* The number of verts == m * n. */
+ unsigned int primitive_num; /* Number of triangles for cloth and edges for hair. */
unsigned char old_solver_type; /* unused, only 1 solver here */
unsigned char pad2;
short pad3;
@@ -89,6 +89,7 @@ typedef struct Cloth {
struct EdgeSet *edgeset; /* used for selfcollisions */
int last_frame;
float initial_mesh_volume; /* Initial volume of the mesh. Used for pressure */
+ struct MEdge *edges; /* Used for hair collisions. */
} Cloth;
/**
@@ -265,15 +266,6 @@ int cloth_bvh_collision(struct Depsgraph *depsgraph,
float step,
float dt);
-void cloth_find_point_contacts(struct Depsgraph *depsgraph,
- struct Object *ob,
- struct ClothModifierData *clmd,
- float step,
- float dt,
- ColliderContacts **r_collider_contacts,
- int *r_totcolliders);
-void cloth_free_contacts(ColliderContacts *collider_contacts, int totcolliders);
-
////////////////////////////////////////////////
/////////////////////////////////////////////////
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 0d33d86ec16..47ed42cade9 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -142,6 +142,8 @@ bool BKE_collection_child_add(struct Main *bmain,
struct Collection *parent,
struct Collection *child);
+bool BKE_collection_child_add_no_sync(struct Collection *parent, struct Collection *child);
+
bool BKE_collection_child_remove(struct Main *bmain,
struct Collection *parent,
struct Collection *child);
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index 5d7a5094eb5..5bf697e5df9 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -125,7 +125,10 @@ void bvhtree_update_from_mvert(BVHTree *bvhtree,
// move Collision modifier object inter-frame with step = [0,1]
// defined in collisions.c
-void collision_move_object(struct CollisionModifierData *collmd, float step, float prevstep);
+void collision_move_object(struct CollisionModifierData *collmd,
+ const float step,
+ const float prevstep,
+ const bool moving_bvh);
void collision_get_collider_velocity(float vel_old[3],
float vel_new[3],
diff --git a/source/blender/blenkernel/BKE_displist_tangent.h b/source/blender/blenkernel/BKE_displist_tangent.h
new file mode 100644
index 00000000000..3af7c513f67
--- /dev/null
+++ b/source/blender/blenkernel/BKE_displist_tangent.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#ifndef __BKE_DISPLIST_TANGENT_H__
+#define __BKE_DISPLIST_TANGENT_H__
+
+/** \file
+ * \ingroup bke
+ */
+
+void BKE_displist_tangent_calc(const DispList *dl, float (*fnormals)[3], float (**r_tangent)[4]);
+
+#endif /* __BKE_DISPLIST_TANGENT_H__ */
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index 1b9e318146e..80cb0f1482b 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -35,6 +35,7 @@ struct Depsgraph;
struct EditMeshData;
struct Mesh;
struct MeshStatVis;
+struct Object;
struct Scene;
/**
@@ -65,18 +66,11 @@ typedef struct BMEditMesh {
/*derivedmesh stuff*/
CustomData_MeshMasks lastDataMask;
- unsigned char (*derivedVertColor)[4];
- int derivedVertColorLen;
- unsigned char (*derivedFaceColor)[4];
- int derivedFaceColorLen;
/*selection mode*/
short selectmode;
short mat_nr;
- /* Object this editmesh came from (if it came from one) */
- struct Object *ob;
-
/*temp variables for x-mirror editing*/
int mirror_cdlayer; /* -1 is invalid */
@@ -96,20 +90,14 @@ BMEditMesh *BKE_editmesh_from_object(struct Object *ob);
void BKE_editmesh_free_derivedmesh(BMEditMesh *em);
void BKE_editmesh_free(BMEditMesh *em);
-void BKE_editmesh_color_free(BMEditMesh *em);
-void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype);
+float (*BKE_editmesh_vert_coords_alloc(struct Depsgraph *depsgraph,
+ struct BMEditMesh *em,
+ struct Scene *scene,
+ struct Object *ob,
+ int *r_vert_len))[3];
float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3];
-void BKE_editmesh_lnorspace_update(BMEditMesh *em);
-void BKE_editmesh_ensure_autosmooth(BMEditMesh *em);
+void BKE_editmesh_lnorspace_update(BMEditMesh *em, struct Mesh *me);
+void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, struct Mesh *me);
struct BoundBox *BKE_editmesh_cage_boundbox_get(BMEditMesh *em);
-/* editderivedmesh.c */
-/* should really be defined in editmesh.c, but they use 'EditDerivedBMesh' */
-void BKE_editmesh_statvis_calc(BMEditMesh *em,
- struct EditMeshData *emd,
- const struct MeshStatVis *statvis);
-
-float (*BKE_editmesh_vert_coords_alloc(
- struct Depsgraph *depsgraph, struct BMEditMesh *em, struct Scene *scene, int *r_vert_len))[3];
-
#endif /* __BKE_EDITMESH_H__ */
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 426e0ed4b0e..405b052f477 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -107,6 +107,7 @@ bool driver_get_variable_property(struct ChannelDriver *driver,
int *r_index);
bool BKE_driver_has_simple_expression(struct ChannelDriver *driver);
+bool BKE_driver_expression_depends_on_time(struct ChannelDriver *driver);
void BKE_driver_invalidate_expression(struct ChannelDriver *driver,
bool expr_changed,
bool varname_changed);
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 94c2a94d420..2b02895043f 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -83,6 +83,8 @@ void IDP_FreeString(struct IDProperty *prop) ATTR_NONNULL();
typedef void (*IDPWalkFunc)(void *userData, IDProperty *idp);
+void IDP_AssignID(IDProperty *prop, ID *id, const int flag);
+
/*-------- Group Functions -------*/
/** Sync values from one group to another, only where they match */
diff --git a/source/blender/blenkernel/BKE_lightprobe.h b/source/blender/blenkernel/BKE_lightprobe.h
index bd442c97000..153ad9bb915 100644
--- a/source/blender/blenkernel/BKE_lightprobe.h
+++ b/source/blender/blenkernel/BKE_lightprobe.h
@@ -29,6 +29,7 @@ struct LightProbe;
struct Main;
void BKE_lightprobe_init(struct LightProbe *probe);
+void BKE_lightprobe_type_set(struct LightProbe *probe, const short lightprobe_type);
void *BKE_lightprobe_add(struct Main *bmain, const char *name);
void BKE_lightprobe_copy_data(struct Main *bmain,
struct LightProbe *probe_dst,
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 90afec54561..570541eb990 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -177,7 +177,6 @@ int BKE_mesh_nurbs_displist_to_mdata(struct Object *ob,
void BKE_mesh_from_nurbs_displist(struct Main *bmain,
struct Object *ob,
struct ListBase *dispbase,
- const bool use_orco_uv,
const char *obdata_name,
bool temporary);
void BKE_mesh_from_nurbs(struct Main *bmain, struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 11f151af44d..b599e1e1b2c 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -545,7 +545,8 @@ void nodeRemoveNode(struct Main *bmain,
struct bNode *BKE_node_copy_ex(struct bNodeTree *ntree,
const struct bNode *node_src,
- const int flag);
+ const int flag,
+ const bool unique_name);
/* Same as BKE_node_copy_ex() but stores pointers to a new node and its sockets in the source
* node.
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index ec6ec027810..54cd172655e 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -66,7 +66,6 @@ void BKE_object_free_curve_cache(struct Object *ob);
void BKE_object_free(struct Object *ob);
void BKE_object_free_derived_caches(struct Object *ob);
-void BKE_object_free_derived_mesh_caches(struct Object *ob);
void BKE_object_free_caches(struct Object *object);
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index fdd3bd7cd86..db35fbde2c8 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -85,19 +85,33 @@ typedef enum ePaintMode {
#define PAINT_MODE_HAS_BRUSH(mode) !ELEM(mode, PAINT_MODE_SCULPT_UV)
/* overlay invalidation */
-typedef enum eOverlayControlFlags {
+typedef enum ePaintOverlayControlFlags {
PAINT_OVERLAY_INVALID_TEXTURE_PRIMARY = 1,
PAINT_OVERLAY_INVALID_TEXTURE_SECONDARY = (1 << 2),
PAINT_OVERLAY_INVALID_CURVE = (1 << 3),
PAINT_OVERLAY_OVERRIDE_CURSOR = (1 << 4),
PAINT_OVERLAY_OVERRIDE_PRIMARY = (1 << 5),
PAINT_OVERLAY_OVERRIDE_SECONDARY = (1 << 6),
-} eOverlayControlFlags;
+} ePaintOverlayControlFlags;
#define PAINT_OVERRIDE_MASK \
(PAINT_OVERLAY_OVERRIDE_SECONDARY | PAINT_OVERLAY_OVERRIDE_PRIMARY | \
PAINT_OVERLAY_OVERRIDE_CURSOR)
+/* Defines 8 areas resulting of splitting the object space by the XYZ axis planes. This is used to
+ * flip or mirror transform values depending on where the vertex is and where the transform
+ * operation started to support XYZ symmetry on those operations in a predictable way. */
+
+#define PAINT_SYMM_AREA_DEFAULT 0
+
+typedef enum ePaintSymmetryAreas {
+ PAINT_SYMM_AREA_X = (1 << 0),
+ PAINT_SYMM_AREA_Y = (1 << 1),
+ PAINT_SYMM_AREA_Z = (1 << 2),
+} ePaintSymmetryAreas;
+
+#define PAINT_SYMM_AREAS 8
+
void BKE_paint_invalidate_overlay_tex(struct Scene *scene,
struct ViewLayer *view_layer,
const struct Tex *tex);
@@ -105,8 +119,8 @@ void BKE_paint_invalidate_cursor_overlay(struct Scene *scene,
struct ViewLayer *view_layer,
struct CurveMapping *curve);
void BKE_paint_invalidate_overlay_all(void);
-eOverlayControlFlags BKE_paint_get_overlay_flags(void);
-void BKE_paint_reset_overlay_invalid(eOverlayControlFlags flag);
+ePaintOverlayControlFlags BKE_paint_get_overlay_flags(void);
+void BKE_paint_reset_overlay_invalid(ePaintOverlayControlFlags flag);
void BKE_paint_set_overlay_override(enum eOverlayFlags flag);
/* palettes */
@@ -211,6 +225,29 @@ struct SculptVertexPaintGeomMap {
struct MeshElemMap *vert_to_poly;
};
+/* Pose Brush IK Chain */
+typedef struct SculptPoseIKChainSegment {
+ float orig[3];
+ float head[3];
+
+ float initial_orig[3];
+ float initial_head[3];
+ float len;
+ float rot[4];
+ float *weights;
+
+ /* Store a 4x4 transform matrix for each of the possible combinations of enabled XYZ symmetry
+ * axis. */
+ float trans_mat[PAINT_SYMM_AREAS][4][4];
+ float pivot_mat[PAINT_SYMM_AREAS][4][4];
+ float pivot_mat_inv[PAINT_SYMM_AREAS][4][4];
+} SculptPoseIKChainSegment;
+
+typedef struct SculptPoseIKChain {
+ SculptPoseIKChainSegment *segments;
+ int tot_segments;
+} SculptPoseIKChain;
+
/* Session data (mode-specific) */
typedef struct SculptSession {
@@ -273,7 +310,10 @@ typedef struct SculptSession {
/* Dynamic mesh preview */
int *preview_vert_index_list;
int preview_vert_index_count;
+
+ /* Pose Brush Preview */
float pose_origin[3];
+ SculptPoseIKChain *pose_ik_chain_preview;
/* Transform operator */
float pivot_pos[3];
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 006915d6c45..d73e40291a0 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -173,6 +173,8 @@ bool BKE_scene_uses_blender_eevee(const struct Scene *scene);
bool BKE_scene_uses_blender_workbench(const struct Scene *scene);
bool BKE_scene_uses_cycles(const struct Scene *scene);
+void BKE_scene_copy_data_eevee(struct Scene *sce_dst, const struct Scene *sce_src);
+
void BKE_scene_disable_color_management(struct Scene *scene);
bool BKE_scene_check_color_management_enabled(const struct Scene *scene);
bool BKE_scene_check_rigidbody_active(const struct Scene *scene);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 770318883c0..bc312c7bb2b 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -208,6 +208,7 @@ struct SeqEffectHandle {
*
* sequencer render functions
* ********************************************************************** */
+double BKE_sequencer_rendersize_to_scale_factor(int size);
struct ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int chanshown);
struct ImBuf *BKE_sequencer_give_ibuf_threaded(const SeqRenderData *context,
@@ -412,7 +413,10 @@ bool BKE_sequence_base_shuffle_ex(struct ListBase *seqbasep,
bool BKE_sequence_base_shuffle(struct ListBase *seqbasep,
struct Sequence *test,
struct Scene *evil_scene);
-bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, struct Scene *evil_scene);
+bool BKE_sequence_base_shuffle_time(ListBase *seqbasep,
+ struct Scene *evil_scene,
+ ListBase *markers,
+ const bool use_sync_markers);
bool BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase);
void BKE_sequencer_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, bool for_render);
struct Sequence *BKE_sequence_dupli_recursive(const struct Scene *scene_src,
@@ -503,6 +507,7 @@ enum {
SEQ_SIDE_LEFT,
SEQ_SIDE_RIGHT,
SEQ_SIDE_BOTH,
+ SEQ_SIDE_NO_CHANGE,
};
int BKE_sequencer_find_next_prev_edit(struct Scene *scene,
int cfra,
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
index cd48e4d7f3b..70aa028a2c7 100644
--- a/source/blender/blenkernel/BKE_subsurf.h
+++ b/source/blender/blenkernel/BKE_subsurf.h
@@ -58,7 +58,7 @@ typedef enum {
struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm,
struct SubsurfModifierData *smd,
- struct Scene *scene,
+ const struct Scene *scene,
float (*vertCos)[3],
SubsurfFlags flags);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index cd03f80d9ec..2885495c3b0 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -105,8 +105,8 @@ set(SRC
intern/data_transfer.c
intern/deform.c
intern/displist.c
+ intern/displist_tangent.c
intern/dynamicpaint.c
- intern/editderivedmesh.c
intern/editlattice.c
intern/editmesh.c
intern/editmesh_bvh.c
@@ -272,6 +272,7 @@ set(SRC
BKE_data_transfer.h
BKE_deform.h
BKE_displist.h
+ BKE_displist_tangent.h
BKE_dynamicpaint.h
BKE_editlattice.h
BKE_editmesh.h
@@ -424,6 +425,10 @@ if(WITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
)
+ list(APPEND LIB
+ ${AUDASPACE_C_LIBRARIES}
+ ${AUDASPACE_PY_LIBRARIES}
+ )
endif()
if(WITH_BULLET)
@@ -436,6 +441,8 @@ if(WITH_BULLET)
list(APPEND LIB
bf_intern_rigidbody
extern_bullet
+
+ ${BULLET_LIBRARIES}
)
add_definitions(-DWITH_BULLET)
endif()
@@ -490,6 +497,9 @@ if(WITH_CODEC_FFMPEG)
list(APPEND INC_SYS
${FFMPEG_INCLUDE_DIRS}
)
+ list(APPEND LIB
+ ${FFMPEG_LIBRARIES}
+ )
add_definitions(-DWITH_FFMPEG)
remove_strict_c_flags_file(
@@ -543,6 +553,9 @@ if(WITH_LZO)
list(APPEND INC_SYS
${LZO_INCLUDE_DIR}
)
+ list(APPEND LIB
+ ${LZO_LIBRARIES}
+ )
add_definitions(-DWITH_SYSTEM_LZO)
else()
list(APPEND INC_SYS
@@ -573,6 +586,9 @@ if(WITH_FFTW3)
list(APPEND INC_SYS
${FFTW3_INCLUDE_DIRS}
)
+ list(APPEND LIB
+ ${FFTW3_LIBRARIES}
+ )
add_definitions(-DFFTW3=1)
endif()
@@ -599,6 +615,9 @@ if(WITH_OPENSUBDIV)
list(APPEND INC_SYS
${OPENSUBDIV_INCLUDE_DIRS}
)
+ list(APPEND LIB
+ ${OPENSUBDIV_LIBRARIES}
+ )
add_definitions(-DWITH_OPENSUBDIV)
endif()
@@ -634,6 +653,9 @@ if(WITH_TBB)
list(APPEND INC_SYS
${TBB_INCLUDE_DIRS}
)
+ list(APPEND LIB
+ ${TBB_LIBRARIES}
+ )
endif()
# # Warnings as errors, this is too strict!
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 8be7a947a67..f9e7627a8dd 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -789,14 +789,6 @@ static void add_orco_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orc
}
}
-static void editmesh_update_statvis_color(const Scene *scene, Object *ob)
-{
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- Mesh *me = ob->data;
- BKE_mesh_runtime_ensure_edit_data(me);
- BKE_editmesh_statvis_calc(em, me->runtime.edit_data, &scene->toolsettings->statvis);
-}
-
static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
const CustomData_MeshMasks *final_datamask,
const bool sculpt_dyntopo,
@@ -1494,7 +1486,6 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* Modifier evaluation modes. */
const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
- const bool do_init_statvis = false; /* FIXME: use V3D_OVERLAY_EDIT_STATVIS. */
/* Modifier evaluation contexts for different types of modifiers. */
const ModifierEvalContext mectx = {depsgraph, ob, MOD_APPLY_USECACHE};
@@ -1703,22 +1694,12 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
else if (!deformed_verts && mesh_cage) {
/* cage should already have up to date normals */
mesh_final = mesh_cage;
-
- /* In this case, we should never have weight-modifying modifiers in stack... */
- if (do_init_statvis) {
- editmesh_update_statvis_color(scene, ob);
- }
}
else {
/* this is just a copy of the editmesh, no need to calc normals */
mesh_final = BKE_mesh_from_editmesh_with_coords_thin_wrap(
em_input, &final_datamask, deformed_verts, mesh_input);
deformed_verts = NULL;
-
- /* In this case, we should never have weight-modifying modifiers in stack... */
- if (do_init_statvis) {
- editmesh_update_statvis_color(scene, ob);
- }
}
if (deformed_verts) {
@@ -1858,7 +1839,7 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph,
BMEditMesh *em,
CustomData_MeshMasks *dataMask)
{
- BLI_assert(em->ob->id.tag & LIB_TAG_COPIED_ON_WRITE);
+ BLI_assert(obedit->id.tag & LIB_TAG_COPIED_ON_WRITE);
BKE_object_free_derived_caches(obedit);
if (DEG_is_active(depsgraph)) {
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 32420e2e894..be6622e5d42 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -1665,11 +1665,11 @@ void BKE_keyingsets_free(ListBase *list)
/* ***************************************** */
/* Evaluation Data-Setting Backend */
-static bool animsys_store_rna_setting(PointerRNA *ptr,
- /* typically 'fcu->rna_path', 'fcu->array_index' */
- const char *rna_path,
- const int array_index,
- PathResolvedRNA *r_result)
+bool BKE_animsys_store_rna_setting(PointerRNA *ptr,
+ /* typically 'fcu->rna_path', 'fcu->array_index' */
+ const char *rna_path,
+ const int array_index,
+ PathResolvedRNA *r_result)
{
bool success = false;
const char *path = rna_path;
@@ -1880,7 +1880,7 @@ static void animsys_write_orig_anim_rna(PointerRNA *ptr,
}
PathResolvedRNA orig_anim_rna;
/* TODO(sergey): Should be possible to cache resolved path in dependency graph somehow. */
- if (animsys_store_rna_setting(&ptr_orig, rna_path, array_index, &orig_anim_rna)) {
+ if (BKE_animsys_store_rna_setting(&ptr_orig, rna_path, array_index, &orig_anim_rna)) {
BKE_animsys_write_rna_setting(&orig_anim_rna, value);
}
}
@@ -1910,7 +1910,7 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr,
continue;
}
PathResolvedRNA anim_rna;
- if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
BKE_animsys_write_rna_setting(&anim_rna, curval);
if (flush_to_original) {
@@ -1944,7 +1944,7 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime
* NOTE: for 'layering' option later on, we should check if we should remove old value
* before adding new to only be done when drivers only changed. */
PathResolvedRNA anim_rna;
- if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
ok = BKE_animsys_write_rna_setting(&anim_rna, curval);
}
@@ -2023,7 +2023,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *
/* check if this curve should be skipped */
if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0 && !BKE_fcurve_is_empty(fcu)) {
PathResolvedRNA anim_rna;
- if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
BKE_animsys_write_rna_setting(&anim_rna, curval);
}
@@ -3803,7 +3803,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
/* for each override, simply execute... */
for (aor = adt->overrides.first; aor; aor = aor->next) {
PathResolvedRNA anim_rna;
- if (animsys_store_rna_setting(ptr, aor->rna_path, aor->array_index, &anim_rna)) {
+ if (BKE_animsys_store_rna_setting(ptr, aor->rna_path, aor->array_index, &anim_rna)) {
BKE_animsys_write_rna_setting(&anim_rna, aor->value);
}
}
@@ -4125,7 +4125,7 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, int driver_index, FCu
// printf("\told val = %f\n", fcu->curval);
PathResolvedRNA anim_rna;
- if (animsys_store_rna_setting(&id_ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ if (BKE_animsys_store_rna_setting(&id_ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
/* Evaluate driver, and write results to COW-domain destination */
const float ctime = DEG_get_ctime(depsgraph);
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index c588ee80c78..e4da10797ff 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -2293,13 +2293,17 @@ void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll)
* If vec is the Y vector from purely rotational mat, result should be exact. */
void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll)
{
- float vecmat[3][3], vecmatinv[3][3], rollmat[3][3];
+ float vecmat[3][3], vecmatinv[3][3], rollmat[3][3], q[4];
+ /* Compute the orientation relative to the vector with zero roll. */
vec_roll_to_mat3(vec, 0.0f, vecmat);
invert_m3_m3(vecmatinv, vecmat);
mul_m3_m3m3(rollmat, vecmatinv, mat);
- *r_roll = atan2f(rollmat[2][0], rollmat[2][2]);
+ /* Extract the twist angle as the roll value. */
+ mat3_to_quat(q, rollmat);
+
+ *r_roll = quat_split_swing_and_twist(q, 1, NULL, NULL);
}
/* Calculates the rest matrix of a bone based on its vector and a roll around that vector. */
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index 7c12747283c..cd950e05415 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -73,7 +73,7 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu, bContext *C)
G.fileflags |= G_FILE_NO_UI;
if (UNDO_DISK) {
- success = BKE_blendfile_read(C, mfu->filename, NULL, 0);
+ success = BKE_blendfile_read(C, mfu->filename, &(const struct BlendFileReadParams){0}, NULL);
}
else {
success = BKE_blendfile_read_from_memfile(
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index b5f2ca0f117..721eb9a2a37 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -893,9 +893,11 @@ void BKE_brush_debug_print_state(Brush *br)
BR_TEST(add_col[0], f);
BR_TEST(add_col[1], f);
BR_TEST(add_col[2], f);
+ BR_TEST(add_col[3], f);
BR_TEST(sub_col[0], f);
BR_TEST(sub_col[1], f);
BR_TEST(sub_col[2], f);
+ BR_TEST(sub_col[3], f);
printf("\n");
@@ -926,7 +928,7 @@ void BKE_brush_sculpt_reset(Brush *br)
br->curve_preset = BRUSH_CURVE_POW4;
br->spacing = 5;
break;
- case SCULPT_TOOL_TOPOLOGY:
+ case SCULPT_TOOL_SLIDE_RELAX:
br->spacing = 10;
br->alpha = 1.0f;
break;
@@ -990,6 +992,7 @@ void BKE_brush_sculpt_reset(Brush *br)
break;
case SCULPT_TOOL_POSE:
br->pose_smooth_iterations = 4;
+ br->pose_ik_segments = 1;
br->flag &= ~BRUSH_ALPHA_PRESSURE;
br->flag &= ~BRUSH_SPACE;
br->flag &= ~BRUSH_SPACE_ATTEN;
@@ -1006,6 +1009,11 @@ void BKE_brush_sculpt_reset(Brush *br)
}
/* Cursor colors */
+
+ /* Default Alpha */
+ br->add_col[3] = 0.90f;
+ br->sub_col[3] = 0.90f;
+
switch (br->sculpt_tool) {
case SCULPT_TOOL_DRAW:
case SCULPT_TOOL_DRAW_SHARP:
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index c26800aefba..7332c3e0d43 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -190,22 +190,36 @@ static BVHTree *bvhtree_build_from_cloth(ClothModifierData *clmd, float epsilon)
vt = cloth->tri;
/* in the moment, return zero if no faces there */
- if (!cloth->tri_num) {
+ if (!cloth->primitive_num) {
return NULL;
}
/* create quadtree with k=26 */
- bvhtree = BLI_bvhtree_new(cloth->tri_num, epsilon, 4, 26);
+ bvhtree = BLI_bvhtree_new(cloth->primitive_num, epsilon, 4, 26);
/* fill tree */
- for (i = 0; i < cloth->tri_num; i++, vt++) {
- float co[3][3];
+ if (clmd->hairdata == NULL) {
+ for (i = 0; i < cloth->primitive_num; i++, vt++) {
+ float co[3][3];
- copy_v3_v3(co[0], verts[vt->tri[0]].xold);
- copy_v3_v3(co[1], verts[vt->tri[1]].xold);
- copy_v3_v3(co[2], verts[vt->tri[2]].xold);
+ copy_v3_v3(co[0], verts[vt->tri[0]].xold);
+ copy_v3_v3(co[1], verts[vt->tri[1]].xold);
+ copy_v3_v3(co[2], verts[vt->tri[2]].xold);
- BLI_bvhtree_insert(bvhtree, i, co[0], 3);
+ BLI_bvhtree_insert(bvhtree, i, co[0], 3);
+ }
+ }
+ else {
+ MEdge *edges = cloth->edges;
+
+ for (i = 0; i < cloth->primitive_num; i++) {
+ float co[2][3];
+
+ copy_v3_v3(co[0], verts[edges[i].v1].xold);
+ copy_v3_v3(co[1], verts[edges[i].v2].xold);
+
+ BLI_bvhtree_insert(bvhtree, i, co[0], 2);
+ }
}
/* balance tree */
@@ -222,6 +236,8 @@ void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving, bool self)
ClothVertex *verts = cloth->verts;
const MVertTri *vt;
+ BLI_assert(!(clmd->hairdata != NULL && self));
+
if (self) {
bvhtree = cloth->bvhselftree;
}
@@ -236,39 +252,59 @@ void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving, bool self)
vt = cloth->tri;
/* update vertex position in bvh tree */
- if (verts && vt) {
- for (i = 0; i < cloth->tri_num; i++, vt++) {
- float co[3][3], co_moving[3][3];
- bool ret;
-
- /* copy new locations into array */
- if (moving) {
- copy_v3_v3(co[0], verts[vt->tri[0]].txold);
- copy_v3_v3(co[1], verts[vt->tri[1]].txold);
- copy_v3_v3(co[2], verts[vt->tri[2]].txold);
-
- /* update moving positions */
- copy_v3_v3(co_moving[0], verts[vt->tri[0]].tx);
- copy_v3_v3(co_moving[1], verts[vt->tri[1]].tx);
- copy_v3_v3(co_moving[2], verts[vt->tri[2]].tx);
-
- ret = BLI_bvhtree_update_node(bvhtree, i, co[0], co_moving[0], 3);
- }
- else {
- copy_v3_v3(co[0], verts[vt->tri[0]].tx);
- copy_v3_v3(co[1], verts[vt->tri[1]].tx);
- copy_v3_v3(co[2], verts[vt->tri[2]].tx);
+ if (clmd->hairdata == NULL) {
+ if (verts && vt) {
+ for (i = 0; i < cloth->primitive_num; i++, vt++) {
+ float co[3][3], co_moving[3][3];
+ bool ret;
+
+ /* copy new locations into array */
+ if (moving) {
+ copy_v3_v3(co[0], verts[vt->tri[0]].txold);
+ copy_v3_v3(co[1], verts[vt->tri[1]].txold);
+ copy_v3_v3(co[2], verts[vt->tri[2]].txold);
+
+ /* update moving positions */
+ copy_v3_v3(co_moving[0], verts[vt->tri[0]].tx);
+ copy_v3_v3(co_moving[1], verts[vt->tri[1]].tx);
+ copy_v3_v3(co_moving[2], verts[vt->tri[2]].tx);
+
+ ret = BLI_bvhtree_update_node(bvhtree, i, co[0], co_moving[0], 3);
+ }
+ else {
+ copy_v3_v3(co[0], verts[vt->tri[0]].tx);
+ copy_v3_v3(co[1], verts[vt->tri[1]].tx);
+ copy_v3_v3(co[2], verts[vt->tri[2]].tx);
- ret = BLI_bvhtree_update_node(bvhtree, i, co[0], NULL, 3);
- }
+ ret = BLI_bvhtree_update_node(bvhtree, i, co[0], NULL, 3);
+ }
- /* check if tree is already full */
- if (ret == false) {
- break;
+ /* check if tree is already full */
+ if (ret == false) {
+ break;
+ }
}
+
+ BLI_bvhtree_update_tree(bvhtree);
}
+ }
+ else {
+ if (verts) {
+ MEdge *edges = cloth->edges;
+
+ for (i = 0; i < cloth->primitive_num; i++) {
+ float co[2][3];
- BLI_bvhtree_update_tree(bvhtree);
+ copy_v3_v3(co[0], verts[edges[i].v1].tx);
+ copy_v3_v3(co[1], verts[edges[i].v2].tx);
+
+ if (!BLI_bvhtree_update_node(bvhtree, i, co[0], NULL, 2)) {
+ break;
+ }
+ }
+
+ BLI_bvhtree_update_tree(bvhtree);
+ }
}
}
@@ -900,7 +936,13 @@ static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh)
}
/* save face information */
- clmd->clothObject->tri_num = looptri_num;
+ if (clmd->hairdata == NULL) {
+ clmd->clothObject->primitive_num = looptri_num;
+ }
+ else {
+ clmd->clothObject->primitive_num = mesh->totedge;
+ }
+
clmd->clothObject->tri = MEM_mallocN(sizeof(MVertTri) * looptri_num, "clothLoopTris");
if (clmd->clothObject->tri == NULL) {
cloth_free_modifier(clmd);
@@ -910,6 +952,8 @@ static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh)
}
BKE_mesh_runtime_verttri_from_looptri(clmd->clothObject->tri, mloop, looptri, looptri_num);
+ clmd->clothObject->edges = mesh->medge;
+
/* Free the springs since they can't be correct if the vertices
* changed.
*/
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index ed306dfa4df..0014fd3e7c0 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -1065,6 +1065,11 @@ bool BKE_collection_child_add(Main *bmain, Collection *parent, Collection *child
return true;
}
+bool BKE_collection_child_add_no_sync(Collection *parent, Collection *child)
+{
+ return collection_child_add(parent, child, 0, true);
+}
+
bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *child)
{
if (!collection_child_remove(parent, child)) {
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 91d66e16dde..5db42618a9e 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -33,6 +33,7 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_task.h"
#include "BLI_threads.h"
@@ -77,9 +78,11 @@ typedef struct SelfColDetectData {
***********************************/
/* step is limited from 0 (frame start position) to 1 (frame end position) */
-void collision_move_object(CollisionModifierData *collmd, float step, float prevstep)
+void collision_move_object(CollisionModifierData *collmd,
+ const float step,
+ const float prevstep,
+ const bool moving_bvh)
{
- float oldx[3];
unsigned int i = 0;
/* the collider doesn't move this frame */
@@ -92,13 +95,17 @@ void collision_move_object(CollisionModifierData *collmd, float step, float prev
}
for (i = 0; i < collmd->mvert_num; i++) {
- interp_v3_v3v3(oldx, collmd->x[i].co, collmd->xnew[i].co, prevstep);
- interp_v3_v3v3(collmd->current_x[i].co, collmd->x[i].co, collmd->xnew[i].co, step);
- sub_v3_v3v3(collmd->current_v[i].co, collmd->current_x[i].co, oldx);
+ interp_v3_v3v3(collmd->current_x[i].co, collmd->x[i].co, collmd->xnew[i].co, prevstep);
+ interp_v3_v3v3(collmd->current_xnew[i].co, collmd->x[i].co, collmd->xnew[i].co, step);
+ sub_v3_v3v3(collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co);
}
- bvhtree_update_from_mvert(
- collmd->bvhtree, collmd->current_x, NULL, collmd->tri, collmd->tri_num, false);
+ bvhtree_update_from_mvert(collmd->bvhtree,
+ collmd->current_xnew,
+ collmd->current_x,
+ collmd->tri,
+ collmd->tri_num,
+ moving_bvh);
}
BVHTree *bvhtree_build_from_mvert(const MVert *mvert,
@@ -187,17 +194,17 @@ BLI_INLINE int next_ind(int i)
return (++i < 3) ? i : 0;
}
-static float compute_collision_point(float a1[3],
- const float a2[3],
- const float a3[3],
- const float b1[3],
- const float b2[3],
- const float b3[3],
- bool culling,
- bool use_normal,
- float r_a[3],
- float r_b[3],
- float r_vec[3])
+static float compute_collision_point_tri_tri(const float a1[3],
+ const float a2[3],
+ const float a3[3],
+ const float b1[3],
+ const float b2[3],
+ const float b3[3],
+ bool culling,
+ bool use_normal,
+ float r_a[3],
+ float r_b[3],
+ float r_vec[3])
{
float a[3][3];
float b[3][3];
@@ -417,6 +424,179 @@ static float compute_collision_point(float a1[3],
return dist;
}
+static float compute_collision_point_edge_tri(const float a1[3],
+ const float a2[3],
+ const float b1[3],
+ const float b2[3],
+ const float b3[3],
+ bool culling,
+ bool use_normal,
+ float r_a[3],
+ float r_b[3],
+ float r_vec[3])
+{
+ float a[2][3];
+ float b[3][3];
+ float dist = FLT_MAX;
+ float tmp_co1[3], tmp_co2[3];
+ float isect_a[3];
+ bool isect = false;
+ float tmp, tmp_vec[3];
+ float normal[3], cent[3];
+ bool backside = false;
+
+ copy_v3_v3(a[0], a1);
+ copy_v3_v3(a[1], a2);
+
+ copy_v3_v3(b[0], b1);
+ copy_v3_v3(b[1], b2);
+ copy_v3_v3(b[2], b3);
+
+ normal_tri_v3(normal, b[0], b[1], b[2]);
+
+ /* Find intersection. */
+ if (isect_line_segment_tri_v3(a[0], a[1], b[0], b[1], b[2], &tmp, NULL)) {
+ interp_v3_v3v3(isect_a, a[0], a[1], tmp);
+ isect = true;
+ }
+
+ /* Determine collision side. */
+ if (culling) {
+ if (isect) {
+ backside = true;
+ }
+ else {
+ mid_v3_v3v3v3(cent, b[0], b[1], b[2]);
+
+ for (int i = 0; i < 2; i++) {
+ sub_v3_v3v3(tmp_vec, a[i], cent);
+ if (dot_v3v3(tmp_vec, normal) < 0.0f) {
+ backside = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (isect) {
+ /* Edge intersection. */
+ copy_v3_v3(r_a, isect_a);
+ copy_v3_v3(r_b, isect_a);
+
+ copy_v3_v3(r_vec, normal);
+
+ return 0.0f;
+ }
+
+ if (backside) {
+ float maxdist = 0.0f;
+ bool found = false;
+
+ /* Point projections. */
+ for (int i = 0; i < 2; i++) {
+ if (isect_ray_tri_v3(a[i], normal, b[0], b[1], b[2], &tmp, NULL)) {
+ if (tmp > maxdist) {
+ maxdist = tmp;
+ copy_v3_v3(r_a, a[i]);
+ madd_v3_v3v3fl(r_b, a[i], normal, tmp);
+ found = true;
+ }
+ }
+ }
+
+ /* Edge projections. */
+ for (int i = 0; i < 3; i++) {
+ float dir[3];
+
+ sub_v3_v3v3(tmp_vec, b[next_ind(i)], b[i]);
+ cross_v3_v3v3(dir, tmp_vec, normal);
+
+ if (isect_line_plane_v3(tmp_co1, a[0], a[1], b[i], dir) &&
+ point_in_slice_seg(tmp_co1, a[0], a[1]) &&
+ point_in_slice_seg(tmp_co1, b[i], b[next_ind(i)])) {
+ closest_to_line_v3(tmp_co2, tmp_co1, b[i], b[next_ind(i)]);
+ sub_v3_v3v3(tmp_vec, tmp_co1, tmp_co2);
+ tmp = len_v3(tmp_vec);
+
+ if ((tmp > maxdist) && (dot_v3v3(tmp_vec, normal) < 0.0f)) {
+ maxdist = tmp;
+ copy_v3_v3(r_a, tmp_co1);
+ copy_v3_v3(r_b, tmp_co2);
+ found = true;
+ }
+ }
+ }
+
+ /* If no point is found, will fallback onto regular proximity test below. */
+ if (found) {
+ sub_v3_v3v3(r_vec, r_b, r_a);
+
+ if (use_normal) {
+ if (dot_v3v3(normal, r_vec) >= 0.0f) {
+ copy_v3_v3(r_vec, normal);
+ }
+ else {
+ negate_v3_v3(r_vec, normal);
+ }
+ }
+
+ return 0.0f;
+ }
+ }
+
+ /* Closest point. */
+ for (int i = 0; i < 2; i++) {
+ closest_on_tri_to_point_v3(tmp_co1, a[i], b[0], b[1], b[2]);
+ tmp = len_squared_v3v3(tmp_co1, a[i]);
+
+ if (tmp < dist) {
+ dist = tmp;
+ copy_v3_v3(r_a, a[i]);
+ copy_v3_v3(r_b, tmp_co1);
+ }
+ }
+
+ /* Closest edge. */
+ if (!isect) {
+ for (int j = 0; j < 3; j++) {
+ isect_seg_seg_v3(a[0], a[1], b[j], b[next_ind(j)], tmp_co1, tmp_co2);
+ tmp = len_squared_v3v3(tmp_co1, tmp_co2);
+
+ if (tmp < dist) {
+ dist = tmp;
+ copy_v3_v3(r_a, tmp_co1);
+ copy_v3_v3(r_b, tmp_co2);
+ }
+ }
+ }
+
+ if (isect) {
+ sub_v3_v3v3(r_vec, r_b, r_a);
+ dist = 0.0f;
+ }
+ else {
+ sub_v3_v3v3(r_vec, r_a, r_b);
+ dist = sqrtf(dist);
+ }
+
+ if (culling && use_normal) {
+ copy_v3_v3(r_vec, normal);
+ }
+ else if (use_normal) {
+ if (dot_v3v3(normal, r_vec) >= 0.0f) {
+ copy_v3_v3(r_vec, normal);
+ }
+ else {
+ negate_v3_v3(r_vec, normal);
+ }
+ }
+ else if (culling && (dot_v3v3(r_vec, normal) < 0.0f)) {
+ return FLT_MAX;
+ }
+
+ return dist;
+}
+
// w3 is not perfect
static void collision_compute_barycentric(
const float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3)
@@ -488,6 +668,7 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
float v1[3], v2[3], relativeVelocity[3];
float magrelVel;
float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree);
+ const bool is_hair = (clmd->hairdata != NULL);
cloth1 = clmd->clothObject;
@@ -503,32 +684,41 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
continue;
}
- /* Compute barycentric coordinates for both collision points. */
- collision_compute_barycentric(collpair->pa,
- cloth1->verts[collpair->ap1].tx,
- cloth1->verts[collpair->ap2].tx,
- cloth1->verts[collpair->ap3].tx,
- &w1,
- &w2,
- &w3);
+ /* Compute barycentric coordinates and relative "velocity" for both collision points. */
+ if (is_hair) {
+ w2 = line_point_factor_v3(
+ collpair->pa, cloth1->verts[collpair->ap1].tx, cloth1->verts[collpair->ap2].tx);
+
+ w1 = 1.0f - w2;
+
+ interp_v3_v3v3(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, w2);
+ }
+ else {
+ collision_compute_barycentric(collpair->pa,
+ cloth1->verts[collpair->ap1].tx,
+ cloth1->verts[collpair->ap2].tx,
+ cloth1->verts[collpair->ap3].tx,
+ &w1,
+ &w2,
+ &w3);
+
+ collision_interpolateOnTriangle(v1,
+ cloth1->verts[collpair->ap1].tv,
+ cloth1->verts[collpair->ap2].tv,
+ cloth1->verts[collpair->ap3].tv,
+ w1,
+ w2,
+ w3);
+ }
collision_compute_barycentric(collpair->pb,
- collmd->current_x[collpair->bp1].co,
- collmd->current_x[collpair->bp2].co,
- collmd->current_x[collpair->bp3].co,
+ collmd->current_xnew[collpair->bp1].co,
+ collmd->current_xnew[collpair->bp2].co,
+ collmd->current_xnew[collpair->bp3].co,
&u1,
&u2,
&u3);
- /* Calculate relative "velocity". */
- collision_interpolateOnTriangle(v1,
- cloth1->verts[collpair->ap1].tv,
- cloth1->verts[collpair->ap2].tv,
- cloth1->verts[collpair->ap3].tv,
- w1,
- w2,
- w3);
-
collision_interpolateOnTriangle(v2,
collmd->current_v[collpair->bp1].co,
collmd->current_v[collpair->bp2].co,
@@ -570,7 +760,10 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
VECADDMUL(i1, vrel_t_pre, w1 * impulse);
VECADDMUL(i2, vrel_t_pre, w2 * impulse);
- VECADDMUL(i3, vrel_t_pre, w3 * impulse);
+
+ if (!is_hair) {
+ VECADDMUL(i3, vrel_t_pre, w3 * impulse);
+ }
}
/* Apply velocity stopping impulse. */
@@ -582,8 +775,10 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
VECADDMUL(i2, collpair->normal, w2 * impulse);
cloth1->verts[collpair->ap2].impulse_count++;
- VECADDMUL(i3, collpair->normal, w3 * impulse);
- cloth1->verts[collpair->ap3].impulse_count++;
+ if (!is_hair) {
+ VECADDMUL(i3, collpair->normal, w3 * impulse);
+ cloth1->verts[collpair->ap3].impulse_count++;
+ }
time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
@@ -603,7 +798,10 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
VECADDMUL(i1, collpair->normal, impulse);
VECADDMUL(i2, collpair->normal, impulse);
- VECADDMUL(i3, collpair->normal, impulse);
+
+ if (!is_hair) {
+ VECADDMUL(i3, collpair->normal, impulse);
+ }
}
result = 1;
@@ -621,11 +819,17 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
VECADDMUL(i1, collpair->normal, w1 * impulse);
VECADDMUL(i2, collpair->normal, w2 * impulse);
- VECADDMUL(i3, collpair->normal, w3 * impulse);
+
+ if (!is_hair) {
+ VECADDMUL(i3, collpair->normal, w3 * impulse);
+ }
cloth1->verts[collpair->ap1].impulse_count++;
cloth1->verts[collpair->ap2].impulse_count++;
- cloth1->verts[collpair->ap3].impulse_count++;
+
+ if (!is_hair) {
+ cloth1->verts[collpair->ap3].impulse_count++;
+ }
result = 1;
}
@@ -650,9 +854,11 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
cloth1->verts[collpair->ap2].impulse[j] = i2[j];
}
- if (cloth1->verts[collpair->ap3].impulse_count > 0 &&
- ABS(cloth1->verts[collpair->ap3].impulse[j]) < ABS(i3[j])) {
- cloth1->verts[collpair->ap3].impulse[j] = i3[j];
+ if (!is_hair) {
+ if (cloth1->verts[collpair->ap3].impulse_count > 0 &&
+ ABS(cloth1->verts[collpair->ap3].impulse[j]) < ABS(i3[j])) {
+ cloth1->verts[collpair->ap3].impulse[j] = i3[j];
+ }
}
}
}
@@ -869,17 +1075,17 @@ static void cloth_collision(void *__restrict userdata,
tri_b = &collmd->tri[data->overlap[index].indexB];
/* Compute distance and normal. */
- distance = compute_collision_point(verts1[tri_a->tri[0]].tx,
- verts1[tri_a->tri[1]].tx,
- verts1[tri_a->tri[2]].tx,
- collmd->current_x[tri_b->tri[0]].co,
- collmd->current_x[tri_b->tri[1]].co,
- collmd->current_x[tri_b->tri[2]].co,
- data->culling,
- data->use_normal,
- pa,
- pb,
- vect);
+ distance = compute_collision_point_tri_tri(verts1[tri_a->tri[0]].tx,
+ verts1[tri_a->tri[1]].tx,
+ verts1[tri_a->tri[2]].tx,
+ collmd->current_xnew[tri_b->tri[0]].co,
+ collmd->current_xnew[tri_b->tri[1]].co,
+ collmd->current_xnew[tri_b->tri[2]].co,
+ data->culling,
+ data->use_normal,
+ pa,
+ pb,
+ vect);
if ((distance <= (epsilon1 + epsilon2 + ALMOST_ZERO)) && (len_squared_v3(vect) > ALMOST_ZERO)) {
collpair[index].ap1 = tri_a->tri[0];
@@ -940,17 +1146,17 @@ static void cloth_selfcollision(void *__restrict userdata,
}
/* Compute distance and normal. */
- distance = compute_collision_point(verts1[tri_a->tri[0]].tx,
- verts1[tri_a->tri[1]].tx,
- verts1[tri_a->tri[2]].tx,
- verts1[tri_b->tri[0]].tx,
- verts1[tri_b->tri[1]].tx,
- verts1[tri_b->tri[2]].tx,
- false,
- false,
- pa,
- pb,
- vect);
+ distance = compute_collision_point_tri_tri(verts1[tri_a->tri[0]].tx,
+ verts1[tri_a->tri[1]].tx,
+ verts1[tri_a->tri[2]].tx,
+ verts1[tri_b->tri[0]].tx,
+ verts1[tri_b->tri[1]].tx,
+ verts1[tri_b->tri[2]].tx,
+ false,
+ false,
+ pa,
+ pb,
+ vect);
if ((distance <= (epsilon * 2.0f + ALMOST_ZERO)) && (len_squared_v3(vect) > ALMOST_ZERO)) {
collpair[index].ap1 = tri_a->tri[0];
@@ -977,6 +1183,64 @@ static void cloth_selfcollision(void *__restrict userdata,
}
}
+static void hair_collision(void *__restrict userdata,
+ const int index,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ ColDetectData *data = (ColDetectData *)userdata;
+
+ ClothModifierData *clmd = data->clmd;
+ CollisionModifierData *collmd = data->collmd;
+ CollPair *collpair = data->collisions;
+ const MVertTri *tri_coll;
+ const MEdge *edge_coll;
+ ClothVertex *verts1 = clmd->clothObject->verts;
+ float distance = 0.0f;
+ float epsilon1 = clmd->coll_parms->epsilon;
+ float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree);
+ float pa[3], pb[3], vect[3];
+
+ /* TODO: This is not efficient. Might be wise to instead build an array before iterating, to
+ * avoid walking the list every time. */
+ edge_coll = &clmd->clothObject->edges[data->overlap[index].indexA];
+ tri_coll = &collmd->tri[data->overlap[index].indexB];
+
+ /* Compute distance and normal. */
+ distance = compute_collision_point_edge_tri(verts1[edge_coll->v1].tx,
+ verts1[edge_coll->v2].tx,
+ collmd->current_x[tri_coll->tri[0]].co,
+ collmd->current_x[tri_coll->tri[1]].co,
+ collmd->current_x[tri_coll->tri[2]].co,
+ data->culling,
+ data->use_normal,
+ pa,
+ pb,
+ vect);
+
+ if ((distance <= (epsilon1 + epsilon2 + ALMOST_ZERO)) && (len_squared_v3(vect) > ALMOST_ZERO)) {
+ collpair[index].ap1 = edge_coll->v1;
+ collpair[index].ap2 = edge_coll->v2;
+
+ collpair[index].bp1 = tri_coll->tri[0];
+ collpair[index].bp2 = tri_coll->tri[1];
+ collpair[index].bp3 = tri_coll->tri[2];
+
+ copy_v3_v3(collpair[index].pa, pa);
+ copy_v3_v3(collpair[index].pb, pb);
+ copy_v3_v3(collpair[index].vector, vect);
+
+ normalize_v3_v3(collpair[index].normal, collpair[index].vector);
+
+ collpair[index].distance = distance;
+ collpair[index].flag = 0;
+
+ data->collided = true;
+ }
+ else {
+ collpair[index].flag = COLLISION_INACTIVE;
+ }
+}
+
static void add_collision_object(ListBase *relations,
Object *ob,
int level,
@@ -1117,7 +1381,7 @@ ListBase *BKE_collider_cache_create(Depsgraph *depsgraph, Object *self, Collecti
col->ob = ob;
col->collmd = cmd;
/* make sure collider is properly set up */
- collision_move_object(cmd, 1.0, 0.0);
+ collision_move_object(cmd, 1.0, 0.0, true);
BLI_addtail(cache, col);
}
}
@@ -1142,6 +1406,7 @@ static bool cloth_bvh_objcollisions_nearcheck(ClothModifierData *clmd,
bool culling,
bool use_normal)
{
+ const bool is_hair = (clmd->hairdata != NULL);
*collisions = (CollPair *)MEM_mallocN(sizeof(CollPair) * numresult, "collision array");
ColDetectData data = {
@@ -1157,7 +1422,8 @@ static bool cloth_bvh_objcollisions_nearcheck(ClothModifierData *clmd,
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = true;
- BLI_task_parallel_range(0, numresult, &data, cloth_collision, &settings);
+ BLI_task_parallel_range(
+ 0, numresult, &data, is_hair ? hair_collision : cloth_collision, &settings);
return data.collided;
}
@@ -1302,8 +1568,14 @@ int cloth_bvh_collision(
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
bvhtree_update_from_cloth(clmd, false, false);
- collobjs = BKE_collision_objects_create(
- depsgraph, ob, clmd->coll_parms->group, &numcollobj, eModifierType_Collision);
+ /* Enable self collision if this is a hair sim */
+ const bool is_hair = (clmd->hairdata != NULL);
+
+ collobjs = BKE_collision_objects_create(depsgraph,
+ is_hair ? NULL : ob,
+ clmd->coll_parms->group,
+ &numcollobj,
+ eModifierType_Collision);
if (collobjs) {
coll_counts_obj = MEM_callocN(sizeof(uint) * numcollobj, "CollCounts");
@@ -1319,7 +1591,7 @@ int cloth_bvh_collision(
}
/* Move object to position (step) in time. */
- collision_move_object(collmd, step + dt, step);
+ collision_move_object(collmd, step + dt, step, false);
overlap_obj[i] = BLI_bvhtree_overlap(
cloth_bvh, collmd->bvhtree, &coll_counts_obj[i], NULL, NULL);
@@ -1468,286 +1740,3 @@ void collision_get_collider_velocity(float vel_old[3],
/* XXX assume constant velocity of the collider for now */
copy_v3_v3(vel_old, vel_new);
}
-
-BLI_INLINE bool cloth_point_face_collision_params(const float p1[3],
- const float p2[3],
- const float v0[3],
- const float v1[3],
- const float v2[3],
- float r_nor[3],
- float *r_lambda,
- float r_w[3])
-{
- float edge1[3], edge2[3], p2face[3], p1p2[3], v0p2[3];
- float nor_v0p2, nor_p1p2;
-
- sub_v3_v3v3(edge1, v1, v0);
- sub_v3_v3v3(edge2, v2, v0);
- cross_v3_v3v3(r_nor, edge1, edge2);
- normalize_v3(r_nor);
-
- sub_v3_v3v3(v0p2, p2, v0);
- nor_v0p2 = dot_v3v3(v0p2, r_nor);
- madd_v3_v3v3fl(p2face, p2, r_nor, -nor_v0p2);
- interp_weights_tri_v3(r_w, v0, v1, v2, p2face);
-
- sub_v3_v3v3(p1p2, p2, p1);
- nor_p1p2 = dot_v3v3(p1p2, r_nor);
- *r_lambda = (nor_p1p2 != 0.0f ? nor_v0p2 / nor_p1p2 : 0.0f);
-
- return r_w[1] >= 0.0f && r_w[2] >= 0.0f && r_w[1] + r_w[2] <= 1.0f;
-}
-
-static CollPair *cloth_point_collpair(float p1[3],
- const float p2[3],
- const MVert *mverts,
- int bp1,
- int bp2,
- int bp3,
- int index_cloth,
- int index_coll,
- float epsilon,
- CollPair *collpair)
-{
- const float *co1 = mverts[bp1].co, *co2 = mverts[bp2].co, *co3 = mverts[bp3].co;
- float lambda /*, distance1 */, distance2;
- float facenor[3], v1p1[3], v1p2[3];
- float w[3];
-
- if (!cloth_point_face_collision_params(p1, p2, co1, co2, co3, facenor, &lambda, w)) {
- return collpair;
- }
-
- sub_v3_v3v3(v1p1, p1, co1);
- // distance1 = dot_v3v3(v1p1, facenor);
- sub_v3_v3v3(v1p2, p2, co1);
- distance2 = dot_v3v3(v1p2, facenor);
- // if (distance2 > epsilon || (distance1 < 0.0f && distance2 < 0.0f))
- if (distance2 > epsilon) {
- return collpair;
- }
-
- collpair->face1 = index_cloth; /* XXX actually not a face, but equivalent index for point */
- collpair->face2 = index_coll;
- collpair->ap1 = index_cloth;
- collpair->ap2 = collpair->ap3 = -1; /* unused */
- collpair->bp1 = bp1;
- collpair->bp2 = bp2;
- collpair->bp3 = bp3;
-
- /* note: using the second point here, which is
- * the current updated position that needs to be corrected
- */
- copy_v3_v3(collpair->pa, p2);
- collpair->distance = distance2;
- mul_v3_v3fl(collpair->vector, facenor, -distance2);
-
- interp_v3_v3v3v3(collpair->pb, co1, co2, co3, w);
-
- copy_v3_v3(collpair->normal, facenor);
- collpair->time = lambda;
- collpair->flag = 0;
-
- collpair++;
- return collpair;
-}
-
-/* Determines collisions on overlap,
- * collisions are written to collpair[i] and collision+number_collision_found is returned. */
-static CollPair *cloth_point_collision(ModifierData *md1,
- ModifierData *md2,
- BVHTreeOverlap *overlap,
- float epsilon,
- CollPair *collpair,
- float UNUSED(dt))
-{
- ClothModifierData *clmd = (ClothModifierData *)md1;
- CollisionModifierData *collmd = (CollisionModifierData *)md2;
- /* Cloth *cloth = clmd->clothObject; */ /* UNUSED */
- ClothVertex *vert = NULL;
- const MVertTri *vt;
- const MVert *mverts = collmd->current_x;
-
- vert = &clmd->clothObject->verts[overlap->indexA];
- vt = &collmd->tri[overlap->indexB];
-
- collpair = cloth_point_collpair(vert->tx,
- vert->x,
- mverts,
- vt->tri[0],
- vt->tri[1],
- vt->tri[2],
- overlap->indexA,
- overlap->indexB,
- epsilon,
- collpair);
-
- return collpair;
-}
-
-static void cloth_points_objcollisions_nearcheck(ClothModifierData *clmd,
- CollisionModifierData *collmd,
- CollPair **collisions,
- CollPair **collisions_index,
- int numresult,
- BVHTreeOverlap *overlap,
- float epsilon,
- double dt)
-{
- int i;
-
- /* can return 2 collisions in total */
- *collisions = (CollPair *)MEM_mallocN(sizeof(CollPair) * numresult * 2, "collision array");
- *collisions_index = *collisions;
-
- for (i = 0; i < numresult; i++) {
- *collisions_index = cloth_point_collision(
- (ModifierData *)clmd, (ModifierData *)collmd, overlap + i, epsilon, *collisions_index, dt);
- }
-}
-
-void cloth_find_point_contacts(Depsgraph *depsgraph,
- Object *ob,
- ClothModifierData *clmd,
- float step,
- float dt,
- ColliderContacts **r_collider_contacts,
- int *r_totcolliders)
-{
- Cloth *cloth = clmd->clothObject;
- BVHTree *cloth_bvh;
- unsigned int i = 0, mvert_num = 0;
- ClothVertex *verts = NULL;
-
- ColliderContacts *collider_contacts;
-
- Object **collobjs = NULL;
- unsigned int numcollobj = 0;
-
- verts = cloth->verts;
- mvert_num = cloth->mvert_num;
-
- ////////////////////////////////////////////////////////////
- // static collisions
- ////////////////////////////////////////////////////////////
-
- /* Check we do have collision objects to test against, before doing anything else. */
- collobjs = BKE_collision_objects_create(
- depsgraph, ob, clmd->coll_parms->group, &numcollobj, eModifierType_Collision);
- if (!collobjs) {
- *r_collider_contacts = NULL;
- *r_totcolliders = 0;
- return;
- }
-
- // create temporary cloth points bvh
- cloth_bvh = BLI_bvhtree_new(mvert_num, clmd->coll_parms->epsilon, 4, 6);
- /* fill tree */
- for (i = 0; i < mvert_num; i++) {
- float co[6];
-
- copy_v3_v3(&co[0 * 3], verts[i].x);
- copy_v3_v3(&co[1 * 3], verts[i].tx);
-
- BLI_bvhtree_insert(cloth_bvh, i, co, 2);
- }
- /* balance tree */
- BLI_bvhtree_balance(cloth_bvh);
-
- /* move object to position (step) in time */
- for (i = 0; i < numcollobj; i++) {
- Object *collob = collobjs[i];
- CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(
- collob, eModifierType_Collision);
- if (!collmd->bvhtree) {
- continue;
- }
-
- /* move object to position (step) in time */
- collision_move_object(collmd, step + dt, step);
- }
-
- collider_contacts = MEM_callocN(sizeof(ColliderContacts) * numcollobj, "CollPair");
-
- // check all collision objects
- for (i = 0; i < numcollobj; i++) {
- ColliderContacts *ct = collider_contacts + i;
- Object *collob = collobjs[i];
- CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(
- collob, eModifierType_Collision);
- BVHTreeOverlap *overlap;
- unsigned int result = 0;
- float epsilon;
-
- ct->ob = collob;
- ct->collmd = collmd;
- ct->collisions = NULL;
- ct->totcollisions = 0;
-
- if (!collmd->bvhtree) {
- continue;
- }
-
- /* search for overlapping collision pairs */
- overlap = BLI_bvhtree_overlap(cloth_bvh, collmd->bvhtree, &result, NULL, NULL);
- epsilon = BLI_bvhtree_get_epsilon(collmd->bvhtree);
-
- // go to next object if no overlap is there
- if (result && overlap) {
- CollPair *collisions_index;
-
- /* check if collisions really happen (costly near check) */
- cloth_points_objcollisions_nearcheck(
- clmd, collmd, &ct->collisions, &collisions_index, result, overlap, epsilon, dt);
- ct->totcollisions = (int)(collisions_index - ct->collisions);
-
- /* Resolve nearby collisions. */
-#if 0
- ret += cloth_points_objcollisions_resolve(
- clmd, collmd, collob->pd, collisions[i], collisions_index[i], dt);
-#endif
- }
-
- if (overlap) {
- MEM_freeN(overlap);
- }
- }
-
- BKE_collision_objects_free(collobjs);
-
- BLI_bvhtree_free(cloth_bvh);
-
- ////////////////////////////////////////////////////////////
- // update positions
- // this is needed for bvh_calc_DOP_hull_moving() [kdop.c]
- ////////////////////////////////////////////////////////////
-
- // verts come from clmd
- for (i = 0; i < mvert_num; i++) {
- if (clmd->sim_parms->vgroup_mass > 0) {
- if (verts[i].flags & CLOTH_VERT_FLAG_PINNED) {
- continue;
- }
- }
-
- add_v3_v3v3(verts[i].tx, verts[i].txold, verts[i].tv);
- }
- ////////////////////////////////////////////////////////////
-
- *r_collider_contacts = collider_contacts;
- *r_totcolliders = numcollobj;
-}
-
-void cloth_free_contacts(ColliderContacts *collider_contacts, int totcolliders)
-{
- if (collider_contacts) {
- int i;
- for (i = 0; i < totcolliders; i++) {
- ColliderContacts *ct = collider_contacts + i;
- if (ct->collisions) {
- MEM_freeN(ct->collisions);
- }
- }
- MEM_freeN(collider_contacts);
- }
-}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index c397fbcf115..a17a09297c5 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -2062,36 +2062,21 @@ static void translike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
bConstraintTarget *ct = targets->first;
if (VALID_CONS_TARGET(ct)) {
- if (data->mix_mode == TRANSLIKE_MIX_REPLACE) {
- /* just copy the entire transform matrix of the target */
- copy_m4_m4(cob->matrix, ct->matrix);
- }
- else {
- float old_loc[3], old_rot[3][3], old_size[3];
- float new_loc[3], new_rot[3][3], new_size[3];
-
- /* Separate matrices so they can be combined in a way that avoids shear. */
- mat4_to_loc_rot_size(old_loc, old_rot, old_size, cob->matrix);
- mat4_to_loc_rot_size(new_loc, new_rot, new_size, ct->matrix);
-
- switch (data->mix_mode) {
- case TRANSLIKE_MIX_BEFORE:
- mul_v3_m4v3(new_loc, ct->matrix, old_loc);
- mul_m3_m3m3(new_rot, new_rot, old_rot);
- mul_v3_v3(new_size, old_size);
- break;
+ switch (data->mix_mode) {
+ case TRANSLIKE_MIX_REPLACE:
+ copy_m4_m4(cob->matrix, ct->matrix);
+ break;
- case TRANSLIKE_MIX_AFTER:
- mul_v3_m4v3(new_loc, cob->matrix, new_loc);
- mul_m3_m3m3(new_rot, old_rot, new_rot);
- mul_v3_v3(new_size, old_size);
- break;
+ case TRANSLIKE_MIX_BEFORE:
+ mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix);
+ break;
- default:
- BLI_assert(false);
- }
+ case TRANSLIKE_MIX_AFTER:
+ mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix);
+ break;
- loc_rot_size_to_mat4(cob->matrix, new_loc, new_rot, new_size);
+ default:
+ BLI_assert(!"Unknown Copy Transforms mix mode");
}
}
}
@@ -2555,6 +2540,9 @@ static void actcon_new_data(void *cdata)
/* set type to 20 (Loc X), as 0 is Rot X for backwards compatibility */
data->type = 20;
+
+ /* Set the mix mode to After Original with anti-shear scale handling. */
+ data->mix_mode = ACTCON_MIX_AFTER;
}
static void actcon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
@@ -2695,18 +2683,28 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
}
}
-static void actcon_evaluate(bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets)
+static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
{
+ bActionConstraint *data = con->data;
bConstraintTarget *ct = targets->first;
if (VALID_CONS_TARGET(ct)) {
- float temp[4][4];
+ switch (data->mix_mode) {
+ case ACTCON_MIX_BEFORE:
+ mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix);
+ break;
- /* Nice and simple... we just need to multiply the matrices, as the get_target_matrix
- * function has already taken care of everything else.
- */
- copy_m4_m4(temp, cob->matrix);
- mul_m4_m4m4(cob->matrix, temp, ct->matrix);
+ case ACTCON_MIX_AFTER:
+ mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix);
+ break;
+
+ case ACTCON_MIX_AFTER_FULL:
+ mul_m4_m4m4(cob->matrix, cob->matrix, ct->matrix);
+ break;
+
+ default:
+ BLI_assert(!"Unknown Action mix mode");
+ }
}
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 12bb7b573bd..4f0ff8bdcd3 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -1805,91 +1805,88 @@ void BKE_curve_bevel_make(Object *ob, ListBase *disp)
}
}
else {
- short dnr;
-
- /* bevel now in three parts, for proper vertex normals */
- /* part 1, back */
-
- if ((cu->flag & CU_BACK) || !(cu->flag & CU_FRONT)) {
- dnr = nr = 2 + cu->bevresol;
- if ((cu->flag & (CU_FRONT | CU_BACK)) == 0) {
- nr = 3 + 2 * cu->bevresol;
- }
- dl = MEM_callocN(sizeof(DispList), "makebevelcurve p1");
- dl->verts = MEM_malloc_arrayN(nr, sizeof(float[3]), "makebevelcurve p1");
- BLI_addtail(disp, dl);
- dl->type = DL_SEGM;
- dl->parts = 1;
- dl->flag = DL_BACK_CURVE;
- dl->nr = nr;
-
- /* half a circle */
- fp = dl->verts;
- dangle = ((float)M_PI_2 / (dnr - 1));
- angle = -(nr - 1) * dangle;
-
- for (a = 0; a < nr; a++) {
+ /* The general case for nonzero extrusion or an incomplete loop. */
+ dl = MEM_callocN(sizeof(DispList), "makebevelcurve");
+ if ((cu->flag & (CU_FRONT | CU_BACK)) == 0) {
+ /* The full loop. */
+ nr = 4 * cu->bevresol + 6;
+ dl->flag = DL_FRONT_CURVE | DL_BACK_CURVE;
+ }
+ else if ((cu->flag & CU_FRONT) && (cu->flag & CU_BACK)) {
+ /* Half the loop. */
+ nr = 2 * (cu->bevresol + 1) + ((cu->ext1 == 0.0f) ? 1 : 2);
+ dl->flag = DL_FRONT_CURVE | DL_BACK_CURVE;
+ }
+ else {
+ /* One quarter of the loop (just front or back). */
+ nr = (cu->ext1 == 0.0f) ? cu->bevresol + 2 : cu->bevresol + 3;
+ dl->flag = (cu->flag & CU_FRONT) ? DL_FRONT_CURVE : DL_BACK_CURVE;
+ }
+
+ dl->verts = MEM_malloc_arrayN(nr, sizeof(float[3]), "makebevelcurve");
+ BLI_addtail(disp, dl);
+ /* Use a different type depending on whether the loop is complete or not. */
+ dl->type = ((cu->flag & (CU_FRONT | CU_BACK)) == 0) ? DL_POLY : DL_SEGM;
+ dl->parts = 1;
+ dl->nr = nr;
+
+ fp = dl->verts;
+ dangle = (float)M_PI_2 / (cu->bevresol + 1);
+ angle = 0.0;
+
+ /* Build the back section. */
+ if (cu->flag & CU_BACK || !(cu->flag & CU_FRONT)) {
+ angle = (float)M_PI_2 * 3.0f;
+ for (a = 0; a < cu->bevresol + 2; a++) {
fp[0] = 0.0;
fp[1] = (float)(cosf(angle) * (cu->ext2));
fp[2] = (float)(sinf(angle) * (cu->ext2)) - cu->ext1;
angle += dangle;
fp += 3;
}
+ if ((cu->ext1 != 0.0f) && !(cu->flag & CU_FRONT) && (cu->flag & CU_BACK)) {
+ /* Add the extrusion if we're only building the back. */
+ fp[0] = 0.0;
+ fp[1] = cu->ext2;
+ fp[2] = cu->ext1;
+ }
}
- /* part 2, sidefaces */
- if (cu->ext1 != 0.0f) {
- nr = 2;
-
- dl = MEM_callocN(sizeof(DispList), "makebevelcurve p2");
- dl->verts = MEM_malloc_arrayN(nr, sizeof(float[3]), "makebevelcurve p2");
- BLI_addtail(disp, dl);
- dl->type = DL_SEGM;
- dl->parts = 1;
- dl->nr = nr;
-
- fp = dl->verts;
- fp[1] = cu->ext2;
- fp[2] = -cu->ext1;
- fp[4] = cu->ext2;
- fp[5] = cu->ext1;
-
- if ((cu->flag & (CU_FRONT | CU_BACK)) == 0) {
- dl = MEM_dupallocN(dl);
- dl->verts = MEM_dupallocN(dl->verts);
- BLI_addtail(disp, dl);
-
- fp = dl->verts;
- fp[1] = -fp[1];
- fp[2] = -fp[2];
- fp[4] = -fp[4];
- fp[5] = -fp[5];
+ /* Build the front section. */
+ if (cu->flag & CU_FRONT || !(cu->flag & CU_BACK)) {
+ if ((cu->ext1 != 0.0f) && !(cu->flag & CU_BACK) && (cu->flag & CU_FRONT)) {
+ /* Add the extrusion if we're only building the back. */
+ fp[0] = 0.0;
+ fp[1] = cu->ext2;
+ fp[2] = -cu->ext1;
+ fp += 3;
+ }
+ /* Don't duplicate the last back vertex. */
+ angle = (cu->ext1 == 0.0f && (cu->flag & CU_BACK)) ? dangle : 0;
+ for (a = 0; a < cu->bevresol + 2; a++) {
+ fp[0] = 0.0;
+ fp[1] = (float)(cosf(angle) * (cu->ext2));
+ fp[2] = (float)(sinf(angle) * (cu->ext2)) + cu->ext1;
+ angle += dangle;
+ fp += 3;
}
}
- /* part 3, front */
- if ((cu->flag & CU_FRONT) || !(cu->flag & CU_BACK)) {
- dnr = nr = 2 + cu->bevresol;
- if ((cu->flag & (CU_FRONT | CU_BACK)) == 0) {
- nr = 3 + 2 * cu->bevresol;
+ /* Build the other half only if we're building the full loop. */
+ if (!(cu->flag & (CU_FRONT | CU_BACK))) {
+ for (a = 0; a < cu->bevresol + 1; a++) {
+ fp[0] = 0.0;
+ fp[1] = (float)(cosf(angle) * (cu->ext2));
+ fp[2] = (float)(sinf(angle) * (cu->ext2)) + cu->ext1;
+ angle += dangle;
+ fp += 3;
}
- dl = MEM_callocN(sizeof(DispList), "makebevelcurve p3");
- dl->verts = MEM_malloc_arrayN(nr, sizeof(float[3]), "makebevelcurve p3");
- BLI_addtail(disp, dl);
- dl->type = DL_SEGM;
- dl->flag = DL_FRONT_CURVE;
- dl->parts = 1;
- dl->nr = nr;
-
- /* half a circle */
- fp = dl->verts;
- angle = 0.0;
- dangle = ((float)M_PI_2 / (dnr - 1));
- for (a = 0; a < nr; a++) {
+ angle = (float)M_PI;
+ for (a = 0; a < cu->bevresol + 1; a++) {
fp[0] = 0.0;
fp[1] = (float)(cosf(angle) * (cu->ext2));
- fp[2] = (float)(sinf(angle) * (cu->ext2)) + cu->ext1;
+ fp[2] = (float)(sinf(angle) * (cu->ext2)) - cu->ext1;
angle += dangle;
fp += 3;
}
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index a964cab3fa5..79dcdd15bf7 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -345,7 +345,7 @@ void defvert_normalize_lock_single(MDeformVert *dvert,
else if (dvert->totweight == 1) {
MDeformWeight *dw = dvert->dw;
if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
- if (def_nr_lock != 0) {
+ if (def_nr_lock != dw->def_nr) {
dw->weight = 1.0f;
}
}
diff --git a/source/blender/blenkernel/intern/displist_tangent.c b/source/blender/blenkernel/intern/displist_tangent.c
new file mode 100644
index 00000000000..4ac8d47feba
--- /dev/null
+++ b/source/blender/blenkernel/intern/displist_tangent.c
@@ -0,0 +1,279 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "BKE_displist.h"
+#include "BKE_displist_tangent.h"
+
+#include "MEM_guardedalloc.h"
+
+/* interface */
+#include "mikktspace.h"
+
+typedef struct {
+ const DispList *dl;
+ float (*tangent)[4]; /* destination */
+ /** Face normal for flat shading. */
+ float (*fnormals)[3];
+ /** Use by surfaces. Size of the surface in faces. */
+ int u_len, v_len;
+} SGLSLDisplistToTangent;
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name DL_INDEX3 tangents
+ * \{ */
+
+static int dl3_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+
+ return dlt->dl->parts;
+}
+
+static int dl3_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
+{
+ UNUSED_VARS(pContext, face_num);
+
+ return 3;
+}
+
+static void dl3_ts_GetPosition(const SMikkTSpaceContext *pContext,
+ float r_co[3],
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+ const float(*verts)[3] = (float(*)[3])dlt->dl->verts;
+ const int(*idx)[3] = (int(*)[3])dlt->dl->index;
+
+ copy_v3_v3(r_co, verts[idx[face_num][vert_index]]);
+}
+
+static void dl3_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext,
+ float r_uv[2],
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+ const int(*idx)[3] = (int(*)[3])dlt->dl->index;
+
+ r_uv[0] = idx[face_num][vert_index] / (float)(dlt->dl->nr - 1);
+ r_uv[1] = 0.0f;
+}
+
+static void dl3_ts_GetNormal(const SMikkTSpaceContext *pContext,
+ float r_no[3],
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+ UNUSED_VARS(face_num, vert_index);
+
+ copy_v3_v3(r_no, dlt->dl->nors);
+}
+
+static void dl3_ts_SetTSpace(const SMikkTSpaceContext *pContext,
+ const float fvTangent[3],
+ const float fSign,
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+ UNUSED_VARS(face_num, vert_index);
+
+ copy_v3_v3(dlt->tangent[0], fvTangent);
+ dlt->tangent[0][3] = fSign;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name DL_SURF tangents
+ * \{ */
+
+static int dlsurf_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+
+ return dlt->v_len * dlt->u_len;
+}
+
+static int dlsurf_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
+{
+ UNUSED_VARS(pContext, face_num);
+
+ return 4;
+}
+
+static int face_to_vert_index(SGLSLDisplistToTangent *dlt,
+ const int face_num,
+ const int vert_index)
+{
+ int u = face_num % dlt->u_len;
+ int v = face_num / dlt->u_len;
+
+ if (vert_index == 0) {
+ u += 1;
+ }
+ else if (vert_index == 1) {
+ u += 1;
+ v += 1;
+ }
+ else if (vert_index == 2) {
+ v += 1;
+ }
+
+ /* Cyclic correction. */
+ u = u % dlt->dl->nr;
+ v = v % dlt->dl->parts;
+
+ return v * dlt->dl->nr + u;
+}
+
+static void dlsurf_ts_GetPosition(const SMikkTSpaceContext *pContext,
+ float r_co[3],
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+ const float(*verts)[3] = (float(*)[3])dlt->dl->verts;
+
+ copy_v3_v3(r_co, verts[face_to_vert_index(dlt, face_num, vert_index)]);
+}
+
+static void dlsurf_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext,
+ float r_uv[2],
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+
+ int idx = face_to_vert_index(dlt, face_num, vert_index);
+
+ /* Note: For some reason the shading U and V are swapped compared to the
+ * one described in the surface format. */
+ r_uv[0] = (idx / dlt->dl->nr) / (float)(dlt->v_len);
+ r_uv[1] = (idx % dlt->dl->nr) / (float)(dlt->u_len);
+
+ if (r_uv[0] == 0.0f && ELEM(vert_index, 1, 2)) {
+ r_uv[0] = 1.0f;
+ }
+ if (r_uv[1] == 0.0f && ELEM(vert_index, 0, 1)) {
+ r_uv[1] = 1.0f;
+ }
+}
+
+static void dlsurf_ts_GetNormal(const SMikkTSpaceContext *pContext,
+ float r_no[3],
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+ const float(*nors)[3] = (float(*)[3])dlt->dl->nors;
+
+ if (dlt->fnormals) {
+ copy_v3_v3(r_no, dlt->fnormals[face_num]);
+ }
+ else {
+ copy_v3_v3(r_no, nors[face_to_vert_index(dlt, face_num, vert_index)]);
+ }
+}
+
+static void dlsurf_ts_SetTSpace(const SMikkTSpaceContext *pContext,
+ const float fvTangent[3],
+ const float fSign,
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+ UNUSED_VARS(face_num, vert_index);
+
+ float *r_tan = dlt->tangent[face_num * 4 + vert_index];
+ copy_v3_v3(r_tan, fvTangent);
+ r_tan[3] = fSign;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Entry point
+ * \{ */
+
+void BKE_displist_tangent_calc(const DispList *dl, float (*fnormals)[3], float (**r_tangent)[4])
+{
+ if (dl->type == DL_INDEX3) {
+ /* INDEX3 have only one tangent so we don't need actual allocation. */
+ BLI_assert(*r_tangent != NULL);
+
+ SGLSLDisplistToTangent mesh2tangent = {
+ .tangent = *r_tangent,
+ .dl = dl,
+ };
+ SMikkTSpaceContext sContext = {NULL};
+ SMikkTSpaceInterface sInterface = {NULL};
+ sContext.m_pUserData = &mesh2tangent;
+ sContext.m_pInterface = &sInterface;
+ sInterface.m_getNumFaces = dl3_ts_GetNumFaces;
+ sInterface.m_getNumVerticesOfFace = dl3_ts_GetNumVertsOfFace;
+ sInterface.m_getPosition = dl3_ts_GetPosition;
+ sInterface.m_getTexCoord = dl3_ts_GetTextureCoordinate;
+ sInterface.m_getNormal = dl3_ts_GetNormal;
+ sInterface.m_setTSpaceBasic = dl3_ts_SetTSpace;
+ /* 0 if failed */
+ genTangSpaceDefault(&sContext);
+ }
+ else if (dl->type == DL_SURF) {
+ SGLSLDisplistToTangent mesh2tangent = {
+ .dl = dl,
+ .u_len = dl->nr - ((dl->flag & DL_CYCL_U) ? 0 : 1),
+ .v_len = dl->parts - ((dl->flag & DL_CYCL_V) ? 0 : 1),
+ .fnormals = fnormals,
+ };
+
+ int loop_len = mesh2tangent.u_len * mesh2tangent.v_len * 4;
+
+ if (*r_tangent == NULL) {
+ *r_tangent = MEM_mallocN(sizeof(float[4]) * loop_len, "displist tangents");
+ }
+ mesh2tangent.tangent = *r_tangent;
+ SMikkTSpaceContext sContext = {NULL};
+ SMikkTSpaceInterface sInterface = {NULL};
+ sContext.m_pUserData = &mesh2tangent;
+ sContext.m_pInterface = &sInterface;
+ sInterface.m_getNumFaces = dlsurf_ts_GetNumFaces;
+ sInterface.m_getNumVerticesOfFace = dlsurf_ts_GetNumVertsOfFace;
+ sInterface.m_getPosition = dlsurf_ts_GetPosition;
+ sInterface.m_getTexCoord = dlsurf_ts_GetTextureCoordinate;
+ sInterface.m_getNormal = dlsurf_ts_GetNormal;
+ sInterface.m_setTSpaceBasic = dlsurf_ts_SetTSpace;
+ /* 0 if failed */
+ genTangSpaceDefault(&sContext);
+ }
+ else {
+ /* Unsupported. */
+ BLI_assert(0);
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 74a523bfbdc..a70e5b67a15 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -6285,7 +6285,11 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph,
PART_FLUID_SPRAY,
PART_FLUID_BUBBLE,
PART_FLUID_FOAM,
- PART_FLUID_TRACER) &&
+ PART_FLUID_TRACER,
+ PART_FLUID_SPRAYFOAM,
+ PART_FLUID_SPRAYBUBBLE,
+ PART_FLUID_FOAMBUBBLE,
+ PART_FLUID_SPRAYFOAMBUBBLE) &&
psys_check_enabled(brushObj, brush->psys, for_render)) {
/* Paint a particle system */
dynamicPaint_paintParticles(surface, brush->psys, brush, timescale);
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
deleted file mode 100644
index 2df3d2f0fe9..00000000000
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2005 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup bke
- *
- * basic design:
- *
- * the bmesh derivedmesh exposes the mesh as triangles. it stores pointers
- * to three loops per triangle. the derivedmesh stores a cache of tessellations
- * for each face. this cache will smartly update as needed (though at first
- * it'll simply be more brute force). keeping track of face/edge counts may
- * be a small problem.
- *
- * this won't be the most efficient thing, considering that internal edges and
- * faces of tessellations are exposed. looking up an edge by index in particular
- * is likely to be a little slow.
- */
-
-#include "atomic_ops.h"
-
-#include "BLI_math.h"
-#include "BLI_jitter_2d.h"
-#include "BLI_bitmap.h"
-#include "BLI_task.h"
-
-#include "BKE_cdderivedmesh.h"
-#include "BKE_deform.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_iterators.h"
-#include "BKE_editmesh.h"
-#include "BKE_editmesh_bvh.h"
-#include "BKE_editmesh_cache.h"
-#include "BKE_editmesh_tangent.h"
-
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
-
-#include "MEM_guardedalloc.h"
-
-/* -------------------------------------------------------------------- */
-/* StatVis Functions */
-
-static void axis_from_enum_v3(float v[3], const char axis)
-{
- zero_v3(v);
- if (axis < 3) {
- v[axis] = 1.0f;
- }
- else {
- v[axis - 3] = -1.0f;
- }
-}
-
-static void statvis_calc_overhang(BMEditMesh *em,
- const float (*polyNos)[3],
- /* values for calculating */
- const float min,
- const float max,
- const char axis,
- /* result */
- unsigned char (*r_face_colors)[4])
-{
- BMIter iter;
- BMesh *bm = em->bm;
- BMFace *f;
- float dir[3];
- int index;
- const float minmax_irange = 1.0f / (max - min);
- bool is_max;
-
- /* fallback */
- unsigned char col_fallback[4] = {64, 64, 64, 255}; /* gray */
- unsigned char col_fallback_max[4] = {0, 0, 0, 255}; /* max color */
-
- BLI_assert(min <= max);
-
- axis_from_enum_v3(dir, axis);
-
- if (LIKELY(em->ob)) {
- mul_transposed_mat3_m4_v3(em->ob->obmat, dir);
- normalize_v3(dir);
- }
-
- /* fallback max */
- {
- float fcol[3];
- BKE_defvert_weight_to_rgb(fcol, 1.0f);
- rgb_float_to_uchar(col_fallback_max, fcol);
- }
-
- /* now convert into global space */
- BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
- float fac = angle_normalized_v3v3(polyNos ? polyNos[index] : f->no, dir) / (float)M_PI;
-
- /* remap */
- if ((is_max = (fac <= max)) && (fac >= min)) {
- float fcol[3];
- fac = (fac - min) * minmax_irange;
- fac = 1.0f - fac;
- CLAMP(fac, 0.0f, 1.0f);
- BKE_defvert_weight_to_rgb(fcol, fac);
- rgb_float_to_uchar(r_face_colors[index], fcol);
- }
- else {
- const unsigned char *fallback = is_max ? col_fallback_max : col_fallback;
- copy_v4_v4_uchar(r_face_colors[index], fallback);
- }
- }
-}
-
-/* so we can use jitter values for face interpolation */
-static void uv_from_jitter_v2(float uv[2])
-{
- uv[0] += 0.5f;
- uv[1] += 0.5f;
- if (uv[0] + uv[1] > 1.0f) {
- uv[0] = 1.0f - uv[0];
- uv[1] = 1.0f - uv[1];
- }
-
- CLAMP(uv[0], 0.0f, 1.0f);
- CLAMP(uv[1], 0.0f, 1.0f);
-}
-
-static void statvis_calc_thickness(BMEditMesh *em,
- const float (*vertexCos)[3],
- /* values for calculating */
- const float min,
- const float max,
- const int samples,
- /* result */
- unsigned char (*r_face_colors)[4])
-{
- const float eps_offset = 0.00002f; /* values <= 0.00001 give errors */
- float *face_dists = (float *)r_face_colors; /* cheating */
- const bool use_jit = samples < 32;
- float jit_ofs[32][2];
- BMesh *bm = em->bm;
- const int tottri = em->tottri;
- const float minmax_irange = 1.0f / (max - min);
- int i;
-
- struct BMLoop *(*looptris)[3] = em->looptris;
-
- /* fallback */
- const unsigned char col_fallback[4] = {64, 64, 64, 255};
-
- struct BMBVHTree *bmtree;
-
- BLI_assert(min <= max);
-
- copy_vn_fl(face_dists, em->bm->totface, max);
-
- if (use_jit) {
- int j;
- BLI_assert(samples < 32);
- BLI_jitter_init(jit_ofs, samples);
-
- for (j = 0; j < samples; j++) {
- uv_from_jitter_v2(jit_ofs[j]);
- }
- }
-
- BM_mesh_elem_index_ensure(bm, BM_FACE);
- if (vertexCos) {
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- }
-
- bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
-
- for (i = 0; i < tottri; i++) {
- BMFace *f_hit;
- BMLoop **ltri = looptris[i];
- const int index = BM_elem_index_get(ltri[0]->f);
- const float *cos[3];
- float ray_co[3];
- float ray_no[3];
-
- if (vertexCos) {
- cos[0] = vertexCos[BM_elem_index_get(ltri[0]->v)];
- cos[1] = vertexCos[BM_elem_index_get(ltri[1]->v)];
- cos[2] = vertexCos[BM_elem_index_get(ltri[2]->v)];
- }
- else {
- cos[0] = ltri[0]->v->co;
- cos[1] = ltri[1]->v->co;
- cos[2] = ltri[2]->v->co;
- }
-
- normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
-
-#define FACE_RAY_TEST_ANGLE \
- f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, &dist, NULL, NULL); \
- if (f_hit && dist < face_dists[index]) { \
- float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no)); \
- angle_fac = 1.0f - angle_fac; \
- angle_fac = angle_fac * angle_fac * angle_fac; \
- angle_fac = 1.0f - angle_fac; \
- dist /= angle_fac; \
- if (dist < face_dists[index]) { \
- face_dists[index] = dist; \
- } \
- } \
- (void)0
-
- if (use_jit) {
- int j;
- for (j = 0; j < samples; j++) {
- float dist = face_dists[index];
- interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
- madd_v3_v3fl(ray_co, ray_no, eps_offset);
-
- FACE_RAY_TEST_ANGLE;
- }
- }
- else {
- float dist = face_dists[index];
- mid_v3_v3v3v3(ray_co, cos[0], cos[1], cos[2]);
- madd_v3_v3fl(ray_co, ray_no, eps_offset);
-
- FACE_RAY_TEST_ANGLE;
- }
- }
-
- BKE_bmbvh_free(bmtree);
-
- /* convert floats into color! */
- for (i = 0; i < bm->totface; i++) {
- float fac = face_dists[i];
-
- /* important not '<=' */
- if (fac < max) {
- float fcol[3];
- fac = (fac - min) * minmax_irange;
- fac = 1.0f - fac;
- CLAMP(fac, 0.0f, 1.0f);
- BKE_defvert_weight_to_rgb(fcol, fac);
- rgb_float_to_uchar(r_face_colors[i], fcol);
- }
- else {
- copy_v4_v4_uchar(r_face_colors[i], col_fallback);
- }
- }
-}
-
-static void statvis_calc_intersect(BMEditMesh *em,
- const float (*vertexCos)[3],
- /* result */
- unsigned char (*r_face_colors)[4])
-{
- BMesh *bm = em->bm;
- int i;
-
- /* fallback */
- // const char col_fallback[4] = {64, 64, 64, 255};
- float fcol[3];
- unsigned char col[3];
-
- struct BMBVHTree *bmtree;
- BVHTreeOverlap *overlap;
- unsigned int overlap_len;
-
- memset(r_face_colors, 64, sizeof(int) * em->bm->totface);
-
- BM_mesh_elem_index_ensure(bm, BM_FACE);
- if (vertexCos) {
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- }
-
- bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
-
- overlap = BKE_bmbvh_overlap(bmtree, bmtree, &overlap_len);
-
- /* same for all faces */
- BKE_defvert_weight_to_rgb(fcol, 1.0f);
- rgb_float_to_uchar(col, fcol);
-
- if (overlap) {
- for (i = 0; i < overlap_len; i++) {
- BMFace *f_hit_pair[2] = {
- em->looptris[overlap[i].indexA][0]->f,
- em->looptris[overlap[i].indexB][0]->f,
- };
- int j;
-
- for (j = 0; j < 2; j++) {
- BMFace *f_hit = f_hit_pair[j];
- int index;
-
- index = BM_elem_index_get(f_hit);
-
- copy_v3_v3_uchar(r_face_colors[index], col);
- }
- }
- MEM_freeN(overlap);
- }
-
- BKE_bmbvh_free(bmtree);
-}
-
-static void statvis_calc_distort(BMEditMesh *em,
- const float (*vertexCos)[3],
- const float (*polyNos)[3],
- /* values for calculating */
- const float min,
- const float max,
- /* result */
- unsigned char (*r_face_colors)[4])
-{
- BMIter iter;
- BMesh *bm = em->bm;
- BMFace *f;
- const float *f_no;
- int index;
- const float minmax_irange = 1.0f / (max - min);
-
- /* fallback */
- const unsigned char col_fallback[4] = {64, 64, 64, 255};
-
- /* now convert into global space */
- BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
- float fac;
-
- if (f->len == 3) {
- fac = -1.0f;
- }
- else {
- BMLoop *l_iter, *l_first;
- if (vertexCos) {
- f_no = polyNos[index];
- }
- else {
- f_no = f->no;
- }
-
- fac = 0.0f;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- float no_corner[3];
- if (vertexCos) {
- normal_tri_v3(no_corner,
- vertexCos[BM_elem_index_get(l_iter->prev->v)],
- vertexCos[BM_elem_index_get(l_iter->v)],
- vertexCos[BM_elem_index_get(l_iter->next->v)]);
- }
- else {
- BM_loop_calc_face_normal_safe(l_iter, no_corner);
- }
- /* simple way to detect (what is most likely) concave */
- if (dot_v3v3(f_no, no_corner) < 0.0f) {
- negate_v3(no_corner);
- }
- fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
- } while ((l_iter = l_iter->next) != l_first);
- fac *= 2.0f;
- }
-
- /* remap */
- if (fac >= min) {
- float fcol[3];
- fac = (fac - min) * minmax_irange;
- CLAMP(fac, 0.0f, 1.0f);
- BKE_defvert_weight_to_rgb(fcol, fac);
- rgb_float_to_uchar(r_face_colors[index], fcol);
- }
- else {
- copy_v4_v4_uchar(r_face_colors[index], col_fallback);
- }
- }
-}
-
-static void statvis_calc_sharp(BMEditMesh *em,
- const float (*vertexCos)[3],
- /* values for calculating */
- const float min,
- const float max,
- /* result */
- unsigned char (*r_vert_colors)[4])
-{
- float *vert_angles = (float *)r_vert_colors; /* cheating */
- BMIter iter;
- BMesh *bm = em->bm;
- BMEdge *e;
- // float f_no[3];
- const float minmax_irange = 1.0f / (max - min);
- int i;
-
- /* fallback */
- const unsigned char col_fallback[4] = {64, 64, 64, 255};
-
- (void)vertexCos; /* TODO */
-
- copy_vn_fl(vert_angles, em->bm->totvert, -M_PI);
-
- /* first assign float values to verts */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- float angle = BM_edge_calc_face_angle_signed(e);
- float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
- float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
- *col1 = max_ff(*col1, angle);
- *col2 = max_ff(*col2, angle);
- }
-
- /* convert floats into color! */
- for (i = 0; i < bm->totvert; i++) {
- float fac = vert_angles[i];
-
- /* important not '<=' */
- if (fac > min) {
- float fcol[3];
- fac = (fac - min) * minmax_irange;
- CLAMP(fac, 0.0f, 1.0f);
- BKE_defvert_weight_to_rgb(fcol, fac);
- rgb_float_to_uchar(r_vert_colors[i], fcol);
- }
- else {
- copy_v4_v4_uchar(r_vert_colors[i], col_fallback);
- }
- }
-}
-
-void BKE_editmesh_statvis_calc(BMEditMesh *em, EditMeshData *emd, const MeshStatVis *statvis)
-{
- switch (statvis->type) {
- case SCE_STATVIS_OVERHANG: {
- BKE_editmesh_color_ensure(em, BM_FACE);
- statvis_calc_overhang(em,
- emd ? emd->polyNos : NULL,
- statvis->overhang_min / (float)M_PI,
- statvis->overhang_max / (float)M_PI,
- statvis->overhang_axis,
- em->derivedFaceColor);
- break;
- }
- case SCE_STATVIS_THICKNESS: {
- const float scale = 1.0f / mat4_to_scale(em->ob->obmat);
- BKE_editmesh_color_ensure(em, BM_FACE);
- statvis_calc_thickness(em,
- emd ? emd->vertexCos : NULL,
- statvis->thickness_min * scale,
- statvis->thickness_max * scale,
- statvis->thickness_samples,
- em->derivedFaceColor);
- break;
- }
- case SCE_STATVIS_INTERSECT: {
- BKE_editmesh_color_ensure(em, BM_FACE);
- statvis_calc_intersect(em, emd ? emd->vertexCos : NULL, em->derivedFaceColor);
- break;
- }
- case SCE_STATVIS_DISTORT: {
- BKE_editmesh_color_ensure(em, BM_FACE);
-
- if (emd) {
- BKE_editmesh_cache_ensure_poly_normals(em, emd);
- }
-
- statvis_calc_distort(em,
- emd ? emd->vertexCos : NULL,
- emd ? emd->polyNos : NULL,
- statvis->distort_min,
- statvis->distort_max,
- em->derivedFaceColor);
- break;
- }
- case SCE_STATVIS_SHARP: {
- BKE_editmesh_color_ensure(em, BM_VERT);
- statvis_calc_sharp(em,
- emd ? emd->vertexCos : NULL,
- statvis->sharp_min,
- statvis->sharp_max,
- /* in this case they are vertex colors */
- em->derivedVertColor);
- break;
- }
- }
-}
-
-/* -------------------------------------------------------------------- */
-/* Editmesh Vert Coords */
-
-struct CageUserData {
- int totvert;
- float (*cos_cage)[3];
- BLI_bitmap *visit_bitmap;
-};
-
-static void cage_mapped_verts_callback(void *userData,
- int index,
- const float co[3],
- const float UNUSED(no_f[3]),
- const short UNUSED(no_s[3]))
-{
- struct CageUserData *data = userData;
-
- if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_TEST(data->visit_bitmap, index))) {
- BLI_BITMAP_ENABLE(data->visit_bitmap, index);
- copy_v3_v3(data->cos_cage[index], co);
- }
-}
-
-float (*BKE_editmesh_vert_coords_alloc(
- struct Depsgraph *depsgraph, BMEditMesh *em, Scene *scene, int *r_vert_len))[3]
-{
- Mesh *cage;
- BLI_bitmap *visit_bitmap;
- struct CageUserData data;
- float(*cos_cage)[3];
-
- cage = editbmesh_get_eval_cage(depsgraph, scene, em->ob, em, &CD_MASK_BAREMESH);
- cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
-
- /* when initializing cage verts, we only want the first cage coordinate for each vertex,
- * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
- visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
-
- data.totvert = em->bm->totvert;
- data.cos_cage = cos_cage;
- data.visit_bitmap = visit_bitmap;
-
- BKE_mesh_foreach_mapped_vert(cage, cage_mapped_verts_callback, &data, MESH_FOREACH_NOP);
-
- MEM_freeN(visit_bitmap);
-
- if (r_vert_len) {
- *r_vert_len = em->bm->totvert;
- }
-
- return cos_cage;
-}
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index b135574a650..9b67a4fb925 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -33,6 +33,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_library.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_iterators.h"
#include "BKE_object.h"
BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate)
@@ -55,11 +56,6 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em)
em_copy->mesh_eval_cage = em_copy->mesh_eval_final = NULL;
em_copy->bb_cage = NULL;
- em_copy->derivedVertColor = NULL;
- em_copy->derivedVertColorLen = 0;
- em_copy->derivedFaceColor = NULL;
- em_copy->derivedFaceColorLen = 0;
-
em_copy->bm = BM_mesh_copy(em->bm);
/* The tessellation is NOT calculated on the copy here,
@@ -163,8 +159,6 @@ void BKE_editmesh_free(BMEditMesh *em)
{
BKE_editmesh_free_derivedmesh(em);
- BKE_editmesh_color_free(em);
-
if (em->looptris) {
MEM_freeN(em->looptris);
}
@@ -174,44 +168,57 @@ void BKE_editmesh_free(BMEditMesh *em)
}
}
-void BKE_editmesh_color_free(BMEditMesh *em)
+struct CageUserData {
+ int totvert;
+ float (*cos_cage)[3];
+ BLI_bitmap *visit_bitmap;
+};
+
+static void cage_mapped_verts_callback(void *userData,
+ int index,
+ const float co[3],
+ const float UNUSED(no_f[3]),
+ const short UNUSED(no_s[3]))
{
- if (em->derivedVertColor) {
- MEM_freeN(em->derivedVertColor);
- }
- if (em->derivedFaceColor) {
- MEM_freeN(em->derivedFaceColor);
- }
- em->derivedVertColor = NULL;
- em->derivedFaceColor = NULL;
+ struct CageUserData *data = userData;
- em->derivedVertColorLen = 0;
- em->derivedFaceColorLen = 0;
+ if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_TEST(data->visit_bitmap, index))) {
+ BLI_BITMAP_ENABLE(data->visit_bitmap, index);
+ copy_v3_v3(data->cos_cage[index], co);
+ }
}
-void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype)
+float (*BKE_editmesh_vert_coords_alloc(struct Depsgraph *depsgraph,
+ BMEditMesh *em,
+ struct Scene *scene,
+ Object *ob,
+ int *r_vert_len))[3]
{
- switch (htype) {
- case BM_VERT:
- if (em->derivedVertColorLen != em->bm->totvert) {
- BKE_editmesh_color_free(em);
- em->derivedVertColor = MEM_mallocN(sizeof(*em->derivedVertColor) * em->bm->totvert,
- __func__);
- em->derivedVertColorLen = em->bm->totvert;
- }
- break;
- case BM_FACE:
- if (em->derivedFaceColorLen != em->bm->totface) {
- BKE_editmesh_color_free(em);
- em->derivedFaceColor = MEM_mallocN(sizeof(*em->derivedFaceColor) * em->bm->totface,
- __func__);
- em->derivedFaceColorLen = em->bm->totface;
- }
- break;
- default:
- BLI_assert(0);
- break;
+ Mesh *cage;
+ BLI_bitmap *visit_bitmap;
+ struct CageUserData data;
+ float(*cos_cage)[3];
+
+ cage = editbmesh_get_eval_cage(depsgraph, scene, ob, em, &CD_MASK_BAREMESH);
+ cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
+
+ /* when initializing cage verts, we only want the first cage coordinate for each vertex,
+ * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
+ visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
+
+ data.totvert = em->bm->totvert;
+ data.cos_cage = cos_cage;
+ data.visit_bitmap = visit_bitmap;
+
+ BKE_mesh_foreach_mapped_vert(cage, cage_mapped_verts_callback, &data, MESH_FOREACH_NOP);
+
+ MEM_freeN(visit_bitmap);
+
+ if (r_vert_len) {
+ *r_vert_len = em->bm->totvert;
}
+
+ return cos_cage;
}
float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3]
@@ -219,7 +226,7 @@ float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3]
return BM_mesh_vert_coords_alloc(em->bm, r_vert_len);
}
-void BKE_editmesh_lnorspace_update(BMEditMesh *em)
+void BKE_editmesh_lnorspace_update(BMEditMesh *em, Mesh *me)
{
BMesh *bm = em->bm;
@@ -231,7 +238,6 @@ void BKE_editmesh_lnorspace_update(BMEditMesh *em)
* with related sharp edges (and hence autosmooth is 'lost').
* Not sure how critical this is, and how to fix that issue? */
if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
- Mesh *me = em->ob->data;
if (me->flag & ME_AUTOSMOOTH) {
BM_edges_sharp_from_angle_set(bm, me->smoothresh);
}
@@ -241,12 +247,11 @@ void BKE_editmesh_lnorspace_update(BMEditMesh *em)
}
/* If autosmooth not already set, set it */
-void BKE_editmesh_ensure_autosmooth(BMEditMesh *em)
+void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, Mesh *me)
{
- Mesh *me = em->ob->data;
if (!(me->flag & ME_AUTOSMOOTH)) {
me->flag |= ME_AUTOSMOOTH;
- BKE_editmesh_lnorspace_update(em);
+ BKE_editmesh_lnorspace_update(em, me);
}
}
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 3876033eaaa..833b8409f7d 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1171,16 +1171,16 @@ void testhandles_fcurve(FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_ha
*/
void sort_time_fcurve(FCurve *fcu)
{
- bool ok = true;
/* keep adjusting order of beztriples until nothing moves (bubble-sort) */
- while (ok) {
- ok = 0;
+ if (fcu->bezt) {
+ BezTriple *bezt;
+ uint a;
- /* currently, will only be needed when there are beztriples */
- if (fcu->bezt) {
- BezTriple *bezt;
- unsigned int a;
+ bool ok = true;
+ while (ok) {
+ ok = 0;
+ /* currently, will only be needed when there are beztriples */
/* loop over ALL points to adjust position in array and recalculate handles */
for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) {
@@ -1191,20 +1191,22 @@ void sort_time_fcurve(FCurve *fcu)
SWAP(BezTriple, *bezt, *(bezt + 1));
ok = 1;
}
-
- /* if either one of both of the points exceeds crosses over the keyframe time... */
- if ((bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0])) {
- /* swap handles if they have switched sides for some reason */
- swap_v2_v2(bezt->vec[0], bezt->vec[2]);
- }
- else {
- /* clamp handles */
- CLAMP_MAX(bezt->vec[0][0], bezt->vec[1][0]);
- CLAMP_MIN(bezt->vec[2][0], bezt->vec[1][0]);
- }
}
}
}
+
+ for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) {
+ /* if either one of both of the points exceeds crosses over the keyframe time... */
+ if ((bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0])) {
+ /* swap handles if they have switched sides for some reason */
+ swap_v2_v2(bezt->vec[0], bezt->vec[2]);
+ }
+ else {
+ /* clamp handles */
+ CLAMP_MAX(bezt->vec[0][0], bezt->vec[1][0]);
+ CLAMP_MIN(bezt->vec[2][0], bezt->vec[1][0]);
+ }
+ }
}
}
@@ -2140,20 +2142,34 @@ ChannelDriver *fcurve_copy_driver(const ChannelDriver *driver)
/* Driver Expression Evaluation --------------- */
+/* Index constants for the expression parameter array. */
+enum {
+ /* Index of the 'frame' variable. */
+ VAR_INDEX_FRAME = 0,
+ /* Index of the first user-defined driver variable. */
+ VAR_INDEX_CUSTOM
+};
+
static ExprPyLike_Parsed *driver_compile_simple_expr_impl(ChannelDriver *driver)
{
/* Prepare parameter names. */
int names_len = BLI_listbase_count(&driver->variables);
- const char **names = BLI_array_alloca(names, names_len + 1);
- int i = 0;
+ const char **names = BLI_array_alloca(names, names_len + VAR_INDEX_CUSTOM);
+ int i = VAR_INDEX_CUSTOM;
- names[i++] = "frame";
+ names[VAR_INDEX_FRAME] = "frame";
for (DriverVar *dvar = driver->variables.first; dvar; dvar = dvar->next) {
names[i++] = dvar->name;
}
- return BLI_expr_pylike_parse(driver->expression, names, names_len + 1);
+ return BLI_expr_pylike_parse(driver->expression, names, names_len + VAR_INDEX_CUSTOM);
+}
+
+static bool driver_check_simple_expr_depends_on_time(ExprPyLike_Parsed *expr)
+{
+ /* Check if the 'frame' parameter is actually used. */
+ return BLI_expr_pylike_is_using_param(expr, VAR_INDEX_FRAME);
}
static bool driver_evaluate_simple_expr(ChannelDriver *driver,
@@ -2163,10 +2179,10 @@ static bool driver_evaluate_simple_expr(ChannelDriver *driver,
{
/* Prepare parameter values. */
int vars_len = BLI_listbase_count(&driver->variables);
- double *vars = BLI_array_alloca(vars, vars_len + 1);
- int i = 0;
+ double *vars = BLI_array_alloca(vars, vars_len + VAR_INDEX_CUSTOM);
+ int i = VAR_INDEX_CUSTOM;
- vars[i++] = time;
+ vars[VAR_INDEX_FRAME] = time;
for (DriverVar *dvar = driver->variables.first; dvar; dvar = dvar->next) {
vars[i++] = driver_get_variable_value(driver, dvar);
@@ -2174,7 +2190,8 @@ static bool driver_evaluate_simple_expr(ChannelDriver *driver,
/* Evaluate expression. */
double result_val;
- eExprPyLike_EvalStatus status = BLI_expr_pylike_eval(expr, vars, vars_len + 1, &result_val);
+ eExprPyLike_EvalStatus status = BLI_expr_pylike_eval(
+ expr, vars, vars_len + VAR_INDEX_CUSTOM, &result_val);
const char *message;
switch (status) {
@@ -2243,6 +2260,44 @@ bool BKE_driver_has_simple_expression(ChannelDriver *driver)
return driver_compile_simple_expr(driver) && BLI_expr_pylike_is_valid(driver->expr_simple);
}
+/* TODO(sergey): This is somewhat weak, but we don't want neither false-positive
+ * time dependencies nor special exceptions in the depsgraph evaluation. */
+static bool python_driver_exression_depends_on_time(const char *expression)
+{
+ if (expression[0] == '\0') {
+ /* Empty expression depends on nothing. */
+ return false;
+ }
+ if (strchr(expression, '(') != NULL) {
+ /* Function calls are considered dependent on a time. */
+ return true;
+ }
+ if (strstr(expression, "frame") != NULL) {
+ /* Variable `frame` depends on time. */
+ /* TODO(sergey): This is a bit weak, but not sure about better way of handling this. */
+ return true;
+ }
+ /* Possible indirect time relation s should be handled via variable targets. */
+ return false;
+}
+
+/* Check if the expression in the driver may depend on the current frame. */
+bool BKE_driver_expression_depends_on_time(ChannelDriver *driver)
+{
+ if (driver->type != DRIVER_TYPE_PYTHON) {
+ return false;
+ }
+
+ if (BKE_driver_has_simple_expression(driver)) {
+ /* Simple expressions can be checked exactly. */
+ return driver_check_simple_expr_depends_on_time(driver->expr_simple);
+ }
+ else {
+ /* Otherwise, heuristically scan the expression string for certain patterns. */
+ return python_driver_exression_depends_on_time(driver->expression);
+ }
+}
+
/* Reset cached compiled expression data */
void BKE_driver_invalidate_expression(ChannelDriver *driver,
bool expr_changed,
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 96be64dea75..f19137bf796 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -85,6 +85,9 @@
/** Time step default value for nice appearance. */
#define DT_DEFAULT 0.1f
+/** Max value for phi initialization */
+#define PHI_MAX 9999.0f
+
static void BKE_fluid_modifier_reset_ex(struct FluidModifierData *mmd, bool need_lock);
#ifdef WITH_FLUID
@@ -330,22 +333,22 @@ void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map)
{
char temp_dir[FILE_MAX];
int flags = mds->cache_flag;
-
- /* Ensure cache directory is not relative */
const char *relbase = modifier_path_relbase_from_global(ob);
- BLI_path_abs(mds->cache_directory, relbase);
if (cache_map & FLUID_DOMAIN_OUTDATED_DATA) {
flags &= ~(FLUID_DOMAIN_BAKING_DATA | FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_OUTDATED_DATA);
BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_CONFIG, NULL);
+ BLI_path_abs(temp_dir, relbase);
if (BLI_exists(temp_dir)) {
BLI_delete(temp_dir, true, true);
}
BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, NULL);
+ BLI_path_abs(temp_dir, relbase);
if (BLI_exists(temp_dir)) {
BLI_delete(temp_dir, true, true);
}
BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, NULL);
+ BLI_path_abs(temp_dir, relbase);
if (BLI_exists(temp_dir)) {
BLI_delete(temp_dir, true, true);
}
@@ -354,6 +357,7 @@ void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map)
if (cache_map & FLUID_DOMAIN_OUTDATED_NOISE) {
flags &= ~(FLUID_DOMAIN_BAKING_NOISE | FLUID_DOMAIN_BAKED_NOISE | FLUID_DOMAIN_OUTDATED_NOISE);
BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_NOISE, NULL);
+ BLI_path_abs(temp_dir, relbase);
if (BLI_exists(temp_dir)) {
BLI_delete(temp_dir, true, true);
}
@@ -362,6 +366,7 @@ void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map)
if (cache_map & FLUID_DOMAIN_OUTDATED_MESH) {
flags &= ~(FLUID_DOMAIN_BAKING_MESH | FLUID_DOMAIN_BAKED_MESH | FLUID_DOMAIN_OUTDATED_MESH);
BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_MESH, NULL);
+ BLI_path_abs(temp_dir, relbase);
if (BLI_exists(temp_dir)) {
BLI_delete(temp_dir, true, true);
}
@@ -372,6 +377,7 @@ void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map)
FLUID_DOMAIN_OUTDATED_PARTICLES);
BLI_path_join(
temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, NULL);
+ BLI_path_abs(temp_dir, relbase);
if (BLI_exists(temp_dir)) {
BLI_delete(temp_dir, true, true);
}
@@ -381,6 +387,7 @@ void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map)
if (cache_map & FLUID_DOMAIN_OUTDATED_GUIDE) {
flags &= ~(FLUID_DOMAIN_BAKING_GUIDE | FLUID_DOMAIN_BAKED_GUIDE | FLUID_DOMAIN_OUTDATED_GUIDE);
BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, NULL);
+ BLI_path_abs(temp_dir, relbase);
if (BLI_exists(temp_dir)) {
BLI_delete(temp_dir, true, true);
}
@@ -612,7 +619,7 @@ typedef struct ObstaclesFromDMData {
bool has_velocity;
float *vert_vel;
float *velocity_x, *velocity_y, *velocity_z;
- int *num_objects;
+ float *num_objects;
float *distances_map;
} ObstaclesFromDMData;
@@ -623,10 +630,10 @@ static void obstacles_from_mesh_task_cb(void *__restrict userdata,
ObstaclesFromDMData *data = userdata;
FluidDomainSettings *mds = data->mds;
- /* slightly rounded-up sqrt(3 * (0.5)^2) == max. distance of cell boundary along the diagonal */
- const float surface_distance = 2.0f; // 0.867f;
- /* Note: Use larger surface distance to cover larger area with obvel. Manta will use these obvels
- * and extrapolate them (inside and outside obstacle) */
+ /* Distance between two opposing vertices in a unit cube.
+ * I.e. the unit cube diagonal or sqrt(3).
+ * This value is our nearest neighbour search distance. */
+ const float surface_distance = 1.732;
for (int x = mds->res_min[0]; x < mds->res_max[0]; x++) {
for (int y = mds->res_min[1]; y < mds->res_max[1]; y++) {
@@ -640,7 +647,7 @@ static void obstacles_from_mesh_task_cb(void *__restrict userdata,
surface_distance; /* find_nearest uses squared distance */
bool has_inc_obj = false;
- /* find the nearest point on the mesh */
+ /* Find the nearest point on the mesh. */
if (BLI_bvhtree_find_nearest(
data->tree->tree, ray_start, &nearest, data->tree->nearest_callback, data->tree) !=
-1) {
@@ -698,15 +705,9 @@ static void obstacles_from_mesh_task_cb(void *__restrict userdata,
}
else {
/* Apply (i.e. add) effector object velocity */
- data->velocity_x[index] += (data->mes->type == FLUID_EFFECTOR_TYPE_GUIDE) ?
- hit_vel[0] * data->mes->vel_multi :
- hit_vel[0];
- data->velocity_y[index] += (data->mes->type == FLUID_EFFECTOR_TYPE_GUIDE) ?
- hit_vel[1] * data->mes->vel_multi :
- hit_vel[1];
- data->velocity_z[index] += (data->mes->type == FLUID_EFFECTOR_TYPE_GUIDE) ?
- hit_vel[2] * data->mes->vel_multi :
- hit_vel[2];
+ data->velocity_x[index] += hit_vel[0];
+ data->velocity_y[index] += hit_vel[1];
+ data->velocity_z[index] += hit_vel[2];
# ifdef DEBUG_PRINT
/* Debugging: Print object velocities. */
printf("adding effector object vel: [%f, %f, %f], dx is: %f\n",
@@ -745,7 +746,7 @@ static void obstacles_from_mesh(Object *coll_ob,
float *velocity_x,
float *velocity_y,
float *velocity_z,
- int *num_objects,
+ float *num_objects,
float dt)
{
if (!mes->mesh) {
@@ -918,32 +919,21 @@ static void update_obstacles(Depsgraph *depsgraph,
float *vel_x_guide = manta_get_guide_velocity_x(mds->fluid);
float *vel_y_guide = manta_get_guide_velocity_y(mds->fluid);
float *vel_z_guide = manta_get_guide_velocity_z(mds->fluid);
- float *vel_x_orig = manta_get_velocity_x(mds->fluid);
- float *vel_y_orig = manta_get_velocity_y(mds->fluid);
- float *vel_z_orig = manta_get_velocity_z(mds->fluid);
- float *density = manta_smoke_get_density(mds->fluid);
- float *fuel = manta_smoke_get_fuel(mds->fluid);
- float *flame = manta_smoke_get_flame(mds->fluid);
- float *r = manta_smoke_get_color_r(mds->fluid);
- float *g = manta_smoke_get_color_g(mds->fluid);
- float *b = manta_smoke_get_color_b(mds->fluid);
float *phi_obs_in = manta_get_phiobs_in(mds->fluid);
float *phi_guide_in = manta_get_phiguide_in(mds->fluid);
- int *obstacles = manta_smoke_get_obstacle(mds->fluid);
- int *num_obstacles = manta_get_num_obstacle(mds->fluid);
- int *num_guides = manta_get_num_guide(mds->fluid);
+ float *num_obstacles = manta_get_num_obstacle(mds->fluid);
+ float *num_guides = manta_get_num_guide(mds->fluid);
uint z;
- float tmp = 0;
/* Grid reset before writing again. */
for (z = 0; z < mds->res[0] * mds->res[1] * mds->res[2]; z++) {
/* Use big value that's not inf to initialize levelset grids. */
if (phi_obs_in) {
- phi_obs_in[z] = FLT_MAX;
+ phi_obs_in[z] = PHI_MAX;
}
if (phi_guide_in) {
- phi_guide_in[z] = FLT_MAX;
+ phi_guide_in[z] = PHI_MAX;
}
if (num_obstacles) {
num_obstacles[z] = 0;
@@ -1019,44 +1009,6 @@ static void update_obstacles(Depsgraph *depsgraph,
}
BKE_collision_objects_free(coll_ob_array);
-
- /* Obstacle cells should not contain any velocity from the smoke simulation. */
- for (z = 0; z < mds->res[0] * mds->res[1] * mds->res[2]; z++) {
- if (obstacles[z] & 2) /* Mantaflow convention: FlagObstacle. */
- {
- if (vel_x_orig && vel_y_orig && vel_z_orig) {
- vel_x_orig[z] = 0.0f;
- vel_y_orig[z] = 0.0f;
- vel_z_orig[z] = 0.0f;
- }
- if (density) {
- density[z] = 0.0f;
- }
- if (fuel) {
- fuel[z] = 0.0f;
- flame[z] = 0.0f;
- }
- if (r) {
- r[z] = 0.0f;
- g[z] = 0.0f;
- b[z] = 0.0f;
- }
- }
- /* Average velocities from multiple obstacles in one cell. */
- if (num_obstacles && num_obstacles[z]) {
- tmp = 1.0f / num_obstacles[z];
- vel_x[z] *= tmp;
- vel_y[z] *= tmp;
- vel_z[z] *= tmp;
- }
- /* Average velocities from multiple guides in one cell. */
- if (num_guides && num_guides[z]) {
- tmp = 1.0f / num_guides[z];
- vel_x_guide[z] *= tmp;
- vel_y_guide[z] *= tmp;
- vel_z_guide[z] *= tmp;
- }
- }
}
/** \} */
@@ -1067,10 +1019,8 @@ static void update_obstacles(Depsgraph *depsgraph,
typedef struct EmissionMap {
float *influence;
- float *influence_high;
float *velocity;
float *distances;
- float *distances_high;
int min[3], max[3], res[3];
int hmin[3], hmax[3], hres[3];
int total_cells, valid;
@@ -1127,7 +1077,7 @@ static void clamp_bounds_in_domain(FluidDomainSettings *mds,
}
}
-static void em_allocateData(EmissionMap *em, bool use_velocity, int hires_mul)
+static void em_allocateData(EmissionMap *em, bool use_velocity)
{
int i, res[3];
@@ -1149,23 +1099,6 @@ static void em_allocateData(EmissionMap *em, bool use_velocity, int hires_mul)
/* Initialize to infinity. */
memset(em->distances, 0x7f7f7f7f, sizeof(float) * em->total_cells);
- /* Allocate high resolution map if required. */
- if (hires_mul > 1) {
- int total_cells_high = em->total_cells * (hires_mul * hires_mul * hires_mul);
-
- for (i = 0; i < 3; i++) {
- em->hmin[i] = em->min[i] * hires_mul;
- em->hmax[i] = em->max[i] * hires_mul;
- em->hres[i] = em->res[i] * hires_mul;
- }
-
- em->influence_high = MEM_calloc_arrayN(
- total_cells_high, sizeof(float), "manta_flow_influence_high");
- em->distances_high = MEM_malloc_arrayN(
- total_cells_high, sizeof(float), "manta_flow_distances_high");
- /* Initialize to infinity. */
- memset(em->distances_high, 0x7f7f7f7f, sizeof(float) * total_cells_high);
- }
em->valid = true;
}
@@ -1174,22 +1107,15 @@ static void em_freeData(EmissionMap *em)
if (em->influence) {
MEM_freeN(em->influence);
}
- if (em->influence_high) {
- MEM_freeN(em->influence_high);
- }
if (em->velocity) {
MEM_freeN(em->velocity);
}
if (em->distances) {
MEM_freeN(em->distances);
}
- if (em->distances_high) {
- MEM_freeN(em->distances_high);
- }
}
-static void em_combineMaps(
- EmissionMap *output, EmissionMap *em2, int hires_multiplier, int additive, float sample_size)
+static void em_combineMaps(EmissionMap *output, EmissionMap *em2, int additive, float sample_size)
{
int i, x, y, z;
@@ -1209,7 +1135,7 @@ static void em_combineMaps(
}
}
/* allocate output map */
- em_allocateData(output, (em1.velocity || em2->velocity), hires_multiplier);
+ em_allocateData(output, (em1.velocity || em2->velocity));
/* base resolution inputs */
for (x = output->min[0]; x < output->max[0]; x++) {
@@ -1265,48 +1191,6 @@ static void em_combineMaps(
}
}
- /* initialize high resolution input if available */
- if (output->influence_high) {
- for (x = output->hmin[0]; x < output->hmax[0]; x++) {
- for (y = output->hmin[1]; y < output->hmax[1]; y++) {
- for (z = output->hmin[2]; z < output->hmax[2]; z++) {
- int index_out = manta_get_index(x - output->hmin[0],
- output->hres[0],
- y - output->hmin[1],
- output->hres[1],
- z - output->hmin[2]);
-
- /* initialize with first input if in range */
- if (x >= em1.hmin[0] && x < em1.hmax[0] && y >= em1.hmin[1] && y < em1.hmax[1] &&
- z >= em1.hmin[2] && z < em1.hmax[2]) {
- int index_in = manta_get_index(
- x - em1.hmin[0], em1.hres[0], y - em1.hmin[1], em1.hres[1], z - em1.hmin[2]);
- /* values */
- output->influence_high[index_out] = em1.influence_high[index_in];
- }
-
- /* apply second input if in range */
- if (x >= em2->hmin[0] && x < em2->hmax[0] && y >= em2->hmin[1] && y < em2->hmax[1] &&
- z >= em2->hmin[2] && z < em2->hmax[2]) {
- int index_in = manta_get_index(
- x - em2->hmin[0], em2->hres[0], y - em2->hmin[1], em2->hres[1], z - em2->hmin[2]);
-
- /* values */
- if (additive) {
- output->influence_high[index_out] += em2->distances_high[index_in] * sample_size;
- }
- else {
- output->distances_high[index_out] = MAX2(em2->distances_high[index_in],
- output->distances_high[index_out]);
- }
- output->distances_high[index_out] = MIN2(em2->distances_high[index_in],
- output->distances_high[index_out]);
- }
- } // high res loop
- }
- }
- }
-
/* free original data */
em_freeData(&em1);
}
@@ -1314,17 +1198,13 @@ static void em_combineMaps(
typedef struct EmitFromParticlesData {
FluidFlowSettings *mfs;
KDTree_3d *tree;
- int hires_multiplier;
EmissionMap *em;
float *particle_vel;
- float hr;
-
int *min, *max, *res;
float solid;
float smooth;
- float hr_smooth;
} EmitFromParticlesData;
static void emit_from_particles_task_cb(void *__restrict userdata,
@@ -1334,62 +1214,26 @@ static void emit_from_particles_task_cb(void *__restrict userdata,
EmitFromParticlesData *data = userdata;
FluidFlowSettings *mfs = data->mfs;
EmissionMap *em = data->em;
- const int hires_multiplier = data->hires_multiplier;
for (int x = data->min[0]; x < data->max[0]; x++) {
for (int y = data->min[1]; y < data->max[1]; y++) {
- /* Take low res samples where possible. */
- if (hires_multiplier <= 1 ||
- !(x % hires_multiplier || y % hires_multiplier || z % hires_multiplier)) {
- /* Get low res space coordinates. */
- float inv_multiplier = 1.0f / hires_multiplier;
- const int lx = x * inv_multiplier;
- const int ly = y * inv_multiplier;
- const int lz = z * inv_multiplier;
-
- const int index = manta_get_index(
- lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
- const float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
-
- /* Find particle distance from the kdtree. */
- KDTreeNearest_3d nearest;
- const float range = data->solid + data->smooth;
- BLI_kdtree_3d_find_nearest(data->tree, ray_start, &nearest);
-
- if (nearest.dist < range) {
- em->influence[index] = (nearest.dist < data->solid) ?
- 1.0f :
- (1.0f - (nearest.dist - data->solid) / data->smooth);
- /* Uses particle velocity as initial velocity for smoke. */
- if (mfs->flags & FLUID_FLOW_INITVELOCITY &&
- (mfs->psys->part->phystype != PART_PHYS_NO)) {
- madd_v3_v3fl(
- &em->velocity[index * 3], &data->particle_vel[nearest.index * 3], mfs->vel_multi);
- }
- }
- }
-
- /* Take high res samples if required. */
- if (hires_multiplier > 1) {
- /* get low res space coordinates */
- const float lx = ((float)x) * data->hr;
- const float ly = ((float)y) * data->hr;
- const float lz = ((float)z) * data->hr;
-
- const int index = manta_get_index(
- x - data->min[0], data->res[0], y - data->min[1], data->res[1], z - data->min[2]);
- const float ray_start[3] = {
- lx + 0.5f * data->hr, ly + 0.5f * data->hr, lz + 0.5f * data->hr};
-
- /* Find particle distance from the kdtree. */
- KDTreeNearest_3d nearest;
- const float range = data->solid + data->hr_smooth;
- BLI_kdtree_3d_find_nearest(data->tree, ray_start, &nearest);
-
- if (nearest.dist < range) {
- em->influence_high[index] = (nearest.dist < data->solid) ?
- 1.0f :
- (1.0f - (nearest.dist - data->solid) / data->smooth);
+ const int index = manta_get_index(
+ x - em->min[0], em->res[0], y - em->min[1], em->res[1], z - em->min[2]);
+ const float ray_start[3] = {((float)x) + 0.5f, ((float)y) + 0.5f, ((float)z) + 0.5f};
+
+ /* Find particle distance from the kdtree. */
+ KDTreeNearest_3d nearest;
+ const float range = data->solid + data->smooth;
+ BLI_kdtree_3d_find_nearest(data->tree, ray_start, &nearest);
+
+ if (nearest.dist < range) {
+ em->influence[index] = (nearest.dist < data->solid) ?
+ 1.0f :
+ (1.0f - (nearest.dist - data->solid) / data->smooth);
+ /* Uses particle velocity as initial velocity for smoke. */
+ if (mfs->flags & FLUID_FLOW_INITVELOCITY && (mfs->psys->part->phystype != PART_PHYS_NO)) {
+ madd_v3_v3fl(
+ &em->velocity[index * 3], &data->particle_vel[nearest.index * 3], mfs->vel_multi);
}
}
}
@@ -1419,7 +1263,6 @@ static void emit_from_particles(Object *flow_ob,
/* radius based flow */
const float solid = mfs->particle_size * 0.5f;
const float smooth = 0.5f; /* add 0.5 cells of linear falloff to reduce aliasing */
- int hires_multiplier = 1;
KDTree_3d *tree = NULL;
sim.depsgraph = depsgraph;
@@ -1456,12 +1299,6 @@ static void emit_from_particles(Object *flow_ob,
/* setup particle radius emission if enabled */
if (mfs->flags & FLUID_FLOW_USE_PART_SIZE) {
tree = BLI_kdtree_3d_new(psys->totpart + psys->totchild);
-
- /* check need for high resolution map */
- if ((mds->flags & FLUID_DOMAIN_USE_NOISE) && (mds->highres_sampling == SM_HRES_FULLSAMPLE)) {
- hires_multiplier = mds->noise_scale;
- }
-
bounds_margin = (int)ceil(solid + smooth);
}
@@ -1509,7 +1346,7 @@ static void emit_from_particles(Object *flow_ob,
/* set emission map */
clamp_bounds_in_domain(mds, em->min, em->max, NULL, NULL, bounds_margin, dt);
- em_allocateData(em, mfs->flags & FLUID_FLOW_INITVELOCITY, hires_multiplier);
+ em_allocateData(em, mfs->flags & FLUID_FLOW_INITVELOCITY);
if (!(mfs->flags & FLUID_FLOW_USE_PART_SIZE)) {
for (p = 0; p < valid_particles; p++) {
@@ -1544,16 +1381,12 @@ static void emit_from_particles(Object *flow_ob,
}
else if (valid_particles > 0) { // FLUID_FLOW_USE_PART_SIZE
int min[3], max[3], res[3];
- const float hr = 1.0f / ((float)hires_multiplier);
- /* Slightly adjust high res anti-alias smoothness based on number of divisions
- * to allow smaller details but yet not differing too much from the low res size. */
- const float hr_smooth = smooth * powf(hr, 1.0f / 3.0f);
/* setup loop bounds */
for (int i = 0; i < 3; i++) {
- min[i] = em->min[i] * hires_multiplier;
- max[i] = em->max[i] * hires_multiplier;
- res[i] = em->res[i] * hires_multiplier;
+ min[i] = em->min[i];
+ max[i] = em->max[i];
+ res[i] = em->res[i];
}
BLI_kdtree_3d_balance(tree);
@@ -1561,8 +1394,6 @@ static void emit_from_particles(Object *flow_ob,
EmitFromParticlesData data = {
.mfs = mfs,
.tree = tree,
- .hires_multiplier = hires_multiplier,
- .hr = hr,
.em = em,
.particle_vel = particle_vel,
.min = min,
@@ -1570,7 +1401,6 @@ static void emit_from_particles(Object *flow_ob,
.res = res,
.solid = solid,
.smooth = smooth,
- .hr_smooth = hr_smooth,
};
TaskParallelSettings settings;
@@ -1602,13 +1432,14 @@ static void update_mesh_distances(int index,
float surface_thickness,
int use_plane_init)
{
- float min_dist = FLT_MAX;
+ float min_dist = PHI_MAX;
- /* Ensure that planes get initialized correctly. */
+ /* a) Planar initialization */
if (use_plane_init) {
BVHTreeNearest nearest = {0};
nearest.index = -1;
- nearest.dist_sq = surface_thickness;
+ nearest.dist_sq = surface_thickness *
+ surface_thickness; /* find_nearest uses squared distance */
if (BLI_bvhtree_find_nearest(
tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
@@ -1616,12 +1447,14 @@ static void update_mesh_distances(int index,
sub_v3_v3v3(ray, ray_start, nearest.co);
min_dist = len_v3(ray);
min_dist = (-1.0f) * fabsf(min_dist);
- mesh_distances[index] = MIN2(mesh_distances[index], min_dist);
+ mesh_distances[index] = min_dist;
}
return;
}
- /* First pass: Ray-casts in 26 directions
+ /* b) Volumetric initialization: Ray-casts around mesh object. */
+
+ /* Ray-casts in 26 directions.
* (6 main axis + 12 quadrant diagonals (2D) + 8 octant diagonals (3D)). */
float ray_dirs[26][3] = {
{1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f},
@@ -1633,15 +1466,16 @@ static void update_mesh_distances(int index,
{-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}};
size_t ray_cnt = sizeof ray_dirs / sizeof ray_dirs[0];
- /* Count for ray misses (no face hit) and cases where ray direction matches face normal
- * direction. */
+ /* Count ray mesh misses (i.e. no face hit) and cases where the ray direction matches the face
+ * normal direction. From this information it can be derived whether a cell is inside or outside
+ * the mesh. */
int miss_cnt = 0, dir_cnt = 0;
- min_dist = FLT_MAX;
+ min_dist = PHI_MAX;
for (int i = 0; i < ray_cnt; i++) {
BVHTreeRayHit hit_tree = {0};
hit_tree.index = -1;
- hit_tree.dist = FLT_MAX;
+ hit_tree.dist = PHI_MAX;
normalize_v3(ray_dirs[i]);
BLI_bvhtree_ray_cast(tree_data->tree,
@@ -1652,14 +1486,13 @@ static void update_mesh_distances(int index,
tree_data->raycast_callback,
tree_data);
- /* Ray did not hit mesh. Current point definitely not inside mesh. Inside mesh all rays have to
- * hit. */
+ /* Ray did not hit mesh.
+ * Current point definitely not inside mesh. Inside mesh as all rays have to hit. */
if (hit_tree.index == -1) {
miss_cnt++;
- continue;
}
- /* Ray and normal are in pointing opposite directions. */
+ /* Ray and normal are pointing in opposite directions. */
if (dot_v3v3(ray_dirs[i], hit_tree.no) <= 0) {
dir_cnt++;
}
@@ -1669,7 +1502,8 @@ static void update_mesh_distances(int index,
}
}
- /* Point lies inside mesh. Use negative sign for distance value. */
+ /* Point lies inside mesh. Use negative sign for distance value.
+ * This "if statement" has 2 conditions that can be true for points outside mesh. */
if (!(miss_cnt > 0 || dir_cnt == ray_cnt)) {
min_dist = (-1.0f) * fabsf(min_dist);
}
@@ -1677,45 +1511,13 @@ static void update_mesh_distances(int index,
/* Update global distance array but ensure that older entries are not overridden. */
mesh_distances[index] = MIN2(mesh_distances[index], min_dist);
- /* Second pass: Use nearest neighbor search on mesh surface. */
- BVHTreeNearest nearest = {0};
- nearest.index = -1;
- nearest.dist_sq = 5;
-
- if (BLI_bvhtree_find_nearest(
- tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
- float ray[3] = {0};
- sub_v3_v3v3(ray, nearest.co, ray_start);
- min_dist = len_v3(ray);
- // CLAMP(min_dist, 0.5, min_dist);
-
- BVHTreeRayHit hit_tree = {0};
- hit_tree.index = -1;
- hit_tree.dist = FLT_MAX;
-
- normalize_v3(ray);
- BLI_bvhtree_ray_cast(
- tree_data->tree, ray_start, ray, 0.0f, &hit_tree, tree_data->raycast_callback, tree_data);
-
- /* Only proceed if casted ray hit the mesh surface. */
- if (hit_tree.index != -1) {
-
- /* Ray and normal are in pointing same directions: Point must lie inside mesh. */
- if (dot_v3v3(ray, hit_tree.no) > 0) {
- min_dist = (-1.0f) * fabsf(min_dist);
- }
-
- /* Update distance value with more accurate one from this nearest neighbor search.
- * Skip if new value would be outside and current value has inside value already. */
- if (!(min_dist > 0 && mesh_distances[index] <= 0)) {
- mesh_distances[index] = min_dist;
- }
- }
- }
-
+ /* Subtract optional surface thickness value and virtually increase the object size. */
if (surface_thickness) {
mesh_distances[index] -= surface_thickness;
}
+
+ /* Sanity check: Ensure that distances don't explode. */
+ CLAMP(mesh_distances[index], -PHI_MAX, PHI_MAX);
}
static void sample_mesh(FluidFlowSettings *mfs,
@@ -1743,16 +1545,23 @@ static void sample_mesh(FluidFlowSettings *mfs,
BVHTreeNearest nearest = {0};
float volume_factor = 0.0f;
- float sample_str = 0.0f;
+ float emission_strength = 0.0f;
hit.index = -1;
- hit.dist = FLT_MAX;
+ hit.dist = PHI_MAX;
nearest.index = -1;
- nearest.dist_sq = mfs->surface_distance *
- mfs->surface_distance; /* find_nearest uses squared distance */
- /* Check volume collision */
- if (mfs->volume_density) {
+ /* Distance between two opposing vertices in a unit cube.
+ * I.e. the unit cube diagonal or sqrt(3).
+ * This value is our nearest neighbour search distance. */
+ const float surface_distance = 1.732;
+ nearest.dist_sq = surface_distance * surface_distance; /* find_nearest uses squared distance. */
+
+ bool is_gas_flow = (mfs->type == FLUID_FLOW_TYPE_SMOKE || mfs->type == FLUID_FLOW_TYPE_FIRE ||
+ mfs->type == FLUID_FLOW_TYPE_SMOKEFIRE);
+
+ /* Emission inside the flow object. */
+ if (is_gas_flow && mfs->volume_density) {
if (BLI_bvhtree_ray_cast(tree_data->tree,
ray_start,
ray_dir,
@@ -1761,14 +1570,13 @@ static void sample_mesh(FluidFlowSettings *mfs,
tree_data->raycast_callback,
tree_data) != -1) {
float dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2];
- /* If ray and hit face normal are facing same direction
- * hit point is inside a closed mesh. */
+ /* If ray and hit face normal are facing same direction hit point is inside a closed mesh. */
if (dot >= 0) {
- /* Also cast a ray in opposite direction to make sure
- * point is at least surrounded by two faces */
+ /* Also cast a ray in opposite direction to make sure point is at least surrounded by two
+ * faces. */
negate_v3(ray_dir);
hit.index = -1;
- hit.dist = FLT_MAX;
+ hit.dist = PHI_MAX;
BLI_bvhtree_ray_cast(tree_data->tree,
ray_start,
@@ -1784,48 +1592,36 @@ static void sample_mesh(FluidFlowSettings *mfs,
}
}
- /* find the nearest point on the mesh */
+ /* Find the nearest point on the mesh. */
if (BLI_bvhtree_find_nearest(
tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
float weights[3];
int v1, v2, v3, f_index = nearest.index;
float n1[3], n2[3], n3[3], hit_normal[3];
- /* emit from surface based on distance */
- if (mfs->surface_distance) {
- sample_str = sqrtf(nearest.dist_sq) / mfs->surface_distance;
- CLAMP(sample_str, 0.0f, 1.0f);
- sample_str = pow(1.0f - sample_str, 0.5f);
- }
- else {
- sample_str = 0.0f;
- }
-
- /* calculate barycentric weights for nearest point */
+ /* Calculate barycentric weights for nearest point. */
v1 = mloop[mlooptri[f_index].tri[0]].v;
v2 = mloop[mlooptri[f_index].tri[1]].v;
v3 = mloop[mlooptri[f_index].tri[2]].v;
interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, nearest.co);
+ /* Initial velocity of flow object. */
if (mfs->flags & FLUID_FLOW_INITVELOCITY && velocity_map) {
- /* apply normal directional velocity */
+ /* Apply normal directional velocity. */
if (mfs->vel_normal) {
- /* interpolate vertex normal vectors to get nearest point normal */
+ /* Interpolate vertex normal vectors to get nearest point normal. */
normal_short_to_float_v3(n1, mvert[v1].no);
normal_short_to_float_v3(n2, mvert[v2].no);
normal_short_to_float_v3(n3, mvert[v3].no);
interp_v3_v3v3v3(hit_normal, n1, n2, n3, weights);
normalize_v3(hit_normal);
- /* apply normal directional and random velocity
- * - TODO: random disabled for now since it doesn't really work well
- * as pressure calc smoothens it out. */
+
+ /* Apply normal directional velocity. */
velocity_map[index * 3] += hit_normal[0] * mfs->vel_normal * 0.25f;
velocity_map[index * 3 + 1] += hit_normal[1] * mfs->vel_normal * 0.25f;
velocity_map[index * 3 + 2] += hit_normal[2] * mfs->vel_normal * 0.25f;
- /* TODO: for fire emitted from mesh surface we can use
- * Vf = Vs + (Ps/Pf - 1)*S to model gaseous expansion from solid to fuel */
}
- /* apply object velocity */
+ /* Apply object velocity. */
if (has_velocity && mfs->vel_multi) {
float hit_vel[3];
interp_v3_v3v3v3(
@@ -1843,50 +1639,59 @@ static void sample_mesh(FluidFlowSettings *mfs,
velocity_map[index * 3 + 2] += mfs->vel_coord[2];
}
- /* apply vertex group influence if used */
- if (defgrp_index != -1 && dvert) {
- float weight_mask = defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] +
- defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] +
- defvert_find_weight(&dvert[v3], defgrp_index) * weights[2];
- sample_str *= weight_mask;
- }
-
- /* apply emission texture */
- if ((mfs->flags & FLUID_FLOW_TEXTUREEMIT) && mfs->noise_texture) {
- float tex_co[3] = {0};
- TexResult texres;
+ /* Compute emission strength for smoke flow. */
+ if (is_gas_flow) {
+ /* Emission from surface is based on UI configurable distance value. */
+ if (mfs->surface_distance) {
+ emission_strength = sqrtf(nearest.dist_sq) / mfs->surface_distance;
+ CLAMP(emission_strength, 0.0f, 1.0f);
+ emission_strength = pow(1.0f - emission_strength, 0.5f);
+ }
+ else {
+ emission_strength = 0.0f;
+ }
- if (mfs->texture_type == FLUID_FLOW_TEXTURE_MAP_AUTO) {
- tex_co[0] = ((x - flow_center[0]) / base_res[0]) / mfs->texture_size;
- tex_co[1] = ((y - flow_center[1]) / base_res[1]) / mfs->texture_size;
- tex_co[2] = ((z - flow_center[2]) / base_res[2] - mfs->texture_offset) / mfs->texture_size;
+ /* Apply vertex group influence if it is being used. */
+ if (defgrp_index != -1 && dvert) {
+ float weight_mask = defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] +
+ defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] +
+ defvert_find_weight(&dvert[v3], defgrp_index) * weights[2];
+ emission_strength *= weight_mask;
}
- else if (mloopuv) {
- const float *uv[3];
- uv[0] = mloopuv[mlooptri[f_index].tri[0]].uv;
- uv[1] = mloopuv[mlooptri[f_index].tri[1]].uv;
- uv[2] = mloopuv[mlooptri[f_index].tri[2]].uv;
-
- interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights);
-
- /* map between -1.0f and 1.0f */
- tex_co[0] = tex_co[0] * 2.0f - 1.0f;
- tex_co[1] = tex_co[1] * 2.0f - 1.0f;
- tex_co[2] = mfs->texture_offset;
+
+ /* Apply emission texture. */
+ if ((mfs->flags & FLUID_FLOW_TEXTUREEMIT) && mfs->noise_texture) {
+ float tex_co[3] = {0};
+ TexResult texres;
+
+ if (mfs->texture_type == FLUID_FLOW_TEXTURE_MAP_AUTO) {
+ tex_co[0] = ((x - flow_center[0]) / base_res[0]) / mfs->texture_size;
+ tex_co[1] = ((y - flow_center[1]) / base_res[1]) / mfs->texture_size;
+ tex_co[2] = ((z - flow_center[2]) / base_res[2] - mfs->texture_offset) /
+ mfs->texture_size;
+ }
+ else if (mloopuv) {
+ const float *uv[3];
+ uv[0] = mloopuv[mlooptri[f_index].tri[0]].uv;
+ uv[1] = mloopuv[mlooptri[f_index].tri[1]].uv;
+ uv[2] = mloopuv[mlooptri[f_index].tri[2]].uv;
+
+ interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights);
+
+ /* Map texure coord between -1.0f and 1.0f. */
+ tex_co[0] = tex_co[0] * 2.0f - 1.0f;
+ tex_co[1] = tex_co[1] * 2.0f - 1.0f;
+ tex_co[2] = mfs->texture_offset;
+ }
+ texres.nor = NULL;
+ BKE_texture_get_value(NULL, mfs->noise_texture, tex_co, &texres, false);
+ emission_strength *= texres.tin;
}
- texres.nor = NULL;
- BKE_texture_get_value(NULL, mfs->noise_texture, tex_co, &texres, false);
- sample_str *= texres.tin;
}
}
- /* multiply initial velocity by emitter influence */
- if (mfs->flags & FLUID_FLOW_INITVELOCITY && velocity_map) {
- mul_v3_fl(&velocity_map[index * 3], sample_str);
- }
-
- /* apply final influence based on volume factor */
- influence_map[index] = MAX2(volume_factor, sample_str);
+ /* Apply final influence value but also consider volume initialization factor. */
+ influence_map[index] = MAX2(volume_factor, emission_strength);
}
typedef struct EmitFromDMData {
@@ -1900,9 +1705,6 @@ typedef struct EmitFromDMData {
int defgrp_index;
BVHTreeFromMesh *tree;
- int hires_multiplier;
- float hr;
-
EmissionMap *em;
bool has_velocity;
float *vert_vel;
@@ -1917,23 +1719,17 @@ static void emit_from_mesh_task_cb(void *__restrict userdata,
{
EmitFromDMData *data = userdata;
EmissionMap *em = data->em;
- const int hires_multiplier = data->hires_multiplier;
for (int x = data->min[0]; x < data->max[0]; x++) {
for (int y = data->min[1]; y < data->max[1]; y++) {
- /* take low res samples where possible */
- if (hires_multiplier <= 1 ||
- !(x % hires_multiplier || y % hires_multiplier || z % hires_multiplier)) {
- /* get low res space coordinates */
- const int lx = x / hires_multiplier;
- const int ly = y / hires_multiplier;
- const int lz = z / hires_multiplier;
-
- const int index = manta_get_index(
- lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
- const float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
-
- /* Emission for smoke and fire. Result in em->influence. Also, calculate invels */
+ const int index = manta_get_index(
+ x - em->min[0], em->res[0], y - em->min[1], em->res[1], z - em->min[2]);
+ const float ray_start[3] = {((float)x) + 0.5f, ((float)y) + 0.5f, ((float)z) + 0.5f};
+
+ /* Compute emission only for flow objects that produce fluid (i.e. skip outflow objects).
+ * Result in em->influence. Also computes initial velocities. Result in em->velocity. */
+ if ((data->mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY) ||
+ (data->mfs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW)) {
sample_mesh(data->mfs,
data->mvert,
data->mloop,
@@ -1950,59 +1746,18 @@ static void emit_from_mesh_task_cb(void *__restrict userdata,
data->has_velocity,
data->defgrp_index,
data->dvert,
- (float)lx,
- (float)ly,
- (float)lz);
-
- /* Calculate levelset from meshes. Result in em->distances */
- update_mesh_distances(index,
- em->distances,
- data->tree,
- ray_start,
- data->mfs->surface_distance,
- data->mfs->flags & FLUID_FLOW_USE_PLANE_INIT);
+ (float)x,
+ (float)y,
+ (float)z);
}
- /* take high res samples if required */
- if (hires_multiplier > 1) {
- /* get low res space coordinates */
- const float lx = ((float)x) * data->hr;
- const float ly = ((float)y) * data->hr;
- const float lz = ((float)z) * data->hr;
-
- const int index = manta_get_index(
- x - data->min[0], data->res[0], y - data->min[1], data->res[1], z - data->min[2]);
- const float ray_start[3] = {
- lx + 0.5f * data->hr,
- ly + 0.5f * data->hr,
- lz + 0.5f * data->hr,
- };
-
- /* Emission for smoke and fire high. Result in em->influence_high */
- if (data->mfs->type == FLUID_FLOW_TYPE_SMOKE || data->mfs->type == FLUID_FLOW_TYPE_FIRE ||
- data->mfs->type == FLUID_FLOW_TYPE_SMOKEFIRE) {
- sample_mesh(data->mfs,
- data->mvert,
- data->mloop,
- data->mlooptri,
- data->mloopuv,
- em->influence_high,
- NULL,
- index,
- data->mds->base_res,
- data->flow_center,
- data->tree,
- ray_start,
- data->vert_vel,
- data->has_velocity,
- data->defgrp_index,
- data->dvert,
- /* x,y,z needs to be always lowres */
- lx,
- ly,
- lz);
- }
- }
+ /* Calculate levelset values from meshes. Result in em->distances. */
+ update_mesh_distances(index,
+ em->distances,
+ data->tree,
+ ray_start,
+ data->mfs->surface_distance,
+ data->mfs->flags & FLUID_FLOW_USE_PLANE_INIT);
}
}
}
@@ -2026,11 +1781,9 @@ static void emit_from_mesh(
int defgrp_index = mfs->vgroup_density - 1;
float flow_center[3] = {0};
int min[3], max[3], res[3];
- int hires_multiplier = 1;
- /* copy mesh for thread safety because we modify it,
- * main issue is its VertArray being modified, then replaced and freed
- */
+ /* Copy mesh for thread safety as we modify it.
+ * Main issue is its VertArray being modified, then replaced and freed. */
me = BKE_mesh_copy_for_eval(mfs->mesh, true);
/* Duplicate vertices to modify. */
@@ -2062,23 +1815,22 @@ static void emit_from_mesh(
}
}
- /* Transform mesh vertices to
- * domain grid space for fast lookups */
+ /* Transform mesh vertices to domain grid space for fast lookups */
for (i = 0; i < numverts; i++) {
float n[3];
- /* vert pos */
+ /* Vertex position. */
mul_m4_v3(flow_ob->obmat, mvert[i].co);
manta_pos_to_cell(mds, mvert[i].co);
- /* vert normal */
+ /* Vertex normal. */
normal_short_to_float_v3(n, mvert[i].no);
mul_mat3_m4_v3(flow_ob->obmat, n);
mul_mat3_m4_v3(mds->imat, n);
normalize_v3(n);
normal_float_to_short_v3(mvert[i].no, n);
- /* vert velocity */
+ /* Vertex velocity. */
if (mfs->flags & FLUID_FLOW_INITVELOCITY) {
float co[3];
add_v3fl_v3fl_v3i(co, mvert[i].co, mds->shift);
@@ -2089,31 +1841,26 @@ static void emit_from_mesh(
copy_v3_v3(&mfs->verts_old[i * 3], co);
}
- /* calculate emission map bounds */
+ /* Calculate emission map bounds. */
em_boundInsert(em, mvert[i].co);
}
mul_m4_v3(flow_ob->obmat, flow_center);
manta_pos_to_cell(mds, flow_center);
- /* check need for high resolution map */
- if ((mds->flags & FLUID_DOMAIN_USE_NOISE) && (mds->highres_sampling == SM_HRES_FULLSAMPLE)) {
- hires_multiplier = mds->noise_scale;
- }
-
- /* set emission map */
- clamp_bounds_in_domain(
- mds, em->min, em->max, NULL, NULL, (int)ceil(mfs->surface_distance), dt);
- em_allocateData(em, mfs->flags & FLUID_FLOW_INITVELOCITY, hires_multiplier);
+ /* Set emission map.
+ * Use 3 cell diagonals as margin (3 * 1.732 = 5.196). */
+ int bounds_margin = (int)ceil(5.196);
+ clamp_bounds_in_domain(mds, em->min, em->max, NULL, NULL, bounds_margin, dt);
+ em_allocateData(em, mfs->flags & FLUID_FLOW_INITVELOCITY);
- /* setup loop bounds */
+ /* Setup loop bounds. */
for (i = 0; i < 3; i++) {
- min[i] = em->min[i] * hires_multiplier;
- max[i] = em->max[i] * hires_multiplier;
- res[i] = em->res[i] * hires_multiplier;
+ min[i] = em->min[i];
+ max[i] = em->max[i];
+ res[i] = em->res[i];
}
if (BKE_bvhtree_from_mesh_get(&tree_data, me, BVHTREE_FROM_LOOPTRI, 4)) {
- const float hr = 1.0f / ((float)hires_multiplier);
EmitFromDMData data = {
.mds = mds,
@@ -2125,8 +1872,6 @@ static void emit_from_mesh(
.dvert = dvert,
.defgrp_index = defgrp_index,
.tree = &tree_data,
- .hires_multiplier = hires_multiplier,
- .hr = hr,
.em = em,
.has_velocity = has_velocity,
.vert_vel = vert_vel,
@@ -2141,7 +1886,7 @@ static void emit_from_mesh(
settings.min_iter_per_thread = 2;
BLI_task_parallel_range(min[2], max[2], &data, emit_from_mesh_task_cb, &settings);
}
- /* free bvh tree */
+ /* Free bvh tree. */
free_bvhtree_from_mesh(&tree_data);
if (vert_vel) {
@@ -2457,60 +2202,55 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
float *phi_in,
float *emission_in)
{
- /* add inflow */
+ /* Set levelset value for liquid inflow.
+ * Ensure that distance value is "joined" into the levelset. */
if (phi_in) {
- phi_in[index] = distance_value;
+ phi_in[index] = MIN2(distance_value, phi_in[index]);
}
- /* save emission value for manta inflow */
+ /* Set emission value for smoke inflow.
+ * Ensure that emission value is "maximised". */
if (emission_in) {
- emission_in[index] = emission_value;
+ emission_in[index] = MAX2(emission_value, emission_in[index]);
}
- /* add smoke inflow */
+ /* Set inflow for smoke from here on. */
int absolute_flow = (mfs->flags & FLUID_FLOW_ABSOLUTE);
float dens_old = (density) ? density[index] : 0.0;
// float fuel_old = (fuel) ? fuel[index] : 0.0f; /* UNUSED */
float dens_flow = (mfs->type == FLUID_FLOW_TYPE_FIRE) ? 0.0f : emission_value * mfs->density;
float fuel_flow = (fuel) ? emission_value * mfs->fuel_amount : 0.0f;
- /* add heat */
+ /* Set heat inflow. */
if (heat && heat_in) {
if (emission_value > 0.0f) {
heat_in[index] = ADD_IF_LOWER(heat[index], mfs->temperature);
- /* Scale inflow by dt/frame-length.
- * This is to ensure that adaptive steps don't apply too much emission. */
- }
- else {
- heat_in[index] = heat[index];
}
}
- /* set density and fuel - absolute mode */
+ /* Set density and fuel - absolute mode. */
if (absolute_flow) {
if (density && density_in) {
- density_in[index] = density[index];
if (mfs->type != FLUID_FLOW_TYPE_FIRE && dens_flow > density[index]) {
- density_in[index] = dens_flow;
+ /* Use MAX2 to preserve values from other emitters at this cell. */
+ density_in[index] = MAX2(dens_flow, density_in[index]);
}
}
if (fuel && fuel_in) {
- fuel_in[index] = fuel[index];
if (mfs->type != FLUID_FLOW_TYPE_SMOKE && fuel_flow && fuel_flow > fuel[index]) {
- fuel_in[index] = fuel_flow;
+ /* Use MAX2 to preserve values from other emitters at this cell. */
+ fuel_in[index] = MAX2(fuel_flow, fuel_in[index]);
}
}
}
- /* set density and fuel - additive mode */
+ /* Set density and fuel - additive mode. */
else {
if (density && density_in) {
- density_in[index] = density[index];
if (mfs->type != FLUID_FLOW_TYPE_FIRE) {
density_in[index] += dens_flow;
CLAMP(density_in[index], 0.0f, 1.0f);
}
}
if (fuel && fuel_in) {
- fuel_in[index] = fuel[index];
if (mfs->type != FLUID_FLOW_TYPE_SMOKE && mfs->fuel_amount) {
fuel_in[index] += fuel_flow;
CLAMP(fuel_in[index], 0.0f, 10.0f);
@@ -2518,12 +2258,8 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
}
}
- /* set color */
+ /* Set color. */
if (color_r && color_r_in) {
- color_r_in[index] = color_r[index];
- color_g_in[index] = color_g[index];
- color_b_in[index] = color_b[index];
-
if (dens_flow) {
float total_dens = density[index] / (dens_old + dens_flow);
color_r_in[index] = (color_r[index] + mfs->color[0] * dens_flow) * total_dens;
@@ -2532,7 +2268,7 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
}
}
- /* set fire reaction coordinate */
+ /* Set fire reaction coordinate. */
if (fuel && fuel_in) {
/* Instead of using 1.0 for all new fuel add slight falloff to reduce flow blocky-ness. */
float value = 1.0f - pow2f(1.0f - emission_value);
@@ -2542,9 +2278,6 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
react_in[index] = value * f + (1.0f - f) * react[index];
CLAMP(react_in[index], 0.0f, value);
}
- else {
- react_in[index] = react[index];
- }
}
}
@@ -2666,37 +2399,49 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
flowobjs = BKE_collision_objects_create(
depsgraph, ob, mds->fluid_group, &numflowobj, eModifierType_Fluid);
- /* Update all flow related flags and ensure that corresponding grids get initialized */
+ /* Update all flow related flags and ensure that corresponding grids get initialized. */
update_flowsflags(mds, flowobjs, numflowobj);
- /* init emission maps for each flow */
+ /* Initialize emission maps for each flow. */
emaps = MEM_callocN(sizeof(struct EmissionMap) * numflowobj, "manta_flow_maps");
- /* Prepare flow emission maps */
+ /* Prepare flow emission maps. */
for (flow_index = 0; flow_index < numflowobj; flow_index++) {
Object *flowobj = flowobjs[flow_index];
FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flowobj,
eModifierType_Fluid);
- /* Check for initialized smoke object */
+ /* Check for initialized smoke object. */
if ((mmd2->type & MOD_FLUID_TYPE_FLOW) && mmd2->flow) {
FluidFlowSettings *mfs = mmd2->flow;
int subframes = mfs->subframes;
EmissionMap *em = &emaps[flow_index];
+ /* Optimization: No need to compute emission value if it won't be applied. */
+ if (mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY && !is_first_frame) {
+ continue;
+ }
+ /* Optimization: Skip flow object if it does not "belong" to this domain type. */
+ if (mfs->type == FLUID_FLOW_TYPE_LIQUID && mds->type == FLUID_DOMAIN_TYPE_GAS) {
+ continue;
+ }
+ if ((mfs->type == FLUID_FLOW_TYPE_SMOKE || mfs->type == FLUID_FLOW_TYPE_FIRE ||
+ mfs->type == FLUID_FLOW_TYPE_SMOKEFIRE) &&
+ mds->type == FLUID_DOMAIN_TYPE_LIQUID) {
+ continue;
+ }
+
/* Length of one adaptive frame. If using adaptive stepping, length is smaller than actual
* frame length */
float adaptframe_length = time_per_frame / frame_length;
/* Adaptive frame length as percentage */
CLAMP(adaptframe_length, 0.0f, 1.0f);
- /* Further splitting because of emission subframe: If no subframes present, sample_size is 1
- */
+ /* More splitting because of emission subframe: If no subframes present, sample_size is 1. */
float sample_size = 1.0f / (float)(subframes + 1);
- int hires_multiplier = 1;
/* First frame cannot have any subframes because there is (obviously) no previous frame from
- * where subframes could come from */
+ * where subframes could come from. */
if (is_first_frame) {
subframes = 0;
}
@@ -2707,7 +2452,7 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
/* Emission loop. When not using subframes this will loop only once. */
for (subframe = subframes; subframe >= 0; subframe--) {
- /* Temporary emission map used when subframes are enabled, i.e. at least one subframe */
+ /* Temporary emission map used when subframes are enabled, i.e. at least one subframe. */
EmissionMap em_temp = {NULL};
/* Set scene time */
@@ -2718,22 +2463,22 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
scene->r.cfra = frame - 1;
}
/* Last frame in this loop (subframe == suframes). Can be real end frame or in between
- * frames (adaptive frame) */
+ * frames (adaptive frame). */
else {
/* Handle adaptive subframe (ie has subframe fraction). Need to set according scene
- * subframe parameter */
+ * subframe parameter. */
if (time_per_frame < frame_length) {
scene->r.subframe = adaptframe_length;
scene->r.cfra = frame - 1;
}
/* Handle absolute endframe (ie no subframe fraction). Need to set the scene subframe
- * parameter to 0 and advance current scene frame */
+ * parameter to 0 and advance current scene frame. */
else {
scene->r.subframe = 0.0f;
scene->r.cfra = frame;
}
}
- /* Sanity check: subframe portion must be between 0 and 1 */
+ /* Sanity check: subframe portion must be between 0 and 1. */
CLAMP(scene->r.subframe, 0.0f, 1.0f);
# ifdef DEBUG_PRINT
/* Debugging: Print subframe information. */
@@ -2748,11 +2493,11 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
/* Update frame time, this is considering current subframe fraction
* BLI_mutex_lock() called in manta_step(), so safe to update subframe here
* TODO (sebbas): Using BKE_scene_frame_get(scene) instead of new DEG_get_ctime(depsgraph)
- * as subframes don't work with the latter yet */
+ * as subframes don't work with the latter yet. */
BKE_object_modifier_update_subframe(
depsgraph, scene, flowobj, true, 5, BKE_scene_frame_get(scene), eModifierType_Fluid);
- /* Emission from particles */
+ /* Emission from particles. */
if (mfs->source == FLUID_FLOW_SOURCE_PARTICLES) {
if (subframes) {
emit_from_particles(flowobj, mds, mfs, &em_temp, depsgraph, scene, subframe_dt);
@@ -2760,12 +2505,8 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
else {
emit_from_particles(flowobj, mds, mfs, em, depsgraph, scene, subframe_dt);
}
-
- if (!(mfs->flags & FLUID_FLOW_USE_PART_SIZE)) {
- hires_multiplier = 1;
- }
}
- /* Emission from mesh */
+ /* Emission from mesh. */
else if (mfs->source == FLUID_FLOW_SOURCE_MESH) {
if (subframes) {
emit_from_mesh(flowobj, mds, mfs, &em_temp, subframe_dt);
@@ -2779,11 +2520,10 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
}
/* If this we emitted with temp emission map in this loop (subframe emission), we combine
- * the temp map with the original emission map */
+ * the temp map with the original emission map. */
if (subframes) {
- /* Combine emission maps */
- em_combineMaps(
- em, &em_temp, hires_multiplier, !(mfs->flags & FLUID_FLOW_ABSOLUTE), sample_size);
+ /* Combine emission maps. */
+ em_combineMaps(em, &em_temp, !(mfs->flags & FLUID_FLOW_ABSOLUTE), sample_size);
em_freeData(&em_temp);
}
}
@@ -2798,7 +2538,7 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
dt);
# endif
- /* Adjust domain size if needed. Only do this once for every frame */
+ /* Adjust domain size if needed. Only do this once for every frame. */
if (mds->type == FLUID_DOMAIN_TYPE_GAS && mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
adaptive_domain_adjust(mds, ob, emaps, numflowobj, dt);
}
@@ -2827,28 +2567,29 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
float *velz_initial = manta_get_in_velocity_z(mds->fluid);
uint z;
- /* Grid reset before writing again */
+ /* Grid reset before writing again. */
for (z = 0; z < mds->res[0] * mds->res[1] * mds->res[2]; z++) {
if (phi_in) {
- phi_in[z] = FLT_MAX;
+ phi_in[z] = PHI_MAX;
}
if (phiout_in) {
- phiout_in[z] = FLT_MAX;
+ phiout_in[z] = PHI_MAX;
}
+ /* Sync smoke inflow grids with their counterparts (simulation grids). */
if (density_in) {
- density_in[z] = 0.0f;
+ density_in[z] = density[z];
}
if (heat_in) {
- heat_in[z] = 0.0f;
+ heat_in[z] = heat[z];
}
if (color_r_in) {
- color_r_in[z] = 0.0f;
- color_g_in[z] = 0.0f;
- color_b_in[z] = 0.0f;
+ color_r_in[z] = color_r[z];
+ color_g_in[z] = color_b[z];
+ color_b_in[z] = color_g[z];
}
if (fuel_in) {
- fuel_in[z] = 0.0f;
- react_in[z] = 0.0f;
+ fuel_in[z] = fuel[z];
+ react_in[z] = react[z];
}
if (emission_in) {
emission_in[z] = 0.0f;
@@ -2860,13 +2601,13 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
}
}
- /* Apply emission data */
+ /* Apply emission data for every flow object. */
for (flow_index = 0; flow_index < numflowobj; flow_index++) {
Object *flowobj = flowobjs[flow_index];
FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flowobj,
eModifierType_Fluid);
- // check for initialized flow object
+ /* Check for initialized flow object. */
if ((mmd2->type & MOD_FLUID_TYPE_FLOW) && mmd2->flow) {
FluidFlowSettings *mfs = mmd2->flow;
EmissionMap *em = &emaps[flow_index];
@@ -2877,28 +2618,29 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
int gx, gy, gz, ex, ey, ez, dx, dy, dz;
size_t e_index, d_index;
- // loop through every emission map cell
+ /* Loop through every emission map cell. */
for (gx = em->min[0]; gx < em->max[0]; gx++) {
for (gy = em->min[1]; gy < em->max[1]; gy++) {
for (gz = em->min[2]; gz < em->max[2]; gz++) {
- /* get emission map index */
+ /* Compute emission map index. */
ex = gx - em->min[0];
ey = gy - em->min[1];
ez = gz - em->min[2];
e_index = manta_get_index(ex, em->res[0], ey, em->res[1], ez);
- /* get domain index */
+ /* Get domain index. */
dx = gx - mds->res_min[0];
dy = gy - mds->res_min[1];
dz = gz - mds->res_min[2];
d_index = manta_get_index(dx, mds->res[0], dy, mds->res[1], dz);
- /* make sure emission cell is inside the new domain boundary */
+ /* Make sure emission cell is inside the new domain boundary. */
if (dx < 0 || dy < 0 || dz < 0 || dx >= mds->res[0] || dy >= mds->res[1] ||
dz >= mds->res[2]) {
continue;
}
- if (mfs->behavior == FLUID_FLOW_BEHAVIOR_OUTFLOW) { // outflow
+ /* Delete fluid in outflow regions. */
+ if (mfs->behavior == FLUID_FLOW_BEHAVIOR_OUTFLOW) {
apply_outflow_fields(d_index,
distance_map[e_index],
density_in,
@@ -2910,10 +2652,11 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
color_b_in,
phiout_in);
}
- else if (mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY && mmd2->time > 2) {
+ /* Do not apply inflow after the first frame when in geometry mode. */
+ else if (mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY && !is_first_frame) {
apply_inflow_fields(mfs,
0.0f,
- FLT_MAX,
+ PHI_MAX,
d_index,
density_in,
density,
@@ -2932,8 +2675,9 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
phi_in,
emission_in);
}
+ /* Main inflow application. */
else if (mfs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW ||
- mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY) { // inflow
+ mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY) {
/* only apply inflow if enabled */
if (mfs->flags & FLUID_FLOW_USE_INFLOW) {
apply_inflow_fields(mfs,
@@ -2956,7 +2700,6 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
color_b,
phi_in,
emission_in);
- /* initial velocity */
if (mfs->flags & FLUID_FLOW_INITVELOCITY) {
velx_initial[d_index] = velocity_map[e_index * 3];
vely_initial[d_index] = velocity_map[e_index * 3 + 1];
@@ -2964,14 +2707,11 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
}
}
}
- } // low res loop
+ }
}
- }
-
- // free emission maps
+ } /* End of flow emission map loop. */
em_freeData(em);
-
- } // end emission
+ } /* End of flow object loop. */
}
BKE_collision_objects_free(flowobjs);
@@ -3161,7 +2901,7 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *mds, Mesh *orgmesh, Obj
// if reading raw data directly from manta, normalize now, otherwise omit this, ie when reading
// from files
- {
+ if (!manta_liquid_mesh_from_file(mds->fluid)) {
// normalize to unit cube around 0
mverts->co[0] -= ((float)mds->res[0] * mds->mesh_scale) * 0.5f;
mverts->co[1] -= ((float)mds->res[1] * mds->mesh_scale) * 0.5f;
@@ -3715,12 +3455,14 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
/* Read mesh cache. */
if (with_liquid && with_mesh) {
- has_mesh = manta_read_mesh(mds->fluid, mmd, mesh_frame);
+ /* Update mesh data from file is faster than via Python (manta_read_mesh()). */
+ has_mesh = manta_update_mesh_structures(mds->fluid, mmd, mesh_frame);
}
/* Read particles cache. */
if (with_liquid && with_particles) {
- has_particles = manta_read_particles(mds->fluid, mmd, particles_frame);
+ /* Update particle data from file is faster than via Python (manta_read_particles()). */
+ has_particles = manta_update_particle_structures(mds->fluid, mmd, particles_frame);
}
/* Read guide cache. */
@@ -3758,12 +3500,23 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
}
/* Read data cache only */
else {
- /* Read config and realloc fluid object if needed. */
- if (manta_read_config(mds->fluid, mmd, data_frame) && manta_needs_realloc(mds->fluid, mmd)) {
- BKE_fluid_reallocate_fluid(mds, mds->res, 1);
+ if (with_smoke) {
+ /* Read config and realloc fluid object if needed. */
+ if (manta_read_config(mds->fluid, mmd, data_frame) &&
+ manta_needs_realloc(mds->fluid, mmd)) {
+ BKE_fluid_reallocate_fluid(mds, mds->res, 1);
+ }
+ /* Read data cache */
+ has_data = manta_read_data(mds->fluid, mmd, data_frame);
+ }
+ if (with_liquid) {
+ if (!baking_data && !baking_particles && !baking_mesh && !mode_replay) {
+ has_data = manta_update_liquid_structures(mds->fluid, mmd, data_frame);
+ }
+ else {
+ has_data = manta_read_data(mds->fluid, mmd, data_frame);
+ }
}
- /* Read data cache */
- has_data = manta_read_data(mds->fluid, mmd, data_frame);
}
}
@@ -3857,15 +3610,47 @@ struct Mesh *BKE_fluid_modifier_do(
BLI_rw_mutex_unlock(mmd->domain->fluid_mutex);
}
+ /* Optimization: Do not update viewport during bakes (except in replay mode)
+ * Reason: UI is locked and updated liquid / smoke geometry is not visible anyways. */
+ bool needs_viewport_update = false;
+ if (mmd->domain) {
+ FluidDomainSettings *mds = mmd->domain;
+
+ /* Always update viewport in cache replay mode. */
+ if (mds->cache_type == FLUID_DOMAIN_CACHE_REPLAY ||
+ mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
+ needs_viewport_update = true;
+ }
+ /* In other cache modes, only update the viewport when no bake is going on. */
+ else {
+ bool with_mesh;
+ with_mesh = mds->flags & FLUID_DOMAIN_USE_MESH;
+ bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide;
+ baking_data = mds->cache_flag & FLUID_DOMAIN_BAKING_DATA;
+ baking_noise = mds->cache_flag & FLUID_DOMAIN_BAKING_NOISE;
+ baking_mesh = mds->cache_flag & FLUID_DOMAIN_BAKING_MESH;
+ baking_particles = mds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES;
+ baking_guide = mds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE;
+
+ if (with_mesh && !baking_data && !baking_noise && !baking_mesh && !baking_particles &&
+ !baking_guide) {
+ needs_viewport_update = true;
+ }
+ }
+ }
+
Mesh *result = NULL;
if (mmd->type & MOD_FLUID_TYPE_DOMAIN && mmd->domain) {
- /* Return generated geometry depending on domain type. */
- if (mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID) {
- result = create_liquid_geometry(mmd->domain, me, ob);
- }
- if (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS) {
- result = create_smoke_geometry(mmd->domain, me, ob);
+ if (needs_viewport_update) {
+ /* Return generated geometry depending on domain type. */
+ if (mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID) {
+ result = create_liquid_geometry(mmd->domain, me, ob);
+ }
+ if (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS) {
+ result = create_smoke_geometry(mmd->domain, me, ob);
+ }
}
+
/* Clear flag outside of locked block (above). */
mmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_DATA;
mmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_NOISE;
@@ -4190,7 +3975,7 @@ void BKE_fluid_particle_system_create(struct Main *bmain,
part->type = psys_type;
part->totpart = 0;
- part->draw_size = 0.01f; // make fluid particles more subtle in viewport
+ part->draw_size = 0.01f; /* Make fluid particles more subtle in viewport. */
part->draw_col = PART_DRAW_COL_VEL;
psys->part = part;
psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
@@ -4212,7 +3997,7 @@ void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_typ
for (psys = ob->particlesystem.first; psys; psys = next_psys) {
next_psys = psys->next;
- if (psys->part->type & particle_type) {
+ if (psys->part->type == particle_type) {
/* clear modifier */
pmmd = psys_get_modifier(ob, psys);
BLI_remlink(&ob->modifiers, pmmd);
@@ -4319,7 +4104,6 @@ void BKE_fluid_domain_type_set(Object *object, FluidDomainSettings *settings, in
BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_LEFT, 0);
BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_TOP, 0);
BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_BOTTOM, 0);
- BKE_fluid_particles_set(settings, FLUID_DOMAIN_PARTICLE_FLIP, 0);
object->dt = OB_SOLID;
}
@@ -4565,7 +4349,7 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd)
mmd->domain->particle_number = 2;
mmd->domain->particle_minimum = 8;
mmd->domain->particle_maximum = 16;
- mmd->domain->particle_radius = 1.5f;
+ mmd->domain->particle_radius = 1.0f;
mmd->domain->particle_band_width = 3.0f;
mmd->domain->fractions_threshold = 0.05f;
@@ -4624,9 +4408,9 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd)
mmd->domain->cache_flag = 0;
mmd->domain->cache_type = FLUID_DOMAIN_CACHE_MODULAR;
mmd->domain->cache_mesh_format = FLUID_DOMAIN_FILE_BIN_OBJECT;
- mmd->domain->cache_data_format = FLUID_DOMAIN_FILE_UNI;
- mmd->domain->cache_particle_format = FLUID_DOMAIN_FILE_UNI;
- mmd->domain->cache_noise_format = FLUID_DOMAIN_FILE_UNI;
+ mmd->domain->cache_data_format = FLUID_DOMAIN_FILE_OPENVDB;
+ mmd->domain->cache_particle_format = FLUID_DOMAIN_FILE_OPENVDB;
+ mmd->domain->cache_noise_format = FLUID_DOMAIN_FILE_OPENVDB;
modifier_path_init(mmd->domain->cache_directory,
sizeof(mmd->domain->cache_directory),
FLUID_DOMAIN_DIR_DEFAULT);
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index f72bb4b4cd4..8eb5cca1ad0 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -494,7 +494,7 @@ bGPDstroke *BKE_gpencil_add_stroke(bGPDframe *gpf, int mat_idx, int totpoints, s
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
/* initialize triangle memory to dummy data */
- gps->triangles = MEM_callocN(sizeof(bGPDtriangle), "GP Stroke triangulation");
+ gps->triangles = NULL;
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
gps->tot_triangles = 0;
@@ -939,9 +939,15 @@ bGPDframe *BKE_gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_M
gpl->actframe = gpf;
}
else {
- /* unresolved errogenous situation! */
- CLOG_STR_ERROR(&LOG, "cannot find appropriate gp-frame");
- /* gpl->actframe should still be NULL */
+ /* If delete first frame, need to find one. */
+ if (gpl->frames.first != NULL) {
+ gpl->actframe = gpl->frames.first;
+ }
+ else {
+ /* unresolved errogenous situation! */
+ CLOG_STR_ERROR(&LOG, "cannot find appropriate gp-frame");
+ /* gpl->actframe should still be NULL */
+ }
}
}
else {
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index fe087256d25..bc0c54ed96e 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -862,6 +862,14 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ /* Clear any previous evaluated data. */
+ if (ob->runtime.gpencil_tot_layers > 0) {
+ for (int i = 0; i < ob->runtime.gpencil_tot_layers; i++) {
+ bGPDframe *gpf_eval = &ob->runtime.gpencil_evaluated_frames[i];
+ BKE_gpencil_free_frame_runtime_data(gpf_eval);
+ }
+ }
+
/* Create array of evaluated frames equal to number of layers. */
ob->runtime.gpencil_tot_layers = BLI_listbase_count(&gpd->layers);
CLAMP_MIN(ob->runtime.gpencil_tot_layers, 1);
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 1125047be32..e3b27236616 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -461,6 +461,21 @@ static IDProperty *IDP_CopyID(const IDProperty *prop, const int flag)
return newp;
}
+void IDP_AssignID(IDProperty *prop, ID *id, const int flag)
+{
+ BLI_assert(prop->type == IDP_ID);
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0 && IDP_Id(prop) != NULL) {
+ id_us_min(IDP_Id(prop));
+ }
+
+ prop->data.pointer = id;
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus(IDP_Id(prop));
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 6d6e5166e1c..be354b04157 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -441,10 +441,9 @@ void BKE_image_copy_data(Main *UNUSED(bmain), Image *ima_dst, const Image *ima_s
BLI_listbase_clear(&ima_dst->anims);
BLI_duplicatelist(&ima_dst->tiles, &ima_src->tiles);
- LISTBASE_FOREACH (ImageTile *, tile, &ima_dst->tiles) {
- for (int i = 0; i < TEXTARGET_COUNT; i++) {
- tile->gputexture[i] = NULL;
- }
+
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ ima_dst->gputexture[i] = NULL;
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
@@ -510,11 +509,9 @@ bool BKE_image_scale(Image *image, int width, int height)
bool BKE_image_has_opengl_texture(Image *ima)
{
- LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
- for (int i = 0; i < TEXTARGET_COUNT; i++) {
- if (tile->gputexture[i] != NULL) {
- return true;
- }
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ if (ima->gputexture[i] != NULL) {
+ return true;
}
}
return false;
@@ -1348,6 +1345,7 @@ char BKE_imtype_valid_channels(const char imtype, bool write_file)
/* bw */
switch (imtype) {
+ case R_IMF_IMTYPE_BMP:
case R_IMF_IMTYPE_PNG:
case R_IMF_IMTYPE_JPEG90:
case R_IMF_IMTYPE_TARGA:
@@ -3293,9 +3291,16 @@ void BKE_image_init_imageuser(Image *ima, ImageUser *iuser)
static void image_free_tile(Image *ima, ImageTile *tile)
{
for (int i = 0; i < TEXTARGET_COUNT; i++) {
- if (tile->gputexture[i] != NULL) {
- GPU_texture_free(tile->gputexture[i]);
- tile->gputexture[i] = NULL;
+ /* Only two textures depends on all tiles, so if this is a secondary tile we can keep the other
+ * two. */
+ if (tile != ima->tiles.first &&
+ !(ELEM(i, TEXTARGET_TEXTURE_2D_ARRAY, TEXTARGET_TEXTURE_TILE_MAPPING))) {
+ continue;
+ }
+
+ if (ima->gputexture[i] != NULL) {
+ GPU_texture_free(ima->gputexture[i]);
+ ima->gputexture[i] = NULL;
}
}
@@ -3560,6 +3565,16 @@ ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *la
BLI_strncpy(tile->label, label, sizeof(tile->label));
}
+ /* Reallocate GPU tile array. */
+ if (ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY] != NULL) {
+ GPU_texture_free(ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY]);
+ ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY] = NULL;
+ }
+ if (ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING] != NULL) {
+ GPU_texture_free(ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING]);
+ ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING] = NULL;
+ }
+
return tile;
}
@@ -3877,7 +3892,12 @@ static void image_initialize_after_load(Image *ima, ImageUser *iuser, ImBuf *UNU
BKE_image_tag_time(ima);
ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
- tile->ok = IMA_OK_LOADED;
+ /* Images should never get loaded if the corresponding tile does not exist,
+ * but we should at least not crash if it happens due to a bug elsewhere. */
+ BLI_assert(tile != NULL);
+ if (tile != NULL) {
+ tile->ok = IMA_OK_LOADED;
+ }
}
static int imbuf_alpha_flags_for_image(Image *ima)
@@ -4750,14 +4770,14 @@ BLI_INLINE bool image_quick_test(Image *ima, ImageUser *iuser)
return false;
}
- ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
-
if (iuser) {
if (iuser->ok == 0) {
return false;
}
}
- else if (tile == NULL) {
+
+ ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
+ if (tile == NULL) {
return false;
}
else if (tile->ok == 0) {
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index bda1cac80e4..12a90906d1f 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -340,6 +340,23 @@ static void library_foreach_layer_collection(LibraryForeachIDData *data, ListBas
FOREACH_FINALIZE_VOID;
}
+/* Used by both real Collection data-blocks, and the fake horror of master collection from Scene.
+ */
+static void library_foreach_collection(LibraryForeachIDData *data, Collection *collection)
+{
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ FOREACH_CALLBACK_INVOKE(data, cob->ob, IDWALK_CB_USER);
+ }
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ FOREACH_CALLBACK_INVOKE(data, child->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_USER);
+ }
+ for (CollectionParent *parent = collection->parents.first; parent; parent = parent->next) {
+ FOREACH_CALLBACK_INVOKE(data, parent->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_LOOPBACK);
+ }
+
+ FOREACH_FINALIZE_VOID;
+}
+
static void library_foreach_ID_as_subdata_link(ID **id_pp,
LibraryIDLinkCallback callback,
void *user_data,
@@ -484,14 +501,7 @@ static void library_foreach_ID_link(Main *bmain,
SEQ_END;
}
- for (CollectionObject *cob = scene->master_collection->gobject.first; cob;
- cob = cob->next) {
- CALLBACK_INVOKE(cob->ob, IDWALK_CB_USER);
- }
- for (CollectionChild *child = scene->master_collection->children.first; child;
- child = child->next) {
- CALLBACK_INVOKE(child->collection, IDWALK_CB_USER);
- }
+ library_foreach_collection(&data, scene->master_collection);
if (scene->master_collection->lanpr) {
CALLBACK_INVOKE(scene->master_collection->lanpr->target, IDWALK_CB_USER);
@@ -804,15 +814,7 @@ static void library_foreach_ID_link(Main *bmain,
case ID_GR: {
Collection *collection = (Collection *)id;
- for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
- CALLBACK_INVOKE(cob->ob, IDWALK_CB_USER);
- }
- for (CollectionChild *child = collection->children.first; child; child = child->next) {
- CALLBACK_INVOKE(child->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_USER);
- }
- for (CollectionParent *parent = collection->parents.first; parent; parent = parent->next) {
- CALLBACK_INVOKE(parent->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_LOOPBACK);
- }
+ library_foreach_collection(&data, collection);
break;
}
diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c
index 06f1ee5050b..3cba3aa9611 100644
--- a/source/blender/blenkernel/intern/lightprobe.c
+++ b/source/blender/blenkernel/intern/lightprobe.c
@@ -41,6 +41,30 @@ void BKE_lightprobe_init(LightProbe *probe)
MEMCPY_STRUCT_AFTER(probe, DNA_struct_default_get(LightProbe), id);
}
+void BKE_lightprobe_type_set(LightProbe *probe, const short lightprobe_type)
+{
+ probe->type = lightprobe_type;
+
+ switch (probe->type) {
+ case LIGHTPROBE_TYPE_GRID:
+ probe->distinf = 0.3f;
+ probe->falloff = 1.0f;
+ probe->clipsta = 0.01f;
+ break;
+ case LIGHTPROBE_TYPE_PLANAR:
+ probe->distinf = 0.1f;
+ probe->falloff = 0.5f;
+ probe->clipsta = 0.001f;
+ break;
+ case LIGHTPROBE_TYPE_CUBE:
+ probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID;
+ break;
+ default:
+ BLI_assert(!"LightProbe type not configured.");
+ break;
+ }
+}
+
void *BKE_lightprobe_add(Main *bmain, const char *name)
{
LightProbe *probe;
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index 2ade368284c..fba84aaad42 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -522,7 +522,6 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob,
Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase)
{
- Curve *cu = ob->data;
Mesh *mesh;
MVert *allvert;
MEdge *alledge;
@@ -530,7 +529,6 @@ Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase)
MPoly *allpoly;
MLoopUV *alluv = NULL;
int totvert, totedge, totloop, totpoly;
- bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
if (BKE_mesh_nurbs_displist_to_mdata(ob,
dispbase,
@@ -540,7 +538,7 @@ Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase)
&totedge,
&allloop,
&allpoly,
- (use_orco_uv) ? &alluv : NULL,
+ &alluv,
&totloop,
&totpoly) != 0) {
/* Error initializing mdata. This often happens when curve is empty */
@@ -580,12 +578,8 @@ Mesh *BKE_mesh_new_nomain_from_curve(Object *ob)
}
/* this may fail replacing ob->data, be sure to check ob->type */
-void BKE_mesh_from_nurbs_displist(Main *bmain,
- Object *ob,
- ListBase *dispbase,
- const bool use_orco_uv,
- const char *obdata_name,
- bool temporary)
+void BKE_mesh_from_nurbs_displist(
+ Main *bmain, Object *ob, ListBase *dispbase, const char *obdata_name, bool temporary)
{
Object *ob1;
Mesh *me_eval = ob->runtime.mesh_eval;
@@ -609,7 +603,7 @@ void BKE_mesh_from_nurbs_displist(Main *bmain,
&totedge,
&allloop,
&allpoly,
- (use_orco_uv) ? &alluv : NULL,
+ &alluv,
&totloop,
&totpoly) != 0) {
/* Error initializing */
@@ -706,14 +700,13 @@ void BKE_mesh_from_nurbs_displist(Main *bmain,
void BKE_mesh_from_nurbs(Main *bmain, Object *ob)
{
Curve *cu = (Curve *)ob->data;
- bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
ListBase disp = {NULL, NULL};
if (ob->runtime.curve_cache) {
disp = ob->runtime.curve_cache->disp;
}
- BKE_mesh_from_nurbs_displist(bmain, ob, &disp, use_orco_uv, cu->id.name, false);
+ BKE_mesh_from_nurbs_displist(bmain, ob, &disp, cu->id.name, false);
}
typedef struct EdgeLink {
@@ -1023,8 +1016,6 @@ static void curve_to_mesh_eval_ensure(Object *object)
static Mesh *mesh_new_from_curve_type_object(Object *object)
{
Curve *curve = object->data;
- const bool uv_from_orco = (curve->flag & CU_UV_ORCO) != 0;
-
Object *temp_object = object_for_curve_to_mesh_create(object);
Curve *temp_curve = (Curve *)temp_object->data;
@@ -1039,12 +1030,8 @@ static Mesh *mesh_new_from_curve_type_object(Object *object)
temp_curve->editnurb = NULL;
/* Convert to mesh. */
- BKE_mesh_from_nurbs_displist(NULL,
- temp_object,
- &temp_object->runtime.curve_cache->disp,
- uv_from_orco,
- curve->id.name + 2,
- true);
+ BKE_mesh_from_nurbs_displist(
+ NULL, temp_object, &temp_object->runtime.curve_cache->disp, curve->id.name + 2, true);
/* BKE_mesh_from_nurbs changes the type to a mesh, check it worked. If it didn't the curve did
* not have any segments or otherwise would have generated an empty mesh. */
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index fa03aec3e08..4aa5bfa04ab 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -866,7 +866,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
tot_elem = mesh->totedge;
break;
case ME_FSEL:
- tot_elem = mesh->totface;
+ tot_elem = mesh->totpoly;
break;
}
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index a539aa45cf6..23fa8dd60d5 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -1289,13 +1289,9 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm, Scene *scene)
int i, j, numGrids, highGridSize, lowGridSize;
const bool has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK);
- /* create subsurf DM from original mesh at high level */
- if (ob->derivedDeform) {
- cddm = CDDM_copy(ob->derivedDeform);
- }
- else {
- cddm = CDDM_from_mesh(me);
- }
+ /* Create subsurf DM from original mesh at high level. */
+ /* TODO: use mesh_deform_eval when sculpting on deformed mesh. */
+ cddm = CDDM_from_mesh(me);
DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
highdm = subsurf_dm_create_local(scene,
@@ -1369,12 +1365,8 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm, Scene *scene)
DerivedMesh *cddm, *subdm;
const bool has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK);
- if (ob->derivedDeform) {
- cddm = CDDM_copy(ob->derivedDeform);
- }
- else {
- cddm = CDDM_from_mesh(me);
- }
+ /* TODO: use mesh_deform_eval when sculpting on deformed mesh. */
+ cddm = CDDM_from_mesh(me);
DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
subdm = subsurf_dm_create_local(scene,
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 09581debd99..7aa8837d139 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -1499,6 +1499,10 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
fcu->bezt->vec[1][0] = strip->start;
fcu->bezt->vec[1][1] = strip->influence;
+
+ /* Respect User Preferences for default interpolation and handles. */
+ fcu->bezt->h1 = fcu->bezt->h2 = U.keyhandles_new;
+ fcu->bezt->ipo = U.ipo_new;
}
}
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index be28ca26459..75e0d044c7c 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1089,7 +1089,11 @@ static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src,
/* keep socket listorder identical, for copying links */
/* ntree is the target tree */
-bNode *BKE_node_copy_ex(bNodeTree *ntree, const bNode *node_src, const int flag)
+/* unique_name needs to be true. It's only disabled for speed when doing GPUnodetrees. */
+bNode *BKE_node_copy_ex(bNodeTree *ntree,
+ const bNode *node_src,
+ const int flag,
+ const bool unique_name)
{
bNode *node_dst = MEM_callocN(sizeof(bNode), "dupli node");
bNodeSocket *sock_dst, *sock_src;
@@ -1098,7 +1102,9 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree, const bNode *node_src, const int flag)
*node_dst = *node_src;
/* can be called for nodes outside a node tree (e.g. clipboard) */
if (ntree) {
- nodeUniqueName(ntree, node_dst);
+ if (unique_name) {
+ nodeUniqueName(ntree, node_dst);
+ }
BLI_addtail(&ntree->nodes, node_dst);
}
@@ -1186,7 +1192,7 @@ static void node_set_new_pointers(bNode *node_src, bNode *new_node)
bNode *BKE_node_copy_store_new_pointers(bNodeTree *ntree, bNode *node_src, const int flag)
{
- bNode *new_node = BKE_node_copy_ex(ntree, node_src, flag);
+ bNode *new_node = BKE_node_copy_ex(ntree, node_src, flag, true);
node_set_new_pointers(node_src, new_node);
return new_node;
}
@@ -1516,7 +1522,7 @@ void BKE_node_tree_copy_data(Main *UNUSED(bmain),
GHash *new_pointers = BLI_ghash_ptr_new("BKE_node_tree_copy_data");
for (const bNode *node_src = ntree_src->nodes.first; node_src; node_src = node_src->next) {
- bNode *new_node = BKE_node_copy_ex(ntree_dst, node_src, flag_subdata);
+ bNode *new_node = BKE_node_copy_ex(ntree_dst, node_src, flag_subdata, true);
BLI_ghash_insert(new_pointers, (void *)node_src, new_node);
/* Store mapping to inputs. */
bNodeSocket *new_input_sock = new_node->inputs.first;
@@ -1595,7 +1601,7 @@ void BKE_node_tree_copy_data(Main *UNUSED(bmain),
bNodeTree *ntreeCopyTree_ex(const bNodeTree *ntree, Main *bmain, const bool do_id_user)
{
bNodeTree *ntree_copy;
- const int flag = do_id_user ? LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN : 0;
+ const int flag = do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN;
BKE_id_copy_ex(bmain, (ID *)ntree, (ID **)&ntree_copy, flag);
return ntree_copy;
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 10553e73d8d..90205286a72 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -430,7 +430,6 @@ void BKE_object_free_derived_caches(Object *ob)
MEM_SAFE_FREE(ob->runtime.bb);
object_update_from_subsurf_ccg(ob);
- BKE_object_free_derived_mesh_caches(ob);
/* Restore initial pointer. */
if (ob->runtime.mesh_orig != NULL) {
@@ -457,20 +456,6 @@ void BKE_object_free_derived_caches(Object *ob)
DRW_gpencil_freecache(ob);
}
-void BKE_object_free_derived_mesh_caches(struct Object *ob)
-{
- if (ob->derivedFinal) {
- ob->derivedFinal->needsFree = 1;
- ob->derivedFinal->release(ob->derivedFinal);
- ob->derivedFinal = NULL;
- }
- if (ob->derivedDeform) {
- ob->derivedDeform->needsFree = 1;
- ob->derivedDeform->release(ob->derivedDeform);
- ob->derivedDeform = NULL;
- }
-}
-
void BKE_object_free_caches(Object *object)
{
ModifierData *md;
@@ -804,6 +789,8 @@ static const char *get_obdata_defname(int type)
return DATA_("Empty");
case OB_GPENCIL:
return DATA_("GPencil");
+ case OB_LIGHTPROBE:
+ return DATA_("LightProbe");
default:
CLOG_ERROR(&LOG, "Internal error, bad type: %d", type);
return DATA_("Empty");
@@ -1323,7 +1310,7 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
{
copy_v3_v3(ob_tar->loc, ob_src->loc);
copy_v3_v3(ob_tar->rot, ob_src->rot);
- copy_v3_v3(ob_tar->quat, ob_src->quat);
+ copy_v4_v4(ob_tar->quat, ob_src->quat);
copy_v3_v3(ob_tar->rotAxis, ob_src->rotAxis);
ob_tar->rotAngle = ob_src->rotAngle;
ob_tar->rotmode = ob_src->rotmode;
@@ -1425,9 +1412,6 @@ void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, con
BKE_object_copy_particlesystems(ob_dst, ob_src, flag_subdata);
- ob_dst->derivedDeform = NULL;
- ob_dst->derivedFinal = NULL;
-
BLI_listbase_clear((ListBase *)&ob_dst->drawdata);
BLI_listbase_clear(&ob_dst->pc_ids);
@@ -2330,40 +2314,38 @@ static void give_parvert(Object *par, int nr, float vec[3])
int count = 0;
const int numVerts = me_eval->totvert;
- if (nr < numVerts) {
- if (em && me_eval->runtime.is_original) {
- if (em->bm->elem_table_dirty & BM_VERT) {
+ if (em && me_eval->runtime.is_original) {
+ if (em->bm->elem_table_dirty & BM_VERT) {
#ifdef VPARENT_THREADING_HACK
- BLI_mutex_lock(&vparent_lock);
- if (em->bm->elem_table_dirty & BM_VERT) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- }
- BLI_mutex_unlock(&vparent_lock);
-#else
- BLI_assert(!"Not safe for threading");
+ BLI_mutex_lock(&vparent_lock);
+ if (em->bm->elem_table_dirty & BM_VERT) {
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
-#endif
}
+ BLI_mutex_unlock(&vparent_lock);
+#else
+ BLI_assert(!"Not safe for threading");
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+#endif
}
+ }
- if (CustomData_has_layer(&me_eval->vdata, CD_ORIGINDEX) &&
- !(em && me_eval->runtime.is_original)) {
- const int *index = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
- /* Get the average of all verts with (original index == nr). */
- for (int i = 0; i < numVerts; i++) {
- if (index[i] == nr) {
- add_v3_v3(vec, me_eval->mvert[i].co);
- count++;
- }
- }
- }
- else {
- if (nr < numVerts) {
- add_v3_v3(vec, me_eval->mvert[nr].co);
+ if (CustomData_has_layer(&me_eval->vdata, CD_ORIGINDEX) &&
+ !(em && me_eval->runtime.is_original)) {
+ const int *index = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
+ /* Get the average of all verts with (original index == nr). */
+ for (int i = 0; i < numVerts; i++) {
+ if (index[i] == nr) {
+ add_v3_v3(vec, me_eval->mvert[i].co);
count++;
}
}
}
+ else {
+ if (nr < numVerts) {
+ add_v3_v3(vec, me_eval->mvert[nr].co);
+ count++;
+ }
+ }
if (count == 0) {
/* keep as 0, 0, 0 */
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 21ca5e6d6a6..366fd0950fa 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -163,9 +163,6 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? BKE_editmesh_from_object(ob) : NULL;
#else
BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? ((Mesh *)ob->data)->edit_mesh : NULL;
- if (em && em->ob != ob) {
- em = NULL;
- }
#endif
CustomData_MeshMasks cddata_masks = scene->customdata_mask;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 584f1ab1b0c..46c2f735761 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -79,7 +79,7 @@ const char PAINT_CURSOR_VERTEX_PAINT[3] = {255, 255, 255};
const char PAINT_CURSOR_WEIGHT_PAINT[3] = {200, 200, 255};
const char PAINT_CURSOR_TEXTURE_PAINT[3] = {255, 255, 255};
-static eOverlayControlFlags overlay_flags = 0;
+static ePaintOverlayControlFlags overlay_flags = 0;
void BKE_paint_invalidate_overlay_tex(Scene *scene, ViewLayer *view_layer, const Tex *tex)
{
@@ -120,7 +120,7 @@ void BKE_paint_invalidate_overlay_all(void)
PAINT_OVERLAY_INVALID_TEXTURE_PRIMARY | PAINT_OVERLAY_INVALID_CURVE);
}
-eOverlayControlFlags BKE_paint_get_overlay_flags(void)
+ePaintOverlayControlFlags BKE_paint_get_overlay_flags(void)
{
return overlay_flags;
}
@@ -143,7 +143,7 @@ void BKE_paint_set_overlay_override(eOverlayFlags flags)
}
}
-void BKE_paint_reset_overlay_invalid(eOverlayControlFlags flag)
+void BKE_paint_reset_overlay_invalid(ePaintOverlayControlFlags flag)
{
overlay_flags &= ~(flag);
}
@@ -1019,15 +1019,12 @@ static void sculptsession_free_pbvh(Object *object)
ss->pbvh = NULL;
}
- if (ss->pmap) {
- MEM_freeN(ss->pmap);
- ss->pmap = NULL;
- }
+ MEM_SAFE_FREE(ss->pmap);
- if (ss->pmap_mem) {
- MEM_freeN(ss->pmap_mem);
- ss->pmap_mem = NULL;
- }
+ MEM_SAFE_FREE(ss->pmap_mem);
+
+ MEM_SAFE_FREE(ss->preview_vert_index_list);
+ ss->preview_vert_index_count = 0;
}
void BKE_sculptsession_bm_to_me_for_render(Object *object)
@@ -1096,6 +1093,14 @@ void BKE_sculptsession_free(Object *ob)
MEM_freeN(ss->preview_vert_index_list);
}
+ if (ss->pose_ik_chain_preview) {
+ for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) {
+ MEM_SAFE_FREE(ss->pose_ik_chain_preview->segments[i].weights);
+ }
+ MEM_SAFE_FREE(ss->pose_ik_chain_preview->segments);
+ MEM_SAFE_FREE(ss->pose_ik_chain_preview);
+ }
+
BKE_sculptsession_free_vwpaint_data(ob->sculpt);
MEM_freeN(ss);
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index ded38cf562f..97fcef4fd27 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -3246,22 +3246,24 @@ static void psys_cache_edit_paths_iter(void *__restrict iter_data_v,
}
}
else {
+ /* HACK(fclem): Instead of setting the color we pass the select state in the red channel.
+ * This is then picked up in DRW and the gpu shader will do the color interpolation. */
if ((ekey + (pind.ekey[0] - point->keys))->flag & PEK_SELECT) {
if ((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT) {
- copy_v3_v3(ca->col, iter_data->sel_col);
+ ca->col[0] = 1.0f;
}
else {
keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
- interp_v3_v3v3(ca->col, iter_data->sel_col, iter_data->nosel_col, keytime);
+ ca->col[0] = 1.0f - keytime;
}
}
else {
if ((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT) {
keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
- interp_v3_v3v3(ca->col, iter_data->nosel_col, iter_data->sel_col, keytime);
+ ca->col[0] = keytime;
}
else {
- copy_v3_v3(ca->col, iter_data->nosel_col);
+ ca->col[0] = 0.0f;
}
}
}
@@ -3565,7 +3567,9 @@ ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob,
psys->totpart = 0;
psys->flag = PSYS_CURRENT;
- psys->cfra = BKE_scene_frame_to_ctime(scene, CFRA + 1);
+ if (scene != NULL) {
+ psys->cfra = BKE_scene_frame_to_ctime(scene, CFRA + 1);
+ }
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@@ -3582,14 +3586,47 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob
return;
}
- /* clear all other appearances of this pointer (like on manta flow modifier) */
+ /* Clear particle system in fluid modifier. */
if ((md = modifiers_findByType(ob, eModifierType_Fluid))) {
FluidModifierData *mmd = (FluidModifierData *)md;
+
+ /* Clear particle system pointer in flow settings. */
if ((mmd->type == MOD_FLUID_TYPE_FLOW) && mmd->flow && mmd->flow->psys) {
if (mmd->flow->psys == psys) {
mmd->flow->psys = NULL;
}
}
+ /* Clear particle flag in domain settings when removing particle system manually. */
+ if (mmd->type == MOD_FLUID_TYPE_DOMAIN) {
+ if (psys->part->type == PART_FLUID_FLIP) {
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP;
+ }
+ if (psys->part->type == PART_FLUID_SPRAY || psys->part->type == PART_FLUID_SPRAYFOAM ||
+ psys->part->type == PART_FLUID_SPRAYBUBBLE ||
+ psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) {
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_SPRAY;
+ }
+ if (psys->part->type == PART_FLUID_FOAM || psys->part->type == PART_FLUID_SPRAYFOAM ||
+ psys->part->type == PART_FLUID_FOAMBUBBLE ||
+ psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) {
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FOAM;
+ }
+ if (psys->part->type == PART_FLUID_BUBBLE || psys->part->type == PART_FLUID_FOAMBUBBLE ||
+ psys->part->type == PART_FLUID_SPRAYBUBBLE ||
+ psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) {
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_BUBBLE;
+ }
+ if (psys->part->type == PART_FLUID_TRACER) {
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_TRACER;
+ }
+
+ /* Disable combined export if combined particle system was deleted. */
+ if (psys->part->type == PART_FLUID_SPRAYFOAM || psys->part->type == PART_FLUID_SPRAYBUBBLE ||
+ psys->part->type == PART_FLUID_FOAMBUBBLE ||
+ psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) {
+ mmd->domain->sndparticle_combined_export = SNDPARTICLE_COMBINED_EXPORT_OFF;
+ }
+ }
}
if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint))) {
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 34f2aa73817..172940760f9 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -4137,6 +4137,34 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_
}
}
+static bool particles_has_flip(short parttype)
+{
+ return (parttype == PART_FLUID_FLIP);
+}
+
+static bool particles_has_tracer(short parttype)
+{
+ return (parttype == PART_FLUID_TRACER);
+}
+
+static bool particles_has_spray(short parttype)
+{
+ return ((parttype == PART_FLUID_SPRAY) || (parttype == PART_FLUID_SPRAYFOAM) ||
+ (parttype == PART_FLUID_SPRAYFOAMBUBBLE));
+}
+
+static bool particles_has_bubble(short parttype)
+{
+ return ((parttype == PART_FLUID_BUBBLE) || (parttype == PART_FLUID_FOAMBUBBLE) ||
+ (parttype == PART_FLUID_SPRAYFOAMBUBBLE));
+}
+
+static bool particles_has_foam(short parttype)
+{
+ return ((parttype == PART_FLUID_FOAM) || (parttype == PART_FLUID_SPRAYFOAM) ||
+ (parttype == PART_FLUID_SPRAYFOAMBUBBLE));
+}
+
static void particles_fluid_step(ParticleSimulationData *sim,
int cfra,
const bool use_render_params)
@@ -4173,15 +4201,15 @@ static void particles_fluid_step(ParticleSimulationData *sim,
float min[3], max[3], size[3], cell_size_scaled[3], max_size;
/* Sanity check: parts also enabled in fluid domain? */
- if ((part->type == PART_FLUID_FLIP &&
+ if ((particles_has_flip(part->type) &&
(mds->particle_type & FLUID_DOMAIN_PARTICLE_FLIP) == 0) ||
- (part->type == PART_FLUID_SPRAY &&
+ (particles_has_spray(part->type) &&
(mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) == 0) ||
- (part->type == PART_FLUID_BUBBLE &&
+ (particles_has_bubble(part->type) &&
(mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) == 0) ||
- (part->type == PART_FLUID_FOAM &&
+ (particles_has_foam(part->type) &&
(mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) == 0) ||
- (part->type == PART_FLUID_TRACER &&
+ (particles_has_tracer(part->type) &&
(mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) == 0)) {
BLI_snprintf(debugStrBuffer,
sizeof(debugStrBuffer),
@@ -4194,23 +4222,23 @@ static void particles_fluid_step(ParticleSimulationData *sim,
if (part->type == PART_FLUID_FLIP) {
tottypepart = totpart = manta_liquid_get_num_flip_particles(mds->fluid);
}
- if ((part->type == PART_FLUID_SPRAY) || (part->type == PART_FLUID_BUBBLE) ||
- (part->type == PART_FLUID_FOAM) || (part->type == PART_FLUID_TRACER)) {
+ if (particles_has_spray(part->type) || particles_has_bubble(part->type) ||
+ particles_has_foam(part->type) || particles_has_tracer(part->type)) {
totpart = manta_liquid_get_num_snd_particles(mds->fluid);
/* tottypepart is the amount of particles of a snd particle type. */
for (p = 0; p < totpart; p++) {
flagActivePart = manta_liquid_get_snd_particle_flag_at(mds->fluid, p);
- if ((part->type & PART_FLUID_SPRAY) && (flagActivePart & PARTICLE_TYPE_SPRAY)) {
+ if (particles_has_spray(part->type) && (flagActivePart & PARTICLE_TYPE_SPRAY)) {
tottypepart++;
}
- if ((part->type & PART_FLUID_BUBBLE) && (flagActivePart & PARTICLE_TYPE_BUBBLE)) {
+ if (particles_has_bubble(part->type) && (flagActivePart & PARTICLE_TYPE_BUBBLE)) {
tottypepart++;
}
- if ((part->type & PART_FLUID_FOAM) && (flagActivePart & PARTICLE_TYPE_FOAM)) {
+ if (particles_has_foam(part->type) && (flagActivePart & PARTICLE_TYPE_FOAM)) {
tottypepart++;
}
- if ((part->type & PART_FLUID_TRACER) && (flagActivePart & PARTICLE_TYPE_TRACER)) {
+ if (particles_has_tracer(part->type) && (flagActivePart & PARTICLE_TYPE_TRACER)) {
tottypepart++;
}
}
@@ -4261,8 +4289,8 @@ static void particles_fluid_step(ParticleSimulationData *sim,
velY = manta_liquid_get_flip_particle_velocity_y_at(mds->fluid, p);
velZ = manta_liquid_get_flip_particle_velocity_z_at(mds->fluid, p);
}
- else if ((part->type == PART_FLUID_SPRAY) || (part->type == PART_FLUID_BUBBLE) ||
- (part->type == PART_FLUID_FOAM) || (part->type == PART_FLUID_TRACER)) {
+ else if (particles_has_spray(part->type) || particles_has_bubble(part->type) ||
+ particles_has_foam(part->type) || particles_has_tracer(part->type)) {
flagActivePart = manta_liquid_get_snd_particle_flag_at(mds->fluid, p);
resX = (float)manta_liquid_get_particle_res_x(mds->fluid);
@@ -4292,16 +4320,16 @@ static void particles_fluid_step(ParticleSimulationData *sim,
/* Type of particle must match current particle system type
* (only important for snd particles). */
- if ((flagActivePart & PARTICLE_TYPE_SPRAY) && (part->type & PART_FLUID_SPRAY) == 0) {
+ if ((flagActivePart & PARTICLE_TYPE_SPRAY) && !particles_has_spray(part->type)) {
continue;
}
- if ((flagActivePart & PARTICLE_TYPE_BUBBLE) && (part->type & PART_FLUID_BUBBLE) == 0) {
+ if ((flagActivePart & PARTICLE_TYPE_BUBBLE) && !particles_has_bubble(part->type)) {
continue;
}
- if ((flagActivePart & PARTICLE_TYPE_FOAM) && (part->type & PART_FLUID_FOAM) == 0) {
+ if ((flagActivePart & PARTICLE_TYPE_FOAM) && !particles_has_foam(part->type)) {
continue;
}
- if ((flagActivePart & PARTICLE_TYPE_TRACER) && (part->type & PART_FLUID_TRACER) == 0) {
+ if ((flagActivePart & PARTICLE_TYPE_TRACER) && !particles_has_tracer(part->type)) {
continue;
}
# if 0
@@ -4844,9 +4872,9 @@ void particle_system_update(struct Depsgraph *depsgraph,
hair_step(&sim, cfra, use_render_params);
}
}
- else if ((part->type == PART_FLUID_FLIP) || (part->type == PART_FLUID_SPRAY) ||
- (part->type == PART_FLUID_BUBBLE) || (part->type == PART_FLUID_FOAM) ||
- (part->type == PART_FLUID_TRACER)) {
+ else if (particles_has_flip(part->type) || particles_has_spray(part->type) ||
+ particles_has_bubble(part->type) || particles_has_foam(part->type) ||
+ particles_has_tracer(part->type)) {
particles_fluid_step(&sim, (int)cfra, use_render_params);
}
else {
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 01612ded396..ec520e188f1 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1120,7 +1120,7 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
{
if (vd.mask && *vd.mask < 1.0f) {
has_unmasked = true;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index bfaea9d438b..75b9f558e90 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -374,6 +374,13 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
sce_dst->preview = NULL;
}
+ BKE_scene_copy_data_eevee(sce_dst, sce_src);
+}
+
+void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src)
+{
+ /* Copy eevee data between scenes. */
+ sce_dst->eevee = sce_src->eevee;
sce_dst->eevee.light_cache = NULL;
sce_dst->eevee.light_cache_info[0] = '\0';
/* TODO Copy the cache. */
@@ -401,9 +408,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
sce_copy->unit = sce->unit;
sce_copy->physics_settings = sce->physics_settings;
sce_copy->audio = sce->audio;
- sce_copy->eevee = sce->eevee;
- sce_copy->eevee.light_cache = NULL;
- sce_copy->eevee.light_cache_info[0] = '\0';
+ BKE_scene_copy_data_eevee(sce_copy, sce);
if (sce->id.properties) {
sce_copy->id.properties = IDP_CopyProperty(sce->id.properties);
@@ -1412,6 +1417,19 @@ static void scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain, bool on
if (run_callbacks) {
BKE_callback_exec_id_depsgraph(
bmain, &scene->id, depsgraph, BKE_CB_EVT_DEPSGRAPH_UPDATE_POST);
+
+ /* It is possible that the custom callback modified scene and removed some IDs from the main
+ * database. In this case DEG_ids_clear_recalc() will crash because it iterates over all IDs
+ * which depsgraph was built for.
+ *
+ * The solution is to update relations prior to this call, avoiding access to freed IDs.
+ * Should be safe because relations update is supposed to preserve flags of all IDs which are
+ * still a part of the dependency graph. If an ID is kicked out of the dependency graph it
+ * should also be fine because when/if it's added to another dependency graph it will need to
+ * be tagged for an update anyway.
+ *
+ * If there are no relations changed by the callback this call will do nothing. */
+ DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
}
/* Inform editors about possible changes. */
DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, false);
@@ -1477,6 +1495,10 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph, Main *bmain)
/* Notify editors and python about recalc. */
if (pass == 0) {
BKE_callback_exec_id_depsgraph(bmain, &scene->id, depsgraph, BKE_CB_EVT_FRAME_CHANGE_POST);
+
+ /* NOTE: Similar to this case in scene_graph_update_tagged(). Need to ensure that
+ * DEG_ids_clear_recalc() doesn't access freed memory of possibly removed ID. */
+ DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
}
/* Inform editors about possible changes. */
@@ -2253,7 +2275,16 @@ void BKE_scene_cursor_mat3_to_rot(View3DCursor *cursor, const float mat[3][3], b
switch (cursor->rotation_mode) {
case ROT_MODE_QUAT: {
- mat3_normalized_to_quat(cursor->rotation_quaternion, mat);
+ float quat[4];
+ mat3_normalized_to_quat(quat, mat);
+ if (use_compat) {
+ float quat_orig[4];
+ copy_v4_v4(quat_orig, cursor->rotation_quaternion);
+ quat_to_compatible_quat(cursor->rotation_quaternion, quat, quat_orig);
+ }
+ else {
+ copy_v4_v4(cursor->rotation_quaternion, quat);
+ }
break;
}
case ROT_MODE_AXISANGLE: {
@@ -2279,7 +2310,14 @@ void BKE_scene_cursor_quat_to_rot(View3DCursor *cursor, const float quat[4], boo
switch (cursor->rotation_mode) {
case ROT_MODE_QUAT: {
- copy_qt_qt(cursor->rotation_quaternion, quat);
+ if (use_compat) {
+ float quat_orig[4];
+ copy_v4_v4(quat_orig, cursor->rotation_quaternion);
+ quat_to_compatible_quat(cursor->rotation_quaternion, quat, quat_orig);
+ }
+ else {
+ copy_qt_qt(cursor->rotation_quaternion, quat);
+ }
break;
}
case ROT_MODE_AXISANGLE: {
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 236fb43e89c..8dfe01ae1fd 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -3888,7 +3888,7 @@ static ImBuf *do_text_effect(const SeqRenderData *context,
int font = blf_mono_font_render;
int line_height;
int y_ofs, x, y;
- float proxy_size_comp;
+ double proxy_size_comp;
if (data->text_blf_id == SEQ_FONT_NOT_LOADED) {
data->text_blf_id = -1;
@@ -3906,15 +3906,11 @@ static ImBuf *do_text_effect(const SeqRenderData *context,
display = IMB_colormanagement_display_get_named(display_device);
/* Compensate text size for preview render size. */
- if (ELEM(
- context->preview_render_size, SEQ_PROXY_RENDER_SIZE_SCENE, SEQ_PROXY_RENDER_SIZE_FULL)) {
- proxy_size_comp = context->scene->r.size / 100.0f;
- }
- else if (context->preview_render_size == SEQ_PROXY_RENDER_SIZE_100) {
- proxy_size_comp = 1.0f;
+ if (context->preview_render_size == SEQ_PROXY_RENDER_SIZE_SCENE) {
+ proxy_size_comp = context->scene->r.size / 100.0;
}
else {
- proxy_size_comp = context->preview_render_size / 100.0f;
+ proxy_size_comp = BKE_sequencer_rendersize_to_scale_factor(context->preview_render_size);
}
/* set before return */
diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c
index 6dd1c47407f..8c9097e1d4e 100644
--- a/source/blender/blenkernel/intern/seqprefetch.c
+++ b/source/blender/blenkernel/intern/seqprefetch.c
@@ -416,9 +416,7 @@ static PrefetchJob *seq_prefetch_start(const SeqRenderData *context, float cfra)
pfjob->stop = false;
pfjob->running = true;
- if (&pfjob->threads) {
- BLI_threadpool_remove(&pfjob->threads, pfjob);
- }
+ BLI_threadpool_remove(&pfjob->threads, pfjob);
BLI_threadpool_insert(&pfjob->threads, pfjob);
return pfjob;
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index b05724ca6af..747ce18cada 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -38,6 +38,7 @@
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_sound_types.h"
+#include "DNA_space_types.h"
#include "BLI_math.h"
#include "BLI_fileops.h"
@@ -1587,35 +1588,32 @@ typedef struct SeqIndexBuildContext {
#define PROXY_MAXFILE (2 * FILE_MAXDIR + FILE_MAXFILE)
-static IMB_Proxy_Size seq_rendersize_to_proxysize(int size)
+static IMB_Proxy_Size seq_rendersize_to_proxysize(int render_size)
{
- if (size >= 100) {
- return IMB_PROXY_NONE;
+ switch (render_size) {
+ case SEQ_PROXY_RENDER_SIZE_25:
+ return IMB_PROXY_25;
+ case SEQ_PROXY_RENDER_SIZE_50:
+ return IMB_PROXY_50;
+ case SEQ_PROXY_RENDER_SIZE_75:
+ return IMB_PROXY_75;
+ case SEQ_PROXY_RENDER_SIZE_100:
+ return IMB_PROXY_100;
}
- if (size >= 99) {
- return IMB_PROXY_100;
- }
- if (size >= 75) {
- return IMB_PROXY_75;
- }
- if (size >= 50) {
- return IMB_PROXY_50;
- }
- return IMB_PROXY_25;
+ return IMB_PROXY_NONE;
}
-static double seq_rendersize_to_scale_factor(int size)
+double BKE_sequencer_rendersize_to_scale_factor(int render_size)
{
- if (size >= 99) {
- return 1.0;
- }
- if (size >= 75) {
- return 0.75;
+ switch (render_size) {
+ case SEQ_PROXY_RENDER_SIZE_25:
+ return 0.25;
+ case SEQ_PROXY_RENDER_SIZE_50:
+ return 0.50;
+ case SEQ_PROXY_RENDER_SIZE_75:
+ return 0.75;
}
- if (size >= 50) {
- return 0.50;
- }
- return 0.25;
+ return 1.0;
}
/* the number of files will vary according to the stereo format */
@@ -1773,8 +1771,12 @@ static void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile)
}
}
-static bool seq_proxy_get_fname(
- Editing *ed, Sequence *seq, int cfra, int render_size, char *name, const int view_id)
+static bool seq_proxy_get_fname(Editing *ed,
+ Sequence *seq,
+ int cfra,
+ eSpaceSeq_Proxy_RenderSize render_size,
+ char *name,
+ const int view_id)
{
int frameno;
char dir[PROXY_MAXFILE];
@@ -1868,19 +1870,21 @@ static bool seq_proxy_get_fname(
/* generate a separate proxy directory for each preview size */
+ int proxy_size_number = BKE_sequencer_rendersize_to_scale_factor(render_size) * 100;
+
if (seq->type == SEQ_TYPE_IMAGE) {
BLI_snprintf(name,
PROXY_MAXFILE,
"%s/images/%d/%s_proxy%s",
dir,
- render_size,
+ proxy_size_number,
BKE_sequencer_give_stripelem(seq, cfra)->name,
suffix);
frameno = 1;
}
else {
frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs;
- BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####%s", dir, render_size, suffix);
+ BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####%s", dir, proxy_size_number, suffix);
}
BLI_path_abs(name, BKE_main_blendfile_path_from_global());
@@ -1896,7 +1900,6 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
char name[PROXY_MAXFILE];
IMB_Proxy_Size psize = seq_rendersize_to_proxysize(context->preview_render_size);
int size_flags;
- int render_size = context->preview_render_size;
StripProxy *proxy = seq->strip->proxy;
Editing *ed = context->scene->ed;
StripAnim *sanim;
@@ -1905,22 +1908,17 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
return NULL;
}
- /* dirty hack to distinguish 100% render size from PROXY_100 */
- if (render_size == 99) {
- render_size = 100;
- }
-
size_flags = proxy->build_size_flags;
/* only use proxies, if they are enabled (even if present!) */
- if (psize == IMB_PROXY_NONE || ((size_flags & psize) != psize)) {
+ if (psize == IMB_PROXY_NONE || (size_flags & psize) == 0) {
return NULL;
}
if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) {
int frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs;
if (proxy->anim == NULL) {
- if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) {
+ if (seq_proxy_get_fname(ed, seq, cfra, psize, name, context->view_id) == 0) {
return NULL;
}
@@ -1939,7 +1937,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE);
}
- if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) {
+ if (seq_proxy_get_fname(ed, seq, cfra, psize, name, context->view_id) == 0) {
return NULL;
}
@@ -2700,10 +2698,10 @@ static ImBuf *input_preprocess(const SeqRenderData *context,
int sx, sy, dx, dy;
if (is_proxy_image) {
- double f = seq_rendersize_to_scale_factor(context->preview_render_size);
+ double f = BKE_sequencer_rendersize_to_scale_factor(context->preview_render_size);
if (f != 1.0) {
- IMB_scalefastImBuf(ibuf, ibuf->x / f, ibuf->y / f);
+ IMB_scalefastImBuf(ibuf, ibuf->x * f, ibuf->y * f);
}
}
@@ -3151,12 +3149,11 @@ static ImBuf *seq_render_movie_strip(const SeqRenderData *context,
bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 &&
(context->scene->r.scemode & R_MULTIVIEW) != 0;
- IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size);
+ IMB_Proxy_Size psize = seq_rendersize_to_proxysize(context->preview_render_size);
if ((seq->flag & SEQ_USE_PROXY) == 0) {
- proxy_size = IMB_PROXY_NONE;
+ psize = IMB_PROXY_NONE;
}
-
/* load all the videos */
seq_open_anim_file(context->scene, seq, false);
@@ -3181,10 +3178,10 @@ static ImBuf *seq_render_movie_strip(const SeqRenderData *context,
nr + seq->anim_startofs,
seq->strip->proxy ? seq->strip->proxy->tc :
IMB_TC_RECORD_RUN,
- proxy_size);
+ psize);
/* fetching for requested proxy size failed, try fetching the original instead */
- if (!ibuf_arr[i] && proxy_size != IMB_PROXY_NONE) {
+ if (!ibuf_arr[i] && psize != IMB_PROXY_NONE) {
ibuf_arr[i] = IMB_anim_absolute(sanim->anim,
nr + seq->anim_startofs,
seq->strip->proxy ? seq->strip->proxy->tc :
@@ -3250,10 +3247,10 @@ static ImBuf *seq_render_movie_strip(const SeqRenderData *context,
ibuf = IMB_anim_absolute(sanim->anim,
nr + seq->anim_startofs,
seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
- proxy_size);
+ psize);
/* fetching for requested proxy size failed, try fetching the original instead */
- if (!ibuf && proxy_size != IMB_PROXY_NONE) {
+ if (!ibuf && psize != IMB_PROXY_NONE) {
ibuf = IMB_anim_absolute(sanim->anim,
nr + seq->anim_startofs,
seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
@@ -3280,6 +3277,7 @@ static ImBuf *seq_render_movieclip_strip(const SeqRenderData *context, Sequence
ImBuf *ibuf = NULL;
MovieClipUser user;
float tloc[2], tscale, tangle;
+ IMB_Proxy_Size psize = seq_rendersize_to_proxysize(context->preview_render_size);
if (!seq->clip) {
return NULL;
@@ -3292,7 +3290,7 @@ static ImBuf *seq_render_movieclip_strip(const SeqRenderData *context, Sequence
user.render_flag |= MCLIP_PROXY_RENDER_USE_FALLBACK_RENDER;
user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
- switch (seq_rendersize_to_proxysize(context->preview_render_size)) {
+ switch (psize) {
case IMB_PROXY_NONE:
user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
break;
@@ -3876,7 +3874,8 @@ static ImBuf *seq_render_strip(const SeqRenderData *context,
if (ibuf) {
if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_MOVIECLIP)) {
- is_proxy_image = (context->preview_render_size != 100);
+ is_proxy_image = seq_rendersize_to_proxysize(context->preview_render_size) !=
+ IMB_PROXY_NONE;
}
}
}
@@ -4920,7 +4919,10 @@ static int shuffle_seq_time_offset(Scene *scene, ListBase *seqbasep, char dir)
return tot_ofs;
}
-bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, Scene *evil_scene)
+bool BKE_sequence_base_shuffle_time(ListBase *seqbasep,
+ Scene *evil_scene,
+ ListBase *markers,
+ const bool use_sync_markers)
{
/* note: seq->tmp is used to tag strips to move */
@@ -4937,6 +4939,16 @@ bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, Scene *evil_scene)
seq->flag &= ~SEQ_OVERLAP;
}
}
+
+ if (use_sync_markers && !(evil_scene->toolsettings->lock_markers) && (markers != NULL)) {
+ TimeMarker *marker;
+ /* affect selected markers - it's unlikely that we will want to affect all in this way? */
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ marker->frame += offset;
+ }
+ }
+ }
}
return offset ? false : true;
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index c6cac2057d6..49a295c6a9e 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -794,54 +794,59 @@ static bool target_project_tri_correct(void *UNUSED(userdata),
float x_next[3])
{
/* Insignificant correction threshold */
- const float epsilon = 1e-6f;
- const float dir_epsilon = 0.05f;
+ const float epsilon = 1e-5f;
+ /* Dot product threshold for checking if step is 'clearly' pointing outside. */
+ const float dir_epsilon = 0.5f;
bool fixed = false, locked = false;
- /* Weight 0 and 1 boundary check. */
- for (int i = 0; i < 2; i++) {
- if (step[i] > x[i]) {
- if (step[i] > dir_epsilon * fabsf(step[1 - i])) {
- /* Abort if the solution is clearly outside the domain. */
- if (x[i] < epsilon) {
- return false;
- }
+ /* The barycentric coordinate domain is a triangle bounded by
+ * the X and Y axes, plus the x+y=1 diagonal. First, clamp the
+ * movement against the diagonal. Note that step is subtracted. */
+ float sum = x[0] + x[1];
+ float sstep = -(step[0] + step[1]);
- /* Scale a significant step down to arrive at the boundary. */
- mul_v3_fl(step, x[i] / step[i]);
- fixed = true;
- }
- else {
- /* Reset precision errors to stay at the boundary. */
- step[i] = x[i];
- fixed = locked = true;
- }
- }
- }
+ if (sum + sstep > 1.0f) {
+ float ldist = 1.0f - sum;
- /* Weight 2 boundary check. */
- float sum = x[0] + x[1];
- float sstep = step[0] + step[1];
+ /* If already at the boundary, slide along it. */
+ if (ldist < epsilon * (float)M_SQRT2) {
+ float step_len = len_v2(step);
- if (sum - sstep > 1.0f) {
- if (sstep < -dir_epsilon * (fabsf(step[0]) + fabsf(step[1]))) {
/* Abort if the solution is clearly outside the domain. */
- if (sum > 1.0f - epsilon) {
+ if (step_len > epsilon && sstep > step_len * dir_epsilon * (float)M_SQRT2) {
return false;
}
+ /* Project the new position onto the diagonal. */
+ add_v2_fl(step, (sum + sstep - 1.0f) * 0.5f);
+ fixed = locked = true;
+ }
+ else {
/* Scale a significant step down to arrive at the boundary. */
- mul_v3_fl(step, (1.0f - sum) / -sstep);
+ mul_v3_fl(step, ldist / sstep);
fixed = true;
}
- else {
- /* Reset precision errors to stay at the boundary. */
- if (locked) {
- step[0] = step[1] = 0.0f;
+ }
+
+ /* Weight 0 and 1 boundary checks - along axis. */
+ for (int i = 0; i < 2; i++) {
+ if (step[i] > x[i]) {
+ /* If already at the boundary, slide along it. */
+ if (x[i] < epsilon) {
+ float step_len = len_v2(step);
+
+ /* Abort if the solution is clearly outside the domain. */
+ if (step_len > epsilon && (locked || step[i] > step_len * dir_epsilon)) {
+ return false;
+ }
+
+ /* Reset precision errors to stay at the boundary. */
+ step[i] = x[i];
+ fixed = true;
}
else {
- step[0] -= 0.5f * sstep;
- step[1] = -step[0];
+ /* Scale a significant step down to arrive at the boundary. */
+ mul_v3_fl(step, x[i] / step[i]);
fixed = true;
}
}
@@ -1506,7 +1511,7 @@ void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C,
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
struct Scene *sce = CTX_data_scene(C);
- ShrinkwrapModifierData ssmd = {0};
+ ShrinkwrapModifierData ssmd = {{0}};
ModifierEvalContext ctx = {depsgraph, ob_source, 0};
int totvert;
@@ -1527,7 +1532,7 @@ void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C,
void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target)
{
- ShrinkwrapModifierData ssmd = {0};
+ ShrinkwrapModifierData ssmd = {{0}};
int totvert;
ssmd.target = ob_target;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index b56403dfb6d..3bbd909800b 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -3132,8 +3132,10 @@ SoftBody *sbNew(Scene *scene)
sb->inpush = 0.5f;
sb->interval = 10;
- sb->sfra = scene->r.sfra;
- sb->efra = scene->r.efra;
+ if (scene != NULL) {
+ sb->sfra = scene->r.sfra;
+ sb->efra = scene->r.efra;
+ }
sb->colball = 0.49f;
sb->balldamp = 0.50f;
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index d42436ecb40..84d135c7f32 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -411,7 +411,7 @@ void BKE_sound_delete_cache(bSound *sound)
}
}
-static void sound_load_audio(Main *bmain, bSound *sound)
+static void sound_load_audio(Main *bmain, bSound *sound, bool free_waveform)
{
if (sound->cache) {
@@ -425,7 +425,9 @@ static void sound_load_audio(Main *bmain, bSound *sound)
sound->playback_handle = NULL;
}
- BKE_sound_free_waveform(sound);
+ if (free_waveform) {
+ BKE_sound_free_waveform(sound);
+ }
/* XXX unused currently */
# if 0
@@ -488,7 +490,7 @@ static void sound_load_audio(Main *bmain, bSound *sound)
void BKE_sound_load(Main *bmain, bSound *sound)
{
sound_verify_evaluated_id(&sound->id);
- sound_load_audio(bmain, sound);
+ sound_load_audio(bmain, sound, true);
}
AUD_Device *BKE_sound_mixdown(Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
@@ -902,7 +904,7 @@ void BKE_sound_read_waveform(Main *bmain, bSound *sound, short *stop)
bool need_close_audio_handles = false;
if (sound->playback_handle == NULL) {
/* TODO(sergey): Make it fully independent audio handle. */
- sound_load_audio(bmain, sound);
+ sound_load_audio(bmain, sound, true);
need_close_audio_handles = true;
}
@@ -1096,7 +1098,9 @@ bool BKE_sound_info_get(struct Main *main, struct bSound *sound, SoundInfo *soun
return sound_info_from_playback_handle(sound->playback_handle, sound_info);
}
/* TODO(sergey): Make it fully independent audio handle. */
- sound_load_audio(main, sound);
+ /* Don't free waveforms during non-destructive queries.
+ * This causes unnecessary recalculation - see T69921 */
+ sound_load_audio(main, sound, false);
const bool result = sound_info_from_playback_handle(sound->playback_handle, sound_info);
sound_free_audio(sound);
return result;
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index a02ff98a38a..9008348ed3b 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -1668,7 +1668,8 @@ StudioLight *BKE_studiolight_create(const char *path,
const float light_ambient[3])
{
StudioLight *sl = studiolight_create(STUDIOLIGHT_EXTERNAL_FILE | STUDIOLIGHT_USER_DEFINED |
- STUDIOLIGHT_TYPE_STUDIO);
+ STUDIOLIGHT_TYPE_STUDIO |
+ STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS);
char filename[FILE_MAXFILE];
BLI_split_file_part(path, filename, FILE_MAXFILE);
@@ -1688,7 +1689,7 @@ StudioLight *BKE_studiolight_create(const char *path,
StudioLight *BKE_studiolight_studio_edit_get(void)
{
static StudioLight sl = {0};
- sl.flag = STUDIOLIGHT_TYPE_STUDIO;
+ sl.flag = STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS;
memcpy(sl.light, U.light_param, sizeof(*sl.light) * 4);
memcpy(sl.light_ambient, U.light_ambient, sizeof(*sl.light_ambient) * 3);
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 11d2314ace3..33a9875151a 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -2519,7 +2519,7 @@ static bool subsurf_use_gpu_backend(SubsurfFlags flags)
struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm,
struct SubsurfModifierData *smd,
- struct Scene *scene,
+ const struct Scene *scene,
float (*vertCos)[3],
SubsurfFlags flags)
{
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 3e449fa6b25..f58c20a7d72 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -247,8 +247,12 @@ WorkSpaceLayout *BKE_workspace_layout_add(Main *bmain,
void BKE_workspace_layout_remove(Main *bmain, WorkSpace *workspace, WorkSpaceLayout *layout)
{
- id_us_min(&layout->screen->id);
- BKE_id_free(bmain, layout->screen);
+ /* Screen should usually be set, but we call this from file reading to get rid of invalid
+ * layouts. */
+ if (layout->screen) {
+ id_us_min(&layout->screen->id);
+ BKE_id_free(bmain, layout->screen);
+ }
BLI_freelinkN(&workspace->layouts, layout);
}