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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2012-07-21 03:12:05 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2012-07-21 03:12:05 +0400
commit3b012c041f1fb7b78eddcf1f93288cf7a86ab8d6 (patch)
treecead235bff7687610b1372e709e742ef70692dcb /source/blender/blenkernel/intern
parent5a581c1fd116c51df13e09c5c320feba48d069bb (diff)
parent16516238e2b25ce53144c2dcea5323dc7313b724 (diff)
Merged changes in the trunk up to revision 49090.
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c8
-rw-r--r--source/blender/blenkernel/intern/curve.c2
-rw-r--r--source/blender/blenkernel/intern/displist.c4
-rw-r--r--source/blender/blenkernel/intern/effect.c3
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c2
-rw-r--r--source/blender/blenkernel/intern/group.c2
-rw-r--r--source/blender/blenkernel/intern/implicit.c4
-rw-r--r--source/blender/blenkernel/intern/lattice.c3
-rw-r--r--source/blender/blenkernel/intern/mask.c282
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c1139
-rw-r--r--source/blender/blenkernel/intern/mball.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c17
-rw-r--r--source/blender/blenkernel/intern/multires.c49
-rw-r--r--source/blender/blenkernel/intern/object.c31
-rw-r--r--source/blender/blenkernel/intern/particle_system.c40
-rw-r--r--source/blender/blenkernel/intern/pointcache.c5
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c4
-rw-r--r--source/blender/blenkernel/intern/sequencer.c2
-rw-r--r--source/blender/blenkernel/intern/softbody.c11
19 files changed, 1286 insertions, 324 deletions
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index e5e73061d52..b19b9db8749 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -1709,10 +1709,10 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
DerivedMesh *CDDM_from_curve(Object *ob)
{
- return CDDM_from_curve_customDB(ob, &ob->disp);
+ return CDDM_from_curve_displist(ob, &ob->disp);
}
-DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
+DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
{
DerivedMesh *dm;
CDDerivedMesh *cddm;
@@ -1722,7 +1722,7 @@ DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
MPoly *allpoly;
int totvert, totedge, totloop, totpoly;
- if (BKE_mesh_nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
+ if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert, &alledge,
&totedge, &allloop, &allpoly, &totloop, &totpoly) != 0)
{
/* Error initializing mdata. This often happens when curve is empty */
@@ -2110,7 +2110,7 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const short only_face_normals
/* No tessellation on this mesh yet, need to calculate one.
*
* Important not to update face normals from polys since it
- * interfears with assigning the new normal layer in the following code.
+ * interferes with assigning the new normal layer in the following code.
*/
CDDM_recalc_tessellation_ex(dm, FALSE);
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 674a2d98d07..31491a80f2b 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -1588,7 +1588,7 @@ static int cu_isectLL(const float v1[3], const float v2[3], const float v3[3], c
float *labda, float *mu, float vec[3])
{
/* return:
- * -1: colliniar
+ * -1: collinear
* 0: no intersection of segments
* 1: exact intersection of segments
* 2: cross-intersection of segments
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 9b349598db1..8011efebaac 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -948,7 +948,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
curve_to_filledpoly(cu, nurb, dispbase);
}
- dm = CDDM_from_curve_customDB(ob, dispbase);
+ dm = CDDM_from_curve_displist(ob, dispbase);
CDDM_calc_normals_mapping(dm);
}
@@ -1038,7 +1038,7 @@ static DerivedMesh *create_orco_dm(Scene *scene, Object *ob)
/* OrcoDM should be created from underformed disp lists */
BKE_displist_make_curveTypes_forOrco(scene, ob, &disp);
- dm = CDDM_from_curve_customDB(ob, &disp);
+ dm = CDDM_from_curve_displist(ob, &disp);
BKE_displist_free(&disp);
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index a4e7676c602..4f4bafd00b4 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -29,7 +29,6 @@
* \ingroup bke
*/
-
#include <stddef.h>
#include <math.h>
@@ -98,8 +97,6 @@
#include <string.h>
#endif // WITH_MOD_FLUID
-//XXX #include "BIF_screen.h"
-
EffectorWeights *BKE_add_effector_weights(Group *group)
{
EffectorWeights *weights = MEM_callocN(sizeof(EffectorWeights), "EffectorWeights");
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index cefcbdd2762..438188b1e2a 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -1298,7 +1298,7 @@ float evaluate_time_fmodifiers(ListBase *modifiers, FCurve *fcu, float cvalue, f
return evaltime;
}
-/* Evalautes the given set of F-Curve Modifiers using the given data
+/* Evaluates the given set of F-Curve Modifiers using the given data
* Should only be called after evaluate_time_fmodifiers() has been called...
*/
void evaluate_value_fmodifiers(ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime)
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 95e659e9a2c..b615f8c0d9f 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -351,7 +351,7 @@ void group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group
#if 0 /* warning, isn't clearing the recalc flag on the object which causes it to run all the time,
* not just on frame change.
- * This isn't working because the animation data is only re-evalyated on frame change so commenting for now
+ * This isn't working because the animation data is only re-evaluated on frame change so commenting for now
* but when its enabled at some point it will need to be changed so as not to update so much - campbell */
/* if animated group... */
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 5b3e823f050..8a573aaa676 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -185,7 +185,7 @@ DO_INLINE void print_lfvector(float (*fLongVector)[3], unsigned int verts)
/* create long vector */
DO_INLINE lfVector *create_lfvector(unsigned int verts)
{
- /* TODO: check if memory allocation was successfull */
+ /* TODO: check if memory allocation was successful */
return (lfVector *)MEM_callocN(verts * sizeof(lfVector), "cloth_implicit_alloc_vector");
// return (lfVector *)cloth_aligned_malloc(&MEMORY_BASE, verts * sizeof(lfVector));
}
@@ -513,7 +513,7 @@ static void print_bfmatrix(fmatrix3x3 *m3)
/* create big matrix */
DO_INLINE fmatrix3x3 *create_bfmatrix(unsigned int verts, unsigned int springs)
{
- // TODO: check if memory allocation was successfull */
+ // TODO: check if memory allocation was successful */
fmatrix3x3 *temp = (fmatrix3x3 *)MEM_callocN(sizeof(fmatrix3x3) * (verts + springs), "cloth_implicit_alloc_matrix");
temp[0].vcount = verts;
temp[0].scount = springs;
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index d5b1d3c98c8..0e73d10fa5f 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -29,8 +29,6 @@
* \ingroup bke
*/
-
-
#include <stdio.h>
#include <string.h>
#include <math.h>
@@ -65,7 +63,6 @@
#include "BKE_deform.h"
-//XXX #include "BIF_editdeform.h"
void calc_lat_fudu(int flag, int res, float *fu, float *du)
{
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 4e683d1618f..fa11721a944 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -239,14 +239,14 @@ MaskSpline *BKE_mask_spline_add(MaskLayer *masklay)
/* cyclic shapes are more usually used */
// spline->flag |= MASK_SPLINE_CYCLIC; // disable because its not so nice for drawing. could be done differently
- spline->weight_interp = MASK_SPLINE_INTERP_LINEAR;
+ spline->weight_interp = MASK_SPLINE_INTERP_EASE;
BKE_mask_parent_init(&spline->parent);
return spline;
}
-static int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
+int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
{
float max_segment = 0.01f;
int i, resol = 1;
@@ -284,7 +284,7 @@ static int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
return resol;
}
-static int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height)
+int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height)
{
const float max_segment = 0.005;
int resol = BKE_mask_spline_resolution(spline, width, height);
@@ -331,8 +331,10 @@ int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const int
return len;
}
-float (*BKE_mask_spline_differentiate_with_resolution_ex(MaskSpline *spline, const int resol,
- int *tot_diff_point))[2]
+float (*BKE_mask_spline_differentiate_with_resolution_ex(MaskSpline *spline,
+ int *tot_diff_point,
+ const int resol
+ ))[2]
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
@@ -389,11 +391,12 @@ float (*BKE_mask_spline_differentiate_with_resolution_ex(MaskSpline *spline, con
}
float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height,
- int *tot_diff_point))[2]
+ int *tot_diff_point
+ ))[2]
{
int resol = BKE_mask_spline_resolution(spline, width, height);
- return BKE_mask_spline_differentiate_with_resolution_ex(spline, resol, tot_diff_point);
+ return BKE_mask_spline_differentiate_with_resolution_ex(spline, tot_diff_point, resol);
}
float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2]
@@ -401,12 +404,266 @@ float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[
return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point);
}
+/* ** feather points self-intersection collapse routine ** */
+
+typedef struct FeatherEdgesBucket {
+ int tot_segment;
+ int (*segments)[2];
+ int alloc_segment;
+} FeatherEdgesBucket;
+
+static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end)
+{
+ const int alloc_delta = 256;
+
+ if (bucket->tot_segment >= bucket->alloc_segment) {
+ if (!bucket->segments) {
+ bucket->segments = MEM_callocN(alloc_delta * sizeof(*bucket->segments), "feather bucket segments");
+ }
+ else {
+ bucket->segments = MEM_reallocN(bucket->segments,
+ (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments));
+ }
+
+ bucket->alloc_segment += alloc_delta;
+ }
+
+ bucket->segments[bucket->tot_segment][0] = start;
+ bucket->segments[bucket->tot_segment][1] = end;
+
+ bucket->tot_segment++;
+}
+
+static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_feather_point, FeatherEdgesBucket *bucket,
+ int cur_a, int cur_b)
+{
+ int i;
+
+ float *v1 = (float *) feather_points[cur_a];
+ float *v2 = (float *) feather_points[cur_b];
+
+ for (i = 0; i < bucket->tot_segment; i++) {
+ int check_a = bucket->segments[i][0];
+ int check_b = bucket->segments[i][1];
+
+ float *v3 = (float *) feather_points[check_a];
+ float *v4 = (float *) feather_points[check_b];
+
+ if (check_a >= cur_a - 1 || cur_b == check_a)
+ continue;
+
+ if (isect_seg_seg_v2(v1, v2, v3, v4)) {
+ int k, len;
+ float p[2];
+
+ isect_seg_seg_v2_point(v1, v2, v3, v4, p);
+
+ /* TODO: for now simply choose the shortest loop, could be made smarter in some way */
+ len = cur_a - check_b;
+ if (len < tot_feather_point - len) {
+ for (k = check_b; k <= cur_a; k++) {
+ copy_v2_v2(feather_points[k], p);
+ }
+ }
+ else {
+ for (k = 0; k <= check_a; k++) {
+ copy_v2_v2(feather_points[k], p);
+ }
+
+ if (cur_b != 0) {
+ for (k = cur_b; k < tot_feather_point; k++) {
+ copy_v2_v2(feather_points[k], p);
+ }
+ }
+ }
+ }
+ }
+}
+
+static int feather_bucket_index_from_coord(float co[2], const float min[2], const float bucket_scale[2],
+ const int buckets_per_side)
+{
+ int x = (int) ((co[0] - min[0]) * bucket_scale[0]);
+ int y = (int) ((co[1] - min[1]) * bucket_scale[1]);
+
+ if (x == buckets_per_side)
+ x--;
+
+ if (y == buckets_per_side)
+ y--;
+
+ return y * buckets_per_side + x;
+}
+
+static void feather_bucket_get_diagonal(FeatherEdgesBucket *buckets, int start_bucket_index, int end_bucket_index,
+ int buckets_per_side, FeatherEdgesBucket **diagonal_bucket_a_r,
+ FeatherEdgesBucket **diagonal_bucket_b_r)
+{
+ int start_bucket_x = start_bucket_index % buckets_per_side;
+ int start_bucket_y = start_bucket_index / buckets_per_side;
+
+ int end_bucket_x = end_bucket_index % buckets_per_side;
+ int end_bucket_y = end_bucket_index / buckets_per_side;
+
+ int diagonal_bucket_a_index = start_bucket_y * buckets_per_side + end_bucket_x;
+ int diagonal_bucket_b_index = end_bucket_y * buckets_per_side + start_bucket_x;
+
+ *diagonal_bucket_a_r = &buckets[diagonal_bucket_a_index];
+ *diagonal_bucket_b_r = &buckets[diagonal_bucket_b_index];
+}
+
+static void spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feather_points)[2], int tot_feather_point)
+{
+#define BUCKET_INDEX(co) \
+ feather_bucket_index_from_coord(co, min, bucket_scale, buckets_per_side)
+
+ int buckets_per_side, tot_bucket;
+ float bucket_size, bucket_scale[2];
+
+ FeatherEdgesBucket *buckets;
+
+ int i;
+ float min[2], max[2];
+ float max_delta_x = -1.0f, max_delta_y = -1.0f, max_delta;
+
+ if (tot_feather_point < 4) {
+ /* self-intersection works only for quads at least,
+ * in other cases polygon can't be self-intersecting anyway
+ */
+
+ return;
+ }
+
+ /* find min/max corners of mask to build buckets in that space */
+ INIT_MINMAX2(min, max);
+
+ for (i = 0; i < tot_feather_point; i++) {
+ int next = i + 1;
+ float delta;
+
+ if (next == tot_feather_point) {
+ if (spline->flag & MASK_SPLINE_CYCLIC)
+ next = 0;
+ else
+ break;
+ }
+
+ delta = fabsf(feather_points[i][0] - feather_points[next][0]);
+ if (delta > max_delta_x)
+ max_delta_x = delta;
+
+ delta = fabsf(feather_points[i][1] - feather_points[next][1]);
+ if (delta > max_delta_y)
+ max_delta_y = delta;
+
+ DO_MINMAX2(feather_points[i], min, max);
+ }
+
+ /* use dynamically calculated buckets per side, so we likely wouldn't
+ * run into a situation when segment doesn't fit two buckets which is
+ * pain collecting candidates for intersection
+ */
+ max_delta_x /= max[0] - min[0];
+ max_delta_y /= max[1] - min[1];
+ max_delta = MAX2(max_delta_x, max_delta_y);
+
+ buckets_per_side = MIN2(512, 0.9f / max_delta);
+
+ if (buckets_per_side == 0) {
+ /* happens when some segment fills the whole bounding box across some of dimension */
+
+ buckets_per_side = 1;
+ }
+
+ tot_bucket = buckets_per_side * buckets_per_side;
+ bucket_size = 1.0f / buckets_per_side;
+
+ /* pre-compute multipliers, to save mathematical operations in loops */
+ bucket_scale[0] = 1.0f / ((max[0] - min[0]) * bucket_size);
+ bucket_scale[1] = 1.0f / ((max[1] - min[1]) * bucket_size);
+
+ /* fill in buckets' edges */
+ buckets = MEM_callocN(sizeof(FeatherEdgesBucket) * tot_bucket, "feather buckets");
+
+ for (i = 0; i < tot_feather_point; i++) {
+ int start = i, end = i + 1;
+ int start_bucket_index, end_bucket_index;
+
+ if (end == tot_feather_point) {
+ if (spline->flag & MASK_SPLINE_CYCLIC)
+ end = 0;
+ else
+ break;
+ }
+
+ start_bucket_index = BUCKET_INDEX(feather_points[start]);
+ end_bucket_index = BUCKET_INDEX(feather_points[end]);
+
+ feather_bucket_add_edge(&buckets[start_bucket_index], start, end);
+
+ if (start_bucket_index != end_bucket_index) {
+ FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
+ FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b;
+
+ feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side,
+ &diagonal_bucket_a, &diagonal_bucket_b);
+
+ feather_bucket_add_edge(end_bucket, start, end);
+ feather_bucket_add_edge(diagonal_bucket_a, start, end);
+ feather_bucket_add_edge(diagonal_bucket_a, start, end);
+ }
+ }
+
+ /* check all edges for intersection with edges from their buckets */
+ for (i = 0; i < tot_feather_point; i++) {
+ int cur_a = i, cur_b = i + 1;
+ int start_bucket_index, end_bucket_index;
+
+ FeatherEdgesBucket *start_bucket;
+
+ if (cur_b == tot_feather_point)
+ cur_b = 0;
+
+ start_bucket_index = BUCKET_INDEX(feather_points[cur_a]);
+ end_bucket_index = BUCKET_INDEX(feather_points[cur_b]);
+
+ start_bucket = &buckets[start_bucket_index];
+
+ feather_bucket_check_intersect(feather_points, tot_feather_point, start_bucket, cur_a, cur_b);
+
+ if (start_bucket_index != end_bucket_index) {
+ FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
+ FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b;
+
+ feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side,
+ &diagonal_bucket_a, &diagonal_bucket_b);
+
+ feather_bucket_check_intersect(feather_points, tot_feather_point, end_bucket, cur_a, cur_b);
+ feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b);
+ feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_b, cur_a, cur_b);
+ }
+ }
+
+ /* free buckets */
+ for (i = 0; i < tot_bucket; i++) {
+ if (buckets[i].segments)
+ MEM_freeN(buckets[i].segments);
+ }
+
+ MEM_freeN(buckets);
+
+#undef BUCKET_INDEX
+}
+
/**
* values align with #BKE_mask_spline_differentiate_with_resolution_ex
* when \a resol arguments match.
*/
-float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline, const int resol,
- int *tot_feather_point))[2]
+float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline,
+ int *tot_feather_point,
+ const int resol,
+ const int do_collapse
+ ))[2]
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
MaskSplinePoint *point, *prev;
@@ -467,6 +724,11 @@ float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpl
*tot_feather_point = tot;
+ /* this is slow! - don't do on draw */
+ if (do_collapse) {
+ spline_feather_collapse_inner_loops(spline, feather, tot);
+ }
+
return feather;
}
@@ -475,7 +737,7 @@ float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline
{
int resol = BKE_mask_spline_feather_resolution(spline, width, height);
- return BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, resol, tot_feather_point);
+ return BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, tot_feather_point, resol, FALSE);
}
float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2]
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index bb18166ba6d..b05c1ad4eaa 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -32,39 +32,107 @@
#include "DNA_vec_types.h"
#include "DNA_mask_types.h"
+#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
-#include "BLI_kdopbvh.h"
#include "BLI_scanfill.h"
+#include "BLI_memarena.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_listbase.h"
-#include "BLI_mempool.h"
+#include "BLI_linklist.h"
#include "BKE_mask.h"
#ifndef USE_RASKTER
-#define RESOL 32
+/* this is rather and annoying hack, use define to isolate it.
+ * problem is caused by scanfill removing edges on us. */
+#define USE_SCANFILL_EDGE_WORKAROUND
+
+#define SPLINE_RESOL_CAP_PER_PIXEL 2
+#define SPLINE_RESOL_CAP_MIN 8
+#define SPLINE_RESOL_CAP_MAX 64
+
+/* found this gives best performance for high detail masks, values between 2 and 8 work best */
+#define BUCKET_PIXELS_PER_CELL 4
+
+#define SF_EDGE_IS_BOUNDARY 0xff
+#define SF_KEYINDEX_TEMP_ID ((unsigned int) -1)
+
+#define TRI_TERMINATOR_ID ((unsigned int) -1)
+#define TRI_VERT ((unsigned int) -1)
+
+/* for debugging add... */
+#ifndef NDEBUG
+/* printf("%u %u %u %u\n", _t[0], _t[1], _t[2], _t[3]); \ */
+# define FACE_ASSERT(face, vert_max) \
+{ \
+ unsigned int *_t = face; \
+ BLI_assert(_t[0] < vert_max); \
+ BLI_assert(_t[1] < vert_max); \
+ BLI_assert(_t[2] < vert_max); \
+ BLI_assert(_t[3] < vert_max || _t[3] == TRI_VERT); \
+} (void)0
+#else
+ /* do nothing */
+# define FACE_ASSERT(face, vert_max)
+#endif
+
+static void rotate_point_v2(float r_p[2], const float p[2], const float cent[2], const float angle, const float asp[2])
+{
+ const float s = sinf(angle);
+ const float c = cosf(angle);
+ float p_new[2];
+
+ /* translate point back to origin */
+ r_p[0] = (p[0] - cent[0]) / asp[0];
+ r_p[1] = (p[1] - cent[1]) / asp[1];
+
+ /* rotate point */
+ p_new[0] = ((r_p[0] * c) - (r_p[1] * s)) * asp[0];
+ p_new[1] = ((r_p[0] * s) + (r_p[1] * c)) * asp[1];
+
+ /* translate point back */
+ r_p[0] = p_new[0] + cent[0];
+ r_p[1] = p_new[1] + cent[1];
+}
+
+BLI_INLINE unsigned int clampis_uint(const unsigned int v, const unsigned int min, const unsigned int max)
+{
+ return v < min ? min : (v > max ? max : v);
+}
+
+/* --------------------------------------------------------------------- */
+/* local structs for mask rasterizeing */
+/* --------------------------------------------------------------------- */
/**
- * A single #MaskRasterHandle contains multile #MaskRasterLayer's,
+ * A single #MaskRasterHandle contains multiple #MaskRasterLayer's,
* each #MaskRasterLayer does its own lookup which contributes to
- * the final pixel with its own blending mode and the final pixel is blended between these.
+ * the final pixel with its own blending mode and the final pixel
+ * is blended between these.
*/
/* internal use only */
typedef struct MaskRasterLayer {
- /* xy raytree */
- BVHTree *bvhtree;
+ /* geometry */
+ unsigned int face_tot;
+ unsigned int (*face_array)[4]; /* access coords tri/quad */
+ float (*face_coords)[3]; /* xy, z 0-1 (1.0 == filled) */
+
- /* 2d bounds (to quickly skip raytree lookup) */
+ /* 2d bounds (to quickly skip bucket lookup) */
rctf bounds;
- /* geometry */
- unsigned int (*tri_array)[4]; /* access coords tri/quad */
- float (*tri_coords)[3]; /* xy, z 0-1 (1.0 == filled) */
+
+ /* buckets */
+ unsigned int **buckets_face;
+ /* cache divide and subtract */
+ float buckets_xy_scalar[2]; /* (1.0 / (buckets_width + FLT_EPSILON)) * buckets_x */
+ unsigned int buckets_x;
+ unsigned int buckets_y;
/* copied direct from #MaskLayer.--- */
@@ -72,9 +140,21 @@ typedef struct MaskRasterLayer {
float alpha;
char blend;
char blend_flag;
+ char falloff;
} MaskRasterLayer;
+typedef struct MaskRasterSplineInfo {
+ /* body of the spline */
+ unsigned int vertex_offset;
+ unsigned int vertex_total;
+
+ /* capping for non-filled, non cyclic splines */
+ unsigned int vertex_total_cap_head;
+ unsigned int vertex_total_cap_tail;
+
+ unsigned int is_cyclic;
+} MaskRasterSplineInfo;
/**
* opaque local struct for mask pixel lookup, each MaskLayer needs one of these
@@ -83,11 +163,15 @@ struct MaskRasterHandle {
MaskRasterLayer *layers;
unsigned int layers_tot;
- /* 2d bounds (to quickly skip raytree lookup) */
+ /* 2d bounds (to quickly skip bucket lookup) */
rctf bounds;
};
-MaskRasterHandle *BLI_maskrasterize_handle_new(void)
+/* --------------------------------------------------------------------- */
+/* alloc / free functions */
+/* --------------------------------------------------------------------- */
+
+MaskRasterHandle *BKE_maskrasterize_handle_new(void)
{
MaskRasterHandle *mr_handle;
@@ -96,22 +180,33 @@ MaskRasterHandle *BLI_maskrasterize_handle_new(void)
return mr_handle;
}
-void BLI_maskrasterize_handle_free(MaskRasterHandle *mr_handle)
+void BKE_maskrasterize_handle_free(MaskRasterHandle *mr_handle)
{
const unsigned int layers_tot = mr_handle->layers_tot;
unsigned int i;
- MaskRasterLayer *raslayers = mr_handle->layers;
+ MaskRasterLayer *layer = mr_handle->layers;
+
+ for (i = 0; i < layers_tot; i++, layer++) {
- /* raycast vars */
- for (i = 0; i < layers_tot; i++, raslayers++) {
- BLI_bvhtree_free(raslayers->bvhtree);
+ if (layer->face_array) {
+ MEM_freeN(layer->face_array);
+ }
- if (raslayers->tri_array) {
- MEM_freeN(raslayers->tri_array);
+ if (layer->face_coords) {
+ MEM_freeN(layer->face_coords);
}
- if (raslayers->tri_coords) {
- MEM_freeN(raslayers->tri_coords);
+ if (layer->buckets_face) {
+ const unsigned int bucket_tot = layer->buckets_x * layer->buckets_y;
+ unsigned int bucket_index;
+ for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) {
+ unsigned int *face_index = layer->buckets_face[bucket_index];
+ if (face_index) {
+ MEM_freeN(face_index);
+ }
+ }
+
+ MEM_freeN(layer->buckets_face);
}
}
@@ -119,21 +214,16 @@ void BLI_maskrasterize_handle_free(MaskRasterHandle *mr_handle)
MEM_freeN(mr_handle);
}
-#define PRINT_MASK_DEBUG printf
-
-#define SF_EDGE_IS_BOUNDARY 0xff
-
-#define SF_KEYINDEX_TEMP_ID ((unsigned int) -1)
-
-void maskrasterize_spline_differentiate_point_inset(float (*diff_feather_points)[2], float (*diff_points)[2],
- const int tot_diff_point, const float ofs, const int do_test)
+void maskrasterize_spline_differentiate_point_outset(float (*diff_feather_points)[2], float (*diff_points)[2],
+ const unsigned int tot_diff_point, const float ofs,
+ const short do_test)
{
- int k_prev = tot_diff_point - 2;
- int k_curr = tot_diff_point - 1;
- int k_next = 0;
+ unsigned int k_prev = tot_diff_point - 2;
+ unsigned int k_curr = tot_diff_point - 1;
+ unsigned int k_next = 0;
- int k;
+ unsigned int k;
float d_prev[2];
float d_next[2];
@@ -153,12 +243,9 @@ void maskrasterize_spline_differentiate_point_inset(float (*diff_feather_points)
sub_v2_v2v2(d_prev, co_prev, co_curr);
normalize_v2(d_prev);
- /* TODO, speedup by only doing one normalize per iter */
-
-
for (k = 0; k < tot_diff_point; k++) {
- co_prev = diff_points[k_prev];
+ /* co_prev = diff_points[k_prev]; */ /* precalc */
co_curr = diff_points[k_curr];
co_next = diff_points[k_next];
@@ -183,26 +270,265 @@ void maskrasterize_spline_differentiate_point_inset(float (*diff_feather_points)
/* use next iter */
copy_v2_v2(d_prev, d_next);
- k_prev = k_curr;
+ /* k_prev = k_curr; */ /* precalc */
k_curr = k_next;
k_next++;
}
}
-#define TRI_VERT ((unsigned int) -1)
+/* this function is not exact, sometimes it returns false positives,
+ * the main point of it is to clear out _almost_ all bucket/face non-intersections,
+ * returning TRUE in corner cases is ok but missing an intersection is NOT.
+ *
+ * method used
+ * - check if the center of the buckets bounding box is intersecting the face
+ * - if not get the max radius to a corner of the bucket and see how close we
+ * are to any of the triangle edges.
+ */
+static int layer_bucket_isect_test(MaskRasterLayer *layer, unsigned int face_index,
+ const unsigned int bucket_x, const unsigned int bucket_y,
+ const float bucket_size_x, const float bucket_size_y,
+ const float bucket_max_rad_squared)
+{
+ unsigned int *face = layer->face_array[face_index];
+ float (*cos)[3] = layer->face_coords;
+
+ const float xmin = layer->bounds.xmin + (bucket_size_x * bucket_x);
+ const float ymin = layer->bounds.ymin + (bucket_size_y * bucket_y);
+ const float xmax = xmin + bucket_size_x;
+ const float ymax = ymin + bucket_size_y;
+
+ const float cent[2] = {(xmin + xmax) * 0.5f,
+ (ymin + ymax) * 0.5f};
+
+ if (face[3] == TRI_VERT) {
+ const float *v1 = cos[face[0]];
+ const float *v2 = cos[face[1]];
+ const float *v3 = cos[face[2]];
+
+ if (isect_point_tri_v2(cent, v1, v2, v3)) {
+ return TRUE;
+ }
+ else {
+ if ((dist_squared_to_line_segment_v2(cent, v1, v2) < bucket_max_rad_squared) ||
+ (dist_squared_to_line_segment_v2(cent, v2, v3) < bucket_max_rad_squared) ||
+ (dist_squared_to_line_segment_v2(cent, v3, v1) < bucket_max_rad_squared))
+ {
+ return TRUE;
+ }
+ else {
+ // printf("skip tri\n");
+ return FALSE;
+ }
+ }
+
+ }
+ else {
+ const float *v1 = cos[face[0]];
+ const float *v2 = cos[face[1]];
+ const float *v3 = cos[face[2]];
+ const float *v4 = cos[face[3]];
+
+ if (isect_point_tri_v2(cent, v1, v2, v3)) {
+ return TRUE;
+ }
+ else if (isect_point_tri_v2(cent, v1, v3, v4)) {
+ return TRUE;
+ }
+ else {
+ if ((dist_squared_to_line_segment_v2(cent, v1, v2) < bucket_max_rad_squared) ||
+ (dist_squared_to_line_segment_v2(cent, v2, v3) < bucket_max_rad_squared) ||
+ (dist_squared_to_line_segment_v2(cent, v3, v4) < bucket_max_rad_squared) ||
+ (dist_squared_to_line_segment_v2(cent, v4, v1) < bucket_max_rad_squared))
+ {
+ return TRUE;
+ }
+ else {
+ // printf("skip quad\n");
+ return FALSE;
+ }
+ }
+ }
+}
+
+static void layer_bucket_init_dummy(MaskRasterLayer *layer)
+{
+ layer->face_tot = 0;
+ layer->face_coords = NULL;
+ layer->face_array = NULL;
+
+ layer->buckets_x = 0;
+ layer->buckets_y = 0;
+
+ layer->buckets_xy_scalar[0] = 0.0f;
+ layer->buckets_xy_scalar[1] = 0.0f;
+
+ layer->buckets_face = NULL;
+
+ BLI_rctf_init(&layer->bounds, -1.0f, -1.0f, -1.0f, -1.0f);
+}
+
+static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size)
+{
+ MemArena *arena = BLI_memarena_new(1 << 16, __func__);
+
+ const float bucket_dim_x = layer->bounds.xmax - layer->bounds.xmin;
+ const float bucket_dim_y = layer->bounds.ymax - layer->bounds.ymin;
+
+ layer->buckets_x = (bucket_dim_x / pixel_size) / (float)BUCKET_PIXELS_PER_CELL;
+ layer->buckets_y = (bucket_dim_y / pixel_size) / (float)BUCKET_PIXELS_PER_CELL;
+
+// printf("bucket size %ux%u\n", layer->buckets_x, layer->buckets_y);
+
+ CLAMP(layer->buckets_x, 8, 512);
+ CLAMP(layer->buckets_y, 8, 512);
+
+ layer->buckets_xy_scalar[0] = (1.0f / (bucket_dim_x + FLT_EPSILON)) * layer->buckets_x;
+ layer->buckets_xy_scalar[1] = (1.0f / (bucket_dim_y + FLT_EPSILON)) * layer->buckets_y;
+
+ {
+ /* width and height of each bucket */
+ const float bucket_size_x = (bucket_dim_x + FLT_EPSILON) / layer->buckets_x;
+ const float bucket_size_y = (bucket_dim_y + FLT_EPSILON) / layer->buckets_y;
+ const float bucket_max_rad = (maxf(bucket_size_x, bucket_size_y) * M_SQRT2) + FLT_EPSILON;
+ const float bucket_max_rad_squared = bucket_max_rad * bucket_max_rad;
+
+ unsigned int *face = &layer->face_array[0][0];
+ float (*cos)[3] = layer->face_coords;
+
+ const unsigned int bucket_tot = layer->buckets_x * layer->buckets_y;
+ LinkNode **bucketstore = MEM_callocN(bucket_tot * sizeof(LinkNode *), __func__);
+ unsigned int *bucketstore_tot = MEM_callocN(bucket_tot * sizeof(unsigned int), __func__);
+
+ unsigned int face_index;
+
+ for (face_index = 0; face_index < layer->face_tot; face_index++, face += 4) {
+ float xmin;
+ float xmax;
+ float ymin;
+ float ymax;
+
+ if (face[3] == TRI_VERT) {
+ const float *v1 = cos[face[0]];
+ const float *v2 = cos[face[1]];
+ const float *v3 = cos[face[2]];
+
+ xmin = minf(v1[0], minf(v2[0], v3[0]));
+ xmax = maxf(v1[0], maxf(v2[0], v3[0]));
+ ymin = minf(v1[1], minf(v2[1], v3[1]));
+ ymax = maxf(v1[1], maxf(v2[1], v3[1]));
+ }
+ else {
+ const float *v1 = cos[face[0]];
+ const float *v2 = cos[face[1]];
+ const float *v3 = cos[face[2]];
+ const float *v4 = cos[face[3]];
+
+ xmin = minf(v1[0], minf(v2[0], minf(v3[0], v4[0])));
+ xmax = maxf(v1[0], maxf(v2[0], maxf(v3[0], v4[0])));
+ ymin = minf(v1[1], minf(v2[1], minf(v3[1], v4[1])));
+ ymax = maxf(v1[1], maxf(v2[1], maxf(v3[1], v4[1])));
+ }
+
+
+ /* not essential but may as will skip any faces outside the view */
+ if (!((xmax < 0.0f) || (ymax < 0.0f) || (xmin > 1.0f) || (ymin > 1.0f))) {
+
+ CLAMP(xmin, 0.0f, 1.0f);
+ CLAMP(ymin, 0.0f, 1.0f);
+ CLAMP(xmax, 0.0f, 1.0f);
+ CLAMP(ymax, 0.0f, 1.0f);
+
+ {
+ unsigned int xi_min = (unsigned int) ((xmin - layer->bounds.xmin) * layer->buckets_xy_scalar[0]);
+ unsigned int xi_max = (unsigned int) ((xmax - layer->bounds.xmin) * layer->buckets_xy_scalar[0]);
+ unsigned int yi_min = (unsigned int) ((ymin - layer->bounds.ymin) * layer->buckets_xy_scalar[1]);
+ unsigned int yi_max = (unsigned int) ((ymax - layer->bounds.ymin) * layer->buckets_xy_scalar[1]);
+ void *face_index_void = SET_UINT_IN_POINTER(face_index);
+
+ unsigned int xi, yi;
+
+ /* this should _almost_ never happen but since it can in extreme cases,
+ * we have to clamp the values or we overrun the buffer and crash */
+ CLAMP(xi_min, 0, layer->buckets_x - 1);
+ CLAMP(xi_max, 0, layer->buckets_x - 1);
+ CLAMP(yi_min, 0, layer->buckets_y - 1);
+ CLAMP(yi_max, 0, layer->buckets_y - 1);
+
+ for (yi = yi_min; yi <= yi_max; yi++) {
+ unsigned int bucket_index = (layer->buckets_x * yi) + xi_min;
+ for (xi = xi_min; xi <= xi_max; xi++, bucket_index++) {
+ // unsigned int bucket_index = (layer->buckets_x * yi) + xi; /* correct but do in outer loop */
+
+ BLI_assert(xi < layer->buckets_x);
+ BLI_assert(yi < layer->buckets_y);
+ BLI_assert(bucket_index < bucket_tot);
+
+ /* check if the bucket intersects with the face */
+ /* note: there is a tradeoff here since checking box/tri intersections isn't
+ * as optimal as it could be, but checking pixels against faces they will never intersect
+ * with is likely the greater slowdown here - so check if the cell intersects the face */
+ if (layer_bucket_isect_test(layer, face_index,
+ xi, yi,
+ bucket_size_x, bucket_size_y,
+ bucket_max_rad_squared))
+ {
+ BLI_linklist_prepend_arena(&bucketstore[bucket_index], face_index_void, arena);
+ bucketstore_tot[bucket_index]++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (1) {
+ /* now convert linknodes into arrays for faster per pixel access */
+ unsigned int **buckets_face = MEM_mallocN(bucket_tot * sizeof(unsigned int **), __func__);
+ unsigned int bucket_index;
-void BLI_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mask,
+ for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) {
+ if (bucketstore_tot[bucket_index]) {
+ unsigned int *bucket = MEM_mallocN((bucketstore_tot[bucket_index] + 1) * sizeof(unsigned int),
+ __func__);
+ LinkNode *bucket_node;
+
+ buckets_face[bucket_index] = bucket;
+
+ for (bucket_node = bucketstore[bucket_index]; bucket_node; bucket_node = bucket_node->next) {
+ *bucket = GET_UINT_FROM_POINTER(bucket_node->link);
+ bucket++;
+ }
+ *bucket = TRI_TERMINATOR_ID;
+ }
+ else {
+ buckets_face[bucket_index] = NULL;
+ }
+ }
+
+ layer->buckets_face = buckets_face;
+ }
+
+ MEM_freeN(bucketstore);
+ MEM_freeN(bucketstore_tot);
+ }
+
+ BLI_memarena_free(arena);
+}
+
+void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mask,
const int width, const int height,
const short do_aspect_correct, const short do_mask_aa,
const short do_feather)
{
- /* TODO: real size */
- const int resol = RESOL;
- const float aa_filter_size = 1.0f / MIN2(width, height);
+ const rctf default_bounds = {0.0f, 1.0f, 0.0f, 1.0f};
+ const float pixel_size = 1.0f / MIN2(width, height);
+ const float asp_xy[2] = {(do_aspect_correct && width > height) ? (float)height / (float)width : 1.0f,
+ (do_aspect_correct && width < height) ? (float)width / (float)height : 1.0f};
const float zvec[3] = {0.0f, 0.0f, 1.0f};
MaskLayer *masklay;
- int masklay_index;
+ unsigned int masklay_index;
mr_handle->layers_tot = BLI_countlist(&mask->masklayers);
mr_handle->layers = MEM_mallocN(sizeof(MaskRasterLayer) * mr_handle->layers_tot, STRINGIFY(MaskRasterLayer));
@@ -210,6 +536,11 @@ void BLI_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
for (masklay = mask->masklayers.first, masklay_index = 0; masklay; masklay = masklay->next, masklay_index++) {
+ /* we need to store vertex ranges for open splines for filling */
+ unsigned int tot_splines;
+ MaskRasterSplineInfo *open_spline_ranges;
+ unsigned int open_spline_index = 0;
+
MaskSpline *spline;
/* scanfill */
@@ -221,13 +552,26 @@ void BLI_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
unsigned int sf_vert_tot = 0;
unsigned int tot_feather_quads = 0;
+#ifdef USE_SCANFILL_EDGE_WORKAROUND
+ unsigned int tot_boundary_used = 0;
+ unsigned int tot_boundary_found = 0;
+#endif
+
if (masklay->restrictflag & MASK_RESTRICT_RENDER) {
+ /* skip the layer */
+ mr_handle->layers_tot--;
+ masklay_index--;
continue;
}
+ tot_splines = BLI_countlist(&masklay->splines);
+ open_spline_ranges = MEM_callocN(sizeof(*open_spline_ranges) * tot_splines, __func__);
+
BLI_scanfill_begin(&sf_ctx);
for (spline = masklay->splines.first; spline; spline = spline->next) {
+ const unsigned int is_cyclic = (spline->flag & MASK_SPLINE_CYCLIC) != 0;
+ const unsigned int is_fill = (spline->flag & MASK_SPLINE_NOFILL) == 0;
float (*diff_points)[2];
int tot_diff_point;
@@ -235,11 +579,17 @@ void BLI_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
float (*diff_feather_points)[2];
int tot_diff_feather_points;
- diff_points = BKE_mask_spline_differentiate_with_resolution_ex(spline, resol, &tot_diff_point);
+ const int resol_a = BKE_mask_spline_resolution(spline, width, height) / 4;
+ const int resol_b = BKE_mask_spline_feather_resolution(spline, width, height) / 4;
+ const int resol = CLAMPIS(MAX2(resol_a, resol_b), 4, 512);
+
+ diff_points = BKE_mask_spline_differentiate_with_resolution_ex(
+ spline, &tot_diff_point, resol);
- /* dont ch*/
if (do_feather) {
- diff_feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, resol, &tot_diff_feather_points);
+ diff_feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution_ex(
+ spline, &tot_diff_feather_points, resol, TRUE);
+ BLI_assert(diff_feather_points);
}
else {
tot_diff_feather_points = 0;
@@ -287,101 +637,220 @@ void BLI_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
if (do_mask_aa == TRUE) {
if (do_feather == FALSE) {
tot_diff_feather_points = tot_diff_point;
- diff_feather_points = MEM_mallocN(sizeof(*diff_feather_points) * tot_diff_feather_points, __func__);
+ diff_feather_points = MEM_mallocN(sizeof(*diff_feather_points) * tot_diff_feather_points,
+ __func__);
/* add single pixel feather */
- maskrasterize_spline_differentiate_point_inset(diff_feather_points, diff_points,
- tot_diff_point, aa_filter_size, FALSE);
+ maskrasterize_spline_differentiate_point_outset(diff_feather_points, diff_points,
+ tot_diff_point, pixel_size, FALSE);
}
else {
/* ensure single pixel feather, on any zero feather areas */
- maskrasterize_spline_differentiate_point_inset(diff_feather_points, diff_points,
- tot_diff_point, aa_filter_size, TRUE);
+ maskrasterize_spline_differentiate_point_outset(diff_feather_points, diff_points,
+ tot_diff_point, pixel_size, TRUE);
}
}
- copy_v2_v2(co, diff_points[0]);
- sf_vert_prev = BLI_scanfill_vert_add(&sf_ctx, co);
- sf_vert_prev->tmp.u = sf_vert_tot;
- sf_vert_prev->keyindex = sf_vert_tot + tot_diff_point; /* absolute index of feather vert */
- sf_vert_tot++;
-
- /* TODO, an alternate functions so we can avoid double vector copy! */
- for (j = 1; j < tot_diff_point; j++) {
- copy_v2_v2(co, diff_points[j]);
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co);
- sf_vert->tmp.u = sf_vert_tot;
- sf_vert->keyindex = sf_vert_tot + tot_diff_point; /* absolute index of feather vert */
+ if (is_fill) {
+ copy_v2_v2(co, diff_points[0]);
+ sf_vert_prev = BLI_scanfill_vert_add(&sf_ctx, co);
+ sf_vert_prev->tmp.u = sf_vert_tot;
+ sf_vert_prev->keyindex = sf_vert_tot + tot_diff_point; /* absolute index of feather vert */
sf_vert_tot++;
- }
-
- sf_vert = sf_vert_prev;
- sf_vert_prev = sf_ctx.fillvertbase.last;
- for (j = 0; j < tot_diff_point; j++) {
- ScanFillEdge *sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_prev, sf_vert);
- sf_edge->tmp.c = SF_EDGE_IS_BOUNDARY;
-
- sf_vert_prev = sf_vert;
- sf_vert = sf_vert->next;
- }
-
- if (diff_feather_points) {
- float co_feather[3];
- co_feather[2] = 1.0f;
+ /* TODO, an alternate functions so we can avoid double vector copy! */
+ for (j = 1; j < tot_diff_point; j++) {
+ copy_v2_v2(co, diff_points[j]);
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, co);
+ sf_vert->tmp.u = sf_vert_tot;
+ sf_vert->keyindex = sf_vert_tot + tot_diff_point; /* absolute index of feather vert */
+ sf_vert_tot++;
+ }
- BLI_assert(tot_diff_feather_points == tot_diff_point);
+ sf_vert = sf_vert_prev;
+ sf_vert_prev = sf_ctx.fillvertbase.last;
- /* note: only added for convenience, we dont infact use these to scanfill,
- * only to create feather faces after scanfill */
- for (j = 0; j < tot_diff_feather_points; j++) {
- copy_v2_v2(co_feather, diff_feather_points[j]);
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
+ for (j = 0; j < tot_diff_point; j++) {
+ ScanFillEdge *sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_prev, sf_vert);
- /* no need for these attrs */
-#if 0
- sf_vert->tmp.u = sf_vert_tot;
- sf_vert->keyindex = sf_vert_tot + tot_diff_point; /* absolute index of feather vert */
+#ifdef USE_SCANFILL_EDGE_WORKAROUND
+ if (diff_feather_points) {
+ sf_edge->tmp.c = SF_EDGE_IS_BOUNDARY;
+ tot_boundary_used++;
+ }
+#else
+ (void)sf_edge;
#endif
- sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
- sf_vert_tot++;
+ sf_vert_prev = sf_vert;
+ sf_vert = sf_vert->next;
}
if (diff_feather_points) {
- MEM_freeN(diff_feather_points);
+ float co_feather[3];
+ co_feather[2] = 1.0f;
+
+ BLI_assert(tot_diff_feather_points == tot_diff_point);
+
+ /* note: only added for convenience, we don't infact use these to scanfill,
+ * only to create feather faces after scanfill */
+ for (j = 0; j < tot_diff_feather_points; j++) {
+ copy_v2_v2(co_feather, diff_feather_points[j]);
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
+
+ /* no need for these attrs */
+ #if 0
+ sf_vert->tmp.u = sf_vert_tot;
+ sf_vert->keyindex = sf_vert_tot + tot_diff_point; /* absolute index of feather vert */
+ #endif
+ sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
+ sf_vert_tot++;
+ }
+
+ tot_feather_quads += tot_diff_point;
}
+ }
+ else {
+ /* unfilled spline */
+ if (diff_feather_points) {
+
+ float co_diff[3];
+
+ float co_feather[3];
+ co_feather[2] = 1.0f;
+
+ open_spline_ranges[open_spline_index].vertex_offset = sf_vert_tot;
+ open_spline_ranges[open_spline_index].vertex_total = tot_diff_point;
+
+ /* TODO, an alternate functions so we can avoid double vector copy! */
+ for (j = 0; j < tot_diff_point; j++) {
+
+ /* center vert */
+ copy_v2_v2(co, diff_points[j]);
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, co);
+ sf_vert->tmp.u = sf_vert_tot;
+ sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
+ sf_vert_tot++;
+
+
+ /* feather vert A */
+ copy_v2_v2(co_feather, diff_feather_points[j]);
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
+ sf_vert->tmp.u = sf_vert_tot;
+ sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
+ sf_vert_tot++;
+
+
+ /* feather vert B */
+ sub_v2_v2v2(co_diff, co, co_feather);
+ add_v2_v2v2(co_feather, co, co_diff);
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
+ sf_vert->tmp.u = sf_vert_tot;
+ sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
+ sf_vert_tot++;
+
+ tot_feather_quads += 2;
+ }
+
+ if (!is_cyclic) {
+ tot_feather_quads -= 2;
+ }
+
+ /* cap ends */
+
+ /* dummy init value */
+ open_spline_ranges[open_spline_index].vertex_total_cap_head = 0;
+ open_spline_ranges[open_spline_index].vertex_total_cap_tail = 0;
+
+ if (!is_cyclic) {
+ float *fp_cent;
+ float *fp_turn;
+
+ unsigned int k;
+
+ fp_cent = diff_points[0];
+ fp_turn = diff_feather_points[0];
+
+#define CALC_CAP_RESOL \
+ clampis_uint((len_v2v2(fp_cent, fp_turn) / (pixel_size * SPLINE_RESOL_CAP_PER_PIXEL)), \
+ SPLINE_RESOL_CAP_MIN, \
+ SPLINE_RESOL_CAP_MAX)
+
+ {
+ const unsigned int vertex_total_cap = CALC_CAP_RESOL;
+
+ for (k = 1; k < vertex_total_cap; k++) {
+ const float angle = (float)k * (1.0f / vertex_total_cap) * (float)M_PI;
+ rotate_point_v2(co_feather, fp_turn, fp_cent, angle, asp_xy);
+
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
+ sf_vert->tmp.u = sf_vert_tot;
+ sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
+ sf_vert_tot++;
+ }
+ tot_feather_quads += vertex_total_cap;
+
+ open_spline_ranges[open_spline_index].vertex_total_cap_head = vertex_total_cap;
+ }
+
+ fp_cent = diff_points[tot_diff_point - 1];
+ fp_turn = diff_feather_points[tot_diff_point - 1];
+
+ {
+ const unsigned int vertex_total_cap = CALC_CAP_RESOL;
+
+ for (k = 1; k < vertex_total_cap; k++) {
+ const float angle = (float)k * (1.0f / vertex_total_cap) * (float)M_PI;
+ rotate_point_v2(co_feather, fp_turn, fp_cent, -angle, asp_xy);
- tot_feather_quads += tot_diff_point;
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
+ sf_vert->tmp.u = sf_vert_tot;
+ sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
+ sf_vert_tot++;
+ }
+ tot_feather_quads += vertex_total_cap;
+
+ open_spline_ranges[open_spline_index].vertex_total_cap_tail = vertex_total_cap;
+ }
+ }
+
+ open_spline_ranges[open_spline_index].is_cyclic = is_cyclic;
+ open_spline_index++;
+
+#undef CALC_CAP_RESOL
+ /* end capping */
+
+ }
}
}
if (diff_points) {
MEM_freeN(diff_points);
}
+
+ if (diff_feather_points) {
+ MEM_freeN(diff_feather_points);
+ }
}
- if (sf_ctx.fillvertbase.first) {
- unsigned int (*tri_array)[4], *tri; /* access coords */
- float (*tri_coords)[3], *cos; /* xy, z 0-1 (1.0 == filled) */
+ {
+ unsigned int (*face_array)[4], *face; /* access coords */
+ float (*face_coords)[3], *cos; /* xy, z 0-1 (1.0 == filled) */
int sf_tri_tot;
rctf bounds;
- int tri_index;
-
- BVHTree *bvhtree;
- float bvhcos[4][3];
+ int face_index;
/* now we have all the splines */
- tri_coords = MEM_mallocN((sizeof(float) * 3) * sf_vert_tot, "maskrast_tri_coords");
+ face_coords = MEM_mallocN((sizeof(float) * 3) * sf_vert_tot, "maskrast_face_coords");
/* init bounds */
BLI_rctf_init_minmax(&bounds);
/* coords */
- cos = (float *)tri_coords;
+ cos = (float *)face_coords;
for (sf_vert = sf_ctx.fillvertbase.first; sf_vert; sf_vert = sf_vert_next) {
sf_vert_next = sf_vert->next;
copy_v3_v3(cos, sf_vert->co);
- /* remove so as not to interfear with fill (called after) */
+ /* remove so as not to interfere with fill (called after) */
if (sf_vert->keyindex == SF_KEYINDEX_TEMP_ID) {
BLI_remlink(&sf_ctx.fillvertbase, sf_vert);
}
@@ -392,78 +861,210 @@ void BLI_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
cos += 3;
}
- /* main scanfill */
+ /* main scan-fill */
sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, FALSE, zvec);
- tri_array = MEM_mallocN(sizeof(*tri_array) * (sf_tri_tot + tot_feather_quads), "maskrast_tri_index");
-
- /* */
- bvhtree = BLI_bvhtree_new(sf_tri_tot + tot_feather_quads, 0.000001f, 8, 6);
-
- /* tri's */
- tri = (unsigned int *)tri_array;
- for (sf_tri = sf_ctx.fillfacebase.first, tri_index = 0; sf_tri; sf_tri = sf_tri->next, tri_index++) {
- *(tri++) = sf_tri->v1->tmp.u;
- *(tri++) = sf_tri->v2->tmp.u;
- *(tri++) = sf_tri->v3->tmp.u;
- *(tri++) = TRI_VERT;
-
- copy_v3_v3(bvhcos[0], tri_coords[*(tri - 4)]);
- copy_v3_v3(bvhcos[1], tri_coords[*(tri - 3)]);
- copy_v3_v3(bvhcos[2], tri_coords[*(tri - 2)]);
-
- BLI_bvhtree_insert(bvhtree, tri_index, (float *)bvhcos, 3);
+ face_array = MEM_mallocN(sizeof(*face_array) * (sf_tri_tot + tot_feather_quads), "maskrast_face_index");
+ face_index = 0;
+
+ /* faces */
+ face = (unsigned int *)face_array;
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ *(face++) = sf_tri->v3->tmp.u;
+ *(face++) = sf_tri->v2->tmp.u;
+ *(face++) = sf_tri->v1->tmp.u;
+ *(face++) = TRI_VERT;
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
}
/* start of feather faces... if we have this set,
- * 'tri_index' is kept from loop above */
+ * 'face_index' is kept from loop above */
- BLI_assert(tri_index == sf_tri_tot);
+ BLI_assert(face_index == sf_tri_tot);
if (tot_feather_quads) {
ScanFillEdge *sf_edge;
for (sf_edge = sf_ctx.filledgebase.first; sf_edge; sf_edge = sf_edge->next) {
if (sf_edge->tmp.c == SF_EDGE_IS_BOUNDARY) {
- *(tri++) = sf_edge->v1->tmp.u;
- *(tri++) = sf_edge->v2->tmp.u;
- *(tri++) = sf_edge->v2->keyindex;
- *(tri++) = sf_edge->v1->keyindex;
+ *(face++) = sf_edge->v1->tmp.u;
+ *(face++) = sf_edge->v2->tmp.u;
+ *(face++) = sf_edge->v2->keyindex;
+ *(face++) = sf_edge->v1->keyindex;
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
+
+#ifdef USE_SCANFILL_EDGE_WORKAROUND
+ tot_boundary_found++;
+#endif
+ }
+ }
+ }
+
+#ifdef USE_SCANFILL_EDGE_WORKAROUND
+ if (tot_boundary_found != tot_boundary_used) {
+ BLI_assert(tot_boundary_found < tot_boundary_used);
+ }
+#endif
+
+ /* feather only splines */
+ while (open_spline_index > 0) {
+ const unsigned int vertex_offset = open_spline_ranges[--open_spline_index].vertex_offset;
+ unsigned int vertex_total = open_spline_ranges[ open_spline_index].vertex_total;
+ unsigned int vertex_total_cap_head = open_spline_ranges[ open_spline_index].vertex_total_cap_head;
+ unsigned int vertex_total_cap_tail = open_spline_ranges[ open_spline_index].vertex_total_cap_tail;
+ unsigned int k, j;
+
+ j = vertex_offset;
+
+ /* subtract one since we reference next vertex triple */
+ for (k = 0; k < vertex_total - 1; k++, j += 3) {
+
+ BLI_assert(j == vertex_offset + (k * 3));
+
+ *(face++) = j + 3; /* next span */ /* z 1 */
+ *(face++) = j + 0; /* z 1 */
+ *(face++) = j + 1; /* z 0 */
+ *(face++) = j + 4; /* next span */ /* z 0 */
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
+
+ *(face++) = j + 0; /* z 1 */
+ *(face++) = j + 3; /* next span */ /* z 1 */
+ *(face++) = j + 5; /* next span */ /* z 0 */
+ *(face++) = j + 2; /* z 0 */
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
+ }
+
+ if (open_spline_ranges[open_spline_index].is_cyclic) {
+ *(face++) = vertex_offset + 0; /* next span */ /* z 1 */
+ *(face++) = j + 0; /* z 1 */
+ *(face++) = j + 1; /* z 0 */
+ *(face++) = vertex_offset + 1; /* next span */ /* z 0 */
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
+
+ *(face++) = j + 0; /* z 1 */
+ *(face++) = vertex_offset + 0; /* next span */ /* z 1 */
+ *(face++) = vertex_offset + 2; /* next span */ /* z 0 */
+ *(face++) = j + 2; /* z 0 */
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
+ }
+ else {
+ unsigned int midvidx = vertex_offset;
+
+ /***************
+ * cap end 'a' */
+ j = midvidx + (vertex_total * 3);
+
+ for (k = 0; k < vertex_total_cap_head - 2; k++, j++) {
+ *(face++) = midvidx + 0; /* z 1 */
+ *(face++) = midvidx + 0; /* z 1 */
+ *(face++) = j + 0; /* z 0 */
+ *(face++) = j + 1; /* z 0 */
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
+ }
+
+ j = vertex_offset + (vertex_total * 3);
+
+ /* 2 tris that join the original */
+ *(face++) = midvidx + 0; /* z 1 */
+ *(face++) = midvidx + 0; /* z 1 */
+ *(face++) = midvidx + 1; /* z 0 */
+ *(face++) = j + 0; /* z 0 */
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
+
+ *(face++) = midvidx + 0; /* z 1 */
+ *(face++) = midvidx + 0; /* z 1 */
+ *(face++) = j + vertex_total_cap_head - 2; /* z 0 */
+ *(face++) = midvidx + 2; /* z 0 */
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
+
+
+ /***************
+ * cap end 'b' */
+ /* ... same as previous but v 2-3 flipped, and different initial offsets */
- copy_v3_v3(bvhcos[0], tri_coords[*(tri - 4)]);
- copy_v3_v3(bvhcos[1], tri_coords[*(tri - 3)]);
- copy_v3_v3(bvhcos[2], tri_coords[*(tri - 2)]);
- copy_v3_v3(bvhcos[3], tri_coords[*(tri - 1)]);
+ j = vertex_offset + (vertex_total * 3) + (vertex_total_cap_head - 1);
- BLI_bvhtree_insert(bvhtree, tri_index++, (const float *)bvhcos, 4);
+ midvidx = vertex_offset + (vertex_total * 3) - 3;
+
+ for (k = 0; k < vertex_total_cap_tail - 2; k++, j++) {
+ *(face++) = midvidx; /* z 1 */
+ *(face++) = midvidx; /* z 1 */
+ *(face++) = j + 1; /* z 0 */
+ *(face++) = j + 0; /* z 0 */
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
}
+
+ j = vertex_offset + (vertex_total * 3) + (vertex_total_cap_head - 1);
+
+ /* 2 tris that join the original */
+ *(face++) = midvidx + 0; /* z 1 */
+ *(face++) = midvidx + 0; /* z 1 */
+ *(face++) = j + 0; /* z 0 */
+ *(face++) = midvidx + 1; /* z 0 */
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
+
+ *(face++) = midvidx + 0; /* z 1 */
+ *(face++) = midvidx + 0; /* z 1 */
+ *(face++) = midvidx + 2; /* z 0 */
+ *(face++) = j + vertex_total_cap_tail - 2; /* z 0 */
+ face_index++;
+ FACE_ASSERT(face - 4, sf_vert_tot);
+
}
}
- fprintf(stderr, "%d %d\n", tri_index, sf_tri_tot + tot_feather_quads);
-
- BLI_assert(tri_index == sf_tri_tot + tot_feather_quads);
+ MEM_freeN(open_spline_ranges);
- BLI_bvhtree_balance(bvhtree);
+// fprintf(stderr, "%u %u (%u %u), %u\n", face_index, sf_tri_tot + tot_feather_quads, sf_tri_tot, tot_feather_quads, tot_boundary_used - tot_boundary_found);
+#ifdef USE_SCANFILL_EDGE_WORKAROUND
+ BLI_assert(face_index + (tot_boundary_used - tot_boundary_found) == sf_tri_tot + tot_feather_quads);
+#else
+ BLI_assert(face_index == sf_tri_tot + tot_feather_quads);
+#endif
{
- MaskRasterLayer *raslayer = &mr_handle->layers[masklay_index];
+ MaskRasterLayer *layer = &mr_handle->layers[masklay_index];
- raslayer->tri_coords = tri_coords;
- raslayer->tri_array = tri_array;
- raslayer->bounds = bounds;
- raslayer->bvhtree = bvhtree;
+ if (BLI_rctf_isect(&default_bounds, &bounds, &bounds)) {
+#ifdef USE_SCANFILL_EDGE_WORKAROUND
+ layer->face_tot = (sf_tri_tot + tot_feather_quads) - (tot_boundary_used - tot_boundary_found);
+#else
+ layer->face_tot = (sf_tri_tot + tot_feather_quads);
+#endif
+ layer->face_coords = face_coords;
+ layer->face_array = face_array;
+ layer->bounds = bounds;
- /* copy as-is */
- raslayer->alpha = masklay->alpha;
- raslayer->blend = masklay->blend;
- raslayer->blend_flag = masklay->blend_flag;
+ layer_bucket_init(layer, pixel_size);
+
+ BLI_rctf_union(&mr_handle->bounds, &bounds);
+ }
+ else {
+ MEM_freeN(face_coords);
+ MEM_freeN(face_array);
+ layer_bucket_init_dummy(layer);
+ }
- BLI_union_rctf(&mr_handle->bounds, &bounds);
+ /* copy as-is */
+ layer->alpha = masklay->alpha;
+ layer->blend = masklay->blend;
+ layer->blend_flag = masklay->blend_flag;
+ layer->falloff = masklay->falloff;
}
- PRINT_MASK_DEBUG("tris %d, feather tris %d\n", sf_tri_tot, tot_feather_quads);
+ /* printf("tris %d, feather tris %d\n", sf_tri_tot, tot_feather_quads); */
}
/* add trianges */
@@ -471,12 +1072,13 @@ void BLI_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
}
}
-//static void tri_flip_tri(unsigned int tri[3])
-//{
-//}
+/* --------------------------------------------------------------------- */
+/* functions that run inside the sampling thread (keep fast!) */
+/* --------------------------------------------------------------------- */
/* 2D ray test */
+#if 0
static float maskrasterize_layer_z_depth_tri(const float pt[2],
const float v1[3], const float v2[3], const float v3[3])
{
@@ -484,47 +1086,44 @@ static float maskrasterize_layer_z_depth_tri(const float pt[2],
barycentric_weights_v2(v1, v2, v3, pt, w);
return (v1[2] * w[0]) + (v2[2] * w[1]) + (v3[2] * w[2]);
}
+#endif
-#if 0
+#if 1
static float maskrasterize_layer_z_depth_quad(const float pt[2],
const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
float w[4];
barycentric_weights_v2_quad(v1, v2, v3, v4, pt, w);
- return (v1[2] * w[0]) + (v2[2] * w[1]) + (v3[2] * w[2]) + (v4[2] * w[3]);
+ //return (v1[2] * w[0]) + (v2[2] * w[1]) + (v3[2] * w[2]) + (v4[2] * w[3]);
+ return w[2] + w[3]; /* we can make this assumption for small speedup */
}
#endif
-static void maskrasterize_layer_bvh_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+static float maskrasterize_layer_isect(unsigned int *face, float (*cos)[3], const float dist_orig, const float xy[2])
{
- MaskRasterLayer *layer = (struct MaskRasterLayer *)userdata;
- unsigned int *tri = layer->tri_array[index];
- float (*cos)[3] = layer->tri_coords;
- const float dist_orig = hit->dist;
-
/* we always cast from same place only need xy */
- if (tri[3] == TRI_VERT) {
+ if (face[3] == TRI_VERT) {
/* --- tri --- */
+#if 0
/* not essential but avoids unneeded extra lookups */
if ((cos[0][2] < dist_orig) ||
(cos[1][2] < dist_orig) ||
(cos[2][2] < dist_orig))
{
- if (isect_point_tri_v2(ray->origin, cos[tri[0]], cos[tri[1]], cos[tri[2]])) {
+ if (isect_point_tri_v2_cw(xy, cos[face[0]], cos[face[1]], cos[face[2]])) {
/* we know all tris are close for now */
-#if 0
- const float dist = maskrasterize_layer_z_depth_tri(ray->origin, cos[tri[0]], cos[tri[1]], cos[tri[2]]);
- if (dist < dist_orig) {
- hit->index = index;
- hit->dist = dist;
- }
+ return maskrasterize_layer_z_depth_tri(xy, cos[face[0]], cos[face[1]], cos[face[2]]);
+ }
+ }
#else
- hit->index = index;
- hit->dist = 0.0f;
-#endif
+ /* we know all tris are close for now */
+ if (1) {
+ if (isect_point_tri_v2_cw(xy, cos[face[0]], cos[face[1]], cos[face[2]])) {
+ return 0.0f;
}
}
+#endif
}
else {
/* --- quad --- */
@@ -537,28 +1136,22 @@ static void maskrasterize_layer_bvh_cb(void *userdata, int index, const BVHTreeR
{
/* needs work */
-#if 0
- if (isect_point_quad_v2(ray->origin, cos[tri[0]], cos[tri[1]], cos[tri[2]], cos[tri[3]])) {
- const float dist = maskrasterize_layer_z_depth_quad(ray->origin, cos[tri[0]], cos[tri[1]], cos[tri[2]], cos[tri[3]]);
- if (dist < dist_orig) {
- hit->index = index;
- hit->dist = dist;
- }
+#if 1
+ /* quad check fails for bowtie, so keep using 2 tri checks */
+ //if (isect_point_quad_v2(xy, cos[face[0]], cos[face[1]], cos[face[2]], cos[face[3]]))
+ if (isect_point_tri_v2(xy, cos[face[0]], cos[face[1]], cos[face[2]]) ||
+ isect_point_tri_v2(xy, cos[face[0]], cos[face[2]], cos[face[3]]))
+ {
+ return maskrasterize_layer_z_depth_quad(xy, cos[face[0]], cos[face[1]], cos[face[2]], cos[face[3]]);
}
#elif 1
- if (isect_point_tri_v2(ray->origin, cos[tri[0]], cos[tri[1]], cos[tri[2]])) {
- const float dist = maskrasterize_layer_z_depth_tri(ray->origin, cos[tri[0]], cos[tri[1]], cos[tri[2]]);
- if (dist < dist_orig) {
- hit->index = index;
- hit->dist = dist;
- }
+ /* don't use isect_point_tri_v2_cw because we could have bowtie quads */
+
+ if (isect_point_tri_v2(xy, cos[face[0]], cos[face[1]], cos[face[2]])) {
+ return maskrasterize_layer_z_depth_tri(xy, cos[face[0]], cos[face[1]], cos[face[2]]);
}
- else if (isect_point_tri_v2(ray->origin, cos[tri[0]], cos[tri[2]], cos[tri[3]])) {
- const float dist = maskrasterize_layer_z_depth_tri(ray->origin, cos[tri[0]], cos[tri[2]], cos[tri[3]]);
- if (dist < dist_orig) {
- hit->index = index;
- hit->dist = dist;
- }
+ else if (isect_point_tri_v2(xy, cos[face[0]], cos[face[2]], cos[face[3]])) {
+ return maskrasterize_layer_z_depth_tri(xy, cos[face[0]], cos[face[2]], cos[face[3]]);
}
#else
/* cheat - we know first 2 verts are z0.0f and second 2 are z 1.0f */
@@ -566,73 +1159,131 @@ static void maskrasterize_layer_bvh_cb(void *userdata, int index, const BVHTreeR
#endif
}
}
+
+ return 1.0f;
}
-float BLI_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float xy[2])
+BLI_INLINE unsigned int layer_bucket_index_from_xy(MaskRasterLayer *layer, const float xy[2])
{
- /* TODO - AA jitter */
-
- if (BLI_in_rctf_v(&mr_handle->bounds, xy)) {
- const unsigned int layers_tot = mr_handle->layers_tot;
- unsigned int i;
- MaskRasterLayer *layer = mr_handle->layers;
-
- /* raycast vars*/
- const float co[3] = {xy[0], xy[1], 0.0f};
- const float dir[3] = {0.0f, 0.0f, 1.0f};
- const float radius = 1.0f;
- BVHTreeRayHit hit = {0};
-
- /* return */
- float value = 0.0f;
+ BLI_assert(BLI_in_rctf_v(&layer->bounds, xy));
- for (i = 0; i < layers_tot; i++, layer++) {
-
- if (BLI_in_rctf_v(&layer->bounds, xy)) {
-
- hit.dist = FLT_MAX;
- hit.index = -1;
+ return ( (unsigned int)((xy[0] - layer->bounds.xmin) * layer->buckets_xy_scalar[0])) +
+ (((unsigned int)((xy[1] - layer->bounds.ymin) * layer->buckets_xy_scalar[1])) * layer->buckets_x);
+}
- /* TODO, and axis aligned version of this function, avoids 2 casts */
- BLI_bvhtree_ray_cast(layer->bvhtree, co, dir, radius, &hit, maskrasterize_layer_bvh_cb, layer);
+static float layer_bucket_depth_from_xy(MaskRasterLayer *layer, const float xy[2])
+{
+ unsigned int index = layer_bucket_index_from_xy(layer, xy);
+ unsigned int *face_index = layer->buckets_face[index];
+
+ if (face_index) {
+ unsigned int (*face_array)[4] = layer->face_array;
+ float (*cos)[3] = layer->face_coords;
+ float best_dist = 1.0f;
+ while (*face_index != TRI_TERMINATOR_ID) {
+ const float test_dist = maskrasterize_layer_isect(face_array[*face_index], cos, best_dist, xy);
+ if (test_dist < best_dist) {
+ best_dist = test_dist;
+ /* comparing with 0.0f is OK here because triangles are always zero depth */
+ if (best_dist == 0.0f) {
+ /* bail early, we're as close as possible */
+ return 0.0f;
+ }
+ }
+ face_index++;
+ }
+ return best_dist;
+ }
+ else {
+ return 1.0f;
+ }
+}
- /* --- hit (start) --- */
- if (hit.index != -1) {
- const float dist = 1.0f - hit.dist;
- const float dist_ease = (3.0f * dist * dist - 2.0f * dist * dist * dist);
+float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float xy[2])
+{
+ /* can't do this because some layers may invert */
+ /* if (BLI_in_rctf_v(&mr_handle->bounds, xy)) */
- float v;
- /* apply alpha */
- v = dist_ease * layer->alpha;
+ const unsigned int layers_tot = mr_handle->layers_tot;
+ unsigned int i;
+ MaskRasterLayer *layer = mr_handle->layers;
+
+ /* return value */
+ float value = 0.0f;
+
+ for (i = 0; i < layers_tot; i++, layer++) {
+ float value_layer;
+
+ /* also used as signal for unused layer (when render is disabled) */
+ if (layer->alpha != 0.0f && BLI_in_rctf_v(&layer->bounds, xy)) {
+ value_layer = 1.0f - layer_bucket_depth_from_xy(layer, xy);
+
+ switch (layer->falloff) {
+ case PROP_SMOOTH:
+ /* ease - gives less hard lines for dilate/erode feather */
+ value_layer = (3.0f * value_layer * value_layer - 2.0f * value_layer * value_layer * value_layer);
+ break;
+ case PROP_SPHERE:
+ value_layer = sqrtf(2.0f * value_layer - value_layer * value_layer);
+ break;
+ case PROP_ROOT:
+ value_layer = sqrtf(value_layer);
+ break;
+ case PROP_SHARP:
+ value_layer = value_layer * value_layer;
+ break;
+ case PROP_LIN:
+ default:
+ /* nothing */
+ break;
+ }
- if (layer->blend_flag & MASK_BLENDFLAG_INVERT) {
- v = 1.0f - v;
- }
+ if (layer->blend != MASK_BLEND_REPLACE) {
+ value_layer *= layer->alpha;
+ }
+ }
+ else {
+ value_layer = 0.0f;
+ }
- switch (layer->blend) {
- case MASK_BLEND_SUBTRACT:
- {
- value -= v;
- break;
- }
- case MASK_BLEND_ADD:
- default:
- {
- value += v;
- break;
- }
- }
- }
- /* --- hit (end) --- */
+ if (layer->blend_flag & MASK_BLENDFLAG_INVERT) {
+ value_layer = 1.0f - value_layer;
+ }
- }
+ switch (layer->blend) {
+ case MASK_BLEND_ADD:
+ value += value_layer;
+ break;
+ case MASK_BLEND_SUBTRACT:
+ value -= value_layer;
+ break;
+ case MASK_BLEND_LIGHTEN:
+ value = maxf(value, value_layer);
+ break;
+ case MASK_BLEND_DARKEN:
+ value = minf(value, value_layer);
+ break;
+ case MASK_BLEND_MUL:
+ value *= value_layer;
+ break;
+ case MASK_BLEND_REPLACE:
+ value = (value * (1.0f - layer->alpha)) + (value_layer * layer->alpha);
+ break;
+ case MASK_BLEND_DIFFERENCE:
+ value = fabsf(value - value_layer);
+ break;
+ default: /* same as add */
+ BLI_assert(0);
+ value += value_layer;
+ break;
}
- return CLAMPIS(value, 0.0f, 1.0f);
- }
- else {
- return 0.0f;
+ /* clamp after applying each layer so we don't get
+ * issues subtracting after accumulating over 1.0f */
+ CLAMP(value, 0.0f, 1.0f);
}
+
+ return value;
}
#endif /* USE_RASKTER */
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index b5b03a8924f..f897543db18 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -2307,7 +2307,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
metaball_tree = NULL;
}
- /* if scene includes more then one MetaElem, then octal tree optimalisation is used */
+ /* if scene includes more then one MetaElem, then octal tree optimization is used */
if ((totelem > 1) && (totelem <= 64)) init_metaball_octal_tree(1);
if ((totelem > 64) && (totelem <= 128)) init_metaball_octal_tree(2);
if ((totelem > 128) && (totelem <= 512)) init_metaball_octal_tree(3);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 8d81e7b595d..c5752e193df 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -1230,7 +1230,7 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
MEdge **alledge, int *totedge, MLoop **allloop, MPoly **allpoly,
int *totloop, int *totpoly)
{
- return BKE_mesh_nurbs_to_mdata_customdb(ob, &ob->disp,
+ return BKE_mesh_nurbs_displist_to_mdata(ob, &ob->disp,
allvert, totvert,
alledge, totedge,
allloop, allpoly,
@@ -1242,7 +1242,7 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
/* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
/* use specified dispbase */
-int BKE_mesh_nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase,
+int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
MVert **allvert, int *_totvert,
MEdge **alledge, int *_totedge,
MLoop **allloop, MPoly **allpoly,
@@ -1462,7 +1462,7 @@ int BKE_mesh_nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase,
}
/* this may fail replacing ob->data, be sure to check ob->type */
-void BKE_mesh_from_nurbs(Object *ob)
+void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase)
{
Main *bmain = G.main;
Object *ob1;
@@ -1478,9 +1478,9 @@ void BKE_mesh_from_nurbs(Object *ob)
cu = ob->data;
if (dm == NULL) {
- if (BKE_mesh_nurbs_to_mdata(ob, &allvert, &totvert,
- &alledge, &totedge, &allloop,
- &allpoly, &totloop, &totpoly) != 0)
+ if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert,
+ &alledge, &totedge, &allloop,
+ &allpoly, &totloop, &totpoly) != 0)
{
/* Error initializing */
return;
@@ -1534,6 +1534,11 @@ void BKE_mesh_from_nurbs(Object *ob)
}
}
+void BKE_mesh_from_nurbs(Object *ob)
+{
+ return BKE_mesh_from_nurbs_displist(ob, &ob->disp);
+}
+
typedef struct EdgeLink {
Link *next, *prev;
void *edge;
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 2bc5c37b41b..866194eea0e 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -992,6 +992,9 @@ static void grid_tangent_matrix(float mat[3][3], const CCGKey *key,
copy_v3_v3(mat[2], CCG_grid_elem_no(key, grid, x, y));
}
+/* XXX WARNING: subsurf elements from dm and oldGridData *must* be of the same format (size),
+ * because this code uses CCGKey's info from dm to access oldGridData's normals
+ * (through the call to grid_tangent_matrix())! */
static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, DispOp op, CCGElem **oldGridData, int totlvl)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
@@ -1064,9 +1067,12 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm
/* if needed, reallocate multires paint mask */
if (gpm && gpm->level < key.level) {
gpm->level = key.level;
- if (gpm->data)
- MEM_freeN(gpm->data);
- gpm->data = MEM_callocN(sizeof(float) * key.grid_area, "gpm.data");
+ #pragma omp critical
+ {
+ if (gpm->data)
+ MEM_freeN(gpm->data);
+ gpm->data = MEM_callocN(sizeof(float) * key.grid_area, "gpm.data");
+ }
}
for (y = 0; y < gridSize; y++) {
@@ -2069,6 +2075,21 @@ void multires_load_old(Object *ob, Mesh *me)
me->mface[i].mat_nr = lvl->faces[i].mat_nr;
}
+ /* Copy the first-level data to the mesh */
+ /* XXX We must do this before converting tessfaces to polys/lopps! */
+ for (i = 0, l = me->mr->vdata.layers; i < me->mr->vdata.totlayer; ++i, ++l)
+ CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert);
+ for (i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; ++i, ++l)
+ CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface);
+ memset(&me->mr->vdata, 0, sizeof(CustomData));
+ memset(&me->mr->fdata, 0, sizeof(CustomData));
+
+ multires_load_old_vcols(me);
+ multires_load_old_face_flags(me);
+
+ /* multiresModifier_subdivide (actually, multires_subdivide) expects polys, not tessfaces! */
+ BKE_mesh_convert_mfaces_to_mpolys(me);
+
/* Add a multires modifier to the object */
md = ob->modifiers.first;
while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
@@ -2081,31 +2102,25 @@ void multires_load_old(Object *ob, Mesh *me)
mmd->lvl = mmd->totlvl;
orig = CDDM_from_mesh(me, NULL);
- dm = multires_make_derived_from_derived(orig, mmd, ob, 0);
-
+ /* XXX We *must* alloc paint mask here, else we have some kind of mismatch in
+ * multires_modifier_update_mdisps() (called by dm->release(dm)), which always creates the
+ * reference subsurfed dm with this option, before calling multiresModifier_disp_run(),
+ * which implicitly expects both subsurfs from its first dm and oldGridData parameters to
+ * be of the same "format"! */
+ dm = multires_make_derived_from_derived(orig, mmd, ob, MULTIRES_ALLOC_PAINT_MASK);
+
multires_load_old_dm(dm, me, mmd->totlvl + 1);
multires_dm_mark_as_modified(dm, MULTIRES_COORDS_MODIFIED);
dm->release(dm);
orig->release(orig);
- /* Copy the first-level data to the mesh */
- for (i = 0, l = me->mr->vdata.layers; i < me->mr->vdata.totlayer; ++i, ++l)
- CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert);
- for (i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; ++i, ++l)
- CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface);
- memset(&me->mr->vdata, 0, sizeof(CustomData));
- memset(&me->mr->fdata, 0, sizeof(CustomData));
-
- multires_load_old_vcols(me);
- multires_load_old_face_flags(me);
-
/* Remove the old multires */
multires_free(me->mr);
me->mr = NULL;
}
-/* If 'ob' and 'to_ob' both have multires modifiers, syncronize them
+/* If 'ob' and 'to_ob' both have multires modifiers, synchronize them
* such that 'ob' has the same total number of levels as 'to_ob'. */
static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob)
{
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index f471ffef0f6..2692e2a2929 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -3166,7 +3166,7 @@ static void obrel_list_add(LinkNode **links, Object *ob)
* If OB_SET_VISIBLE or OB_SET_SELECTED are collected,
* then also add related objects according to the given includeFilters.
*/
-struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter)
+LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter)
{
LinkNode *links = NULL;
@@ -3245,3 +3245,32 @@ struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet
return links;
}
+
+/**
+ * return all groups this object is apart of, caller must free.
+ */
+struct LinkNode *BKE_object_groups(Object *ob)
+{
+ LinkNode *group_linknode = NULL;
+ Group *group = NULL;
+ while ((group = find_group(ob, group))) {
+ BLI_linklist_prepend(&group_linknode, group);
+ }
+
+ return group_linknode;
+}
+
+void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
+{
+ Group *group = NULL;
+
+ BLI_assert(base->object == object);
+
+ if (scene && base == NULL) {
+ base = BKE_scene_base_find(scene, object);
+ }
+
+ while ((group = find_group(base->object, group))) {
+ rem_from_group(group, object, scene, base);
+ }
+}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index aa798f59482..0b3131f0a1c 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -2159,7 +2159,9 @@ static void integrate_particle(ParticleSettings *part, ParticleData *pa, float d
break;
}
- copy_particle_key(states, &pa->state, 1);
+ for (i=0; i<steps; i++) {
+ copy_particle_key(states + i, &pa->state, 1);
+ }
states->time = 0.f;
@@ -2441,7 +2443,8 @@ static void sph_particle_courant(SPHData *sphdata, SPHRangeData *pfr)
int i;
float flow[3], offset[3], dist;
- flow[0] = flow[1] = flow[2] = 0.0f;
+ zero_v3(flow);
+
dist = 0.0f;
if (pfr->tot_neighbors > 0) {
pa = pfr->pa;
@@ -2733,13 +2736,17 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
{
float rotfac, rot1[4], rot2[4]={1.0,0.0,0.0,0.0}, dtime=dfra*timestep, extrotfac;
- if ((part->flag & PART_ROTATIONS)==0) {
- pa->state.rot[0]=1.0f;
- pa->state.rot[1]=pa->state.rot[2]=pa->state.rot[3]=0;
+ if ((part->flag & PART_ROTATIONS) == 0) {
+ unit_qt(pa->state.rot);
return;
}
- extrotfac = len_v3(pa->state.ave);
+ if (part->flag & PART_ROT_DYN) {
+ extrotfac = len_v3(pa->state.ave);
+ }
+ else {
+ extrotfac = 0.0f;
+ }
if ((part->flag & PART_ROT_DYN) && ELEM3(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) {
float angle;
@@ -2747,8 +2754,9 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
float len2 = len_v3(pa->state.vel);
float vec[3];
- if (len1==0.0f || len2==0.0f)
- pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0f;
+ if (len1 == 0.0f || len2 == 0.0f) {
+ zero_v3(pa->state.ave);
+ }
else {
cross_v3_v3v3(pa->state.ave, pa->prev_state.vel, pa->state.vel);
normalize_v3(pa->state.ave);
@@ -2761,9 +2769,8 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
}
rotfac = len_v3(pa->state.ave);
- if (rotfac == 0.0f || (part->flag & PART_ROT_DYN)==0 || extrotfac == 0.0f) { /* unit_qt(in VecRotToQuat) doesn't give unit quat [1,0,0,0]?? */
- rot1[0]=1.0f;
- rot1[1]=rot1[2]=rot1[3]=0;
+ if (rotfac == 0.0f || (part->flag & PART_ROT_DYN)==0 || extrotfac == 0.0f) {
+ unit_qt(rot1);
}
else {
axis_angle_to_quat(rot1,pa->state.ave,rotfac*dtime);
@@ -3750,8 +3757,10 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
pa->totkey++;
/* root is always in the origin of hair space so we set it to be so after the last key is saved*/
- if (pa->totkey == psys->part->hair_step + 1)
- root->co[0] = root->co[1] = root->co[2] = 0.0f;
+ if (pa->totkey == psys->part->hair_step + 1) {
+ zero_v3(root->co);
+ }
+
}
}
@@ -4130,9 +4139,8 @@ static void particles_fluid_step(ParticleSimulationData *sim, int UNUSED(cfra))
pa->state.vel[j] = wrf;
}
- pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0f;
- pa->state.rot[0] = 1.0;
- pa->state.rot[1] = pa->state.rot[2] = pa->state.rot[3] = 0.0;
+ zero_v3(pa->state.ave);
+ unit_qt(pa->state.rot);
pa->time = 1.f;
pa->dietime = sim->scene->r.efra + 1;
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index a3fa8f8be89..101f53fe94f 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -326,8 +326,7 @@ static void ptcache_particle_read(int index, void *psys_v, void **data, float cf
/* default to no rotation */
if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
- pa->state.rot[0]=1.0f;
- pa->state.rot[1]=pa->state.rot[2]=pa->state.rot[3]=0;
+ unit_qt(pa->state.rot);
}
}
static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
@@ -2320,7 +2319,7 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
* - simulation time is scaled by result of bsystem_time
* - for offsetting time only time offset is taken into account, since
* that's always the same and can't be animated. a timeoffset which
- * varies over time is not simpe to support.
+ * varies over time is not simple to support.
* - field and motion blur offsets are currently ignored, proper solution
* is probably to interpolate results from two frames for that ..
*/
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 2e2f0e54792..0532a019ecc 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -310,7 +310,7 @@ static void do_alphaunder_effect_byte(
/* rt = rt1 under rt2 (alpha from rt2) */
- /* this complex optimalisation is because the
+ /* this complex optimization is because the
* 'skybuf' can be crossed in
*/
if (rt2[3] == 0 && fac2 == 256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
@@ -379,7 +379,7 @@ static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y,
/* rt = rt1 under rt2 (alpha from rt2) */
- /* this complex optimalisation is because the
+ /* this complex optimization is because the
* 'skybuf' can be crossed in
*/
if (rt2[3] <= 0 && fac2 >= 1.0f) {
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 902eeefd934..b7f72ff86e2 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -464,7 +464,7 @@ void seq_end(SeqIterator *iter)
* **********************************************************************
* build_seqar
* *********************************************************************
- * Build a complete array of _all_ sequencies (including those
+ * Build a complete array of _all_ sequences (including those
* in metastrips!)
* *********************************************************************
*/
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 1d6895a8c71..2c105e4940d 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -78,9 +78,8 @@ variables on the UI for now
#include "BKE_DerivedMesh.h"
#include "BKE_pointcache.h"
#include "BKE_deform.h"
-#include "BKE_mesh.h"
-//XXX #include "BIF_editdeform.h"
-//XXX #include "BIF_graphics.h"
+#include "BKE_mesh.h"
+
#include "PIL_time.h"
// #include "ONL_opennl.h" remove linking to ONL for now
@@ -2914,7 +2913,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
aabbmin[0]=aabbmin[1]=aabbmin[2] = 1e20f;
aabbmax[0]=aabbmax[1]=aabbmax[2] = -1e20f;
- /* old one with homogenous masses */
+ /* old one with homogeneous masses */
/* claim a minimum mass for vertex */
/*
if (sb->nodemass > 0.009999f) timeovermass = forcetime/sb->nodemass;
@@ -3297,7 +3296,7 @@ static void mesh_to_softbody(Scene *scene, Object *ob)
/* I'd like to have it .. if (sb->namedVG_Goal[0]) */
get_scalar_from_vertexgroup(ob, a, (short) (sb->vertgroup-1), &bp->goal);
- /* do this always, regardless successfull read from vertex group */
+ /* do this always, regardless successful read from vertex group */
/* this is where '2.5 every thing is animatable' goes wrong in the first place jow_go_for2_5 */
/* 1st coding action to take : move this to frame level */
/* reads: leave the bp->goal as it was read from vertex group / or default .. we will need it at per frame call */
@@ -3811,7 +3810,7 @@ static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCo
* that is:
* a precise position vector denoting the motion of the center of mass
* give a rotation/scale matrix using averaging method, that's why estimate and not calculate
- * see: this is kind of reverse engeneering: having to states of a point cloud and recover what happend
+ * see: this is kind of reverse engineering: having to states of a point cloud and recover what happend
* our advantage here we know the identity of the vertex
* there are others methods giving other results.
* lloc, lrot, lscale are allowed to be NULL, just in case you don't need it.