diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2012-07-21 03:12:05 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2012-07-21 03:12:05 +0400 |
commit | 3b012c041f1fb7b78eddcf1f93288cf7a86ab8d6 (patch) | |
tree | cead235bff7687610b1372e709e742ef70692dcb /source/blender/blenkernel | |
parent | 5a581c1fd116c51df13e09c5c320feba48d069bb (diff) | |
parent | 16516238e2b25ce53144c2dcea5323dc7313b724 (diff) |
Merged changes in the trunk up to revision 49090.
Diffstat (limited to 'source/blender/blenkernel')
23 files changed, 1303 insertions, 333 deletions
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 37763003099..eeebcdafe48 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -66,7 +66,7 @@ struct DerivedMesh *CDDM_from_curve(struct Object *ob); /* creates a CDDerivedMesh from the given curve object and specified dispbase */ /* useful for OrcoDM creation for curves with constructive modifiers */ -DerivedMesh *CDDM_from_curve_customDB(struct Object *ob, struct ListBase *dispbase); +DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispbase); /* Copies the given DerivedMesh with verts, faces & edges stored as * custom element data. diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 50d8576dd91..9a4f30c853f 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -64,14 +64,19 @@ void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, struct ListBase * /* splines */ struct MaskSpline *BKE_mask_spline_add(struct MaskLayer *masklay); +int BKE_mask_spline_resolution(struct MaskSpline *spline, int width, int height); +int BKE_mask_spline_feather_resolution(struct MaskSpline *spline, int width, int height); + int BKE_mask_spline_differentiate_calc_total(const struct MaskSpline *spline, const int resol); float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point))[2]; float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point))[2]; -float (*BKE_mask_spline_differentiate_with_resolution_ex(struct MaskSpline *spline, const int resol, int *tot_diff_point))[2]; +float (*BKE_mask_spline_differentiate_with_resolution_ex(struct MaskSpline *spline, int *tot_diff_point, + const int resol))[2]; float (*BKE_mask_spline_differentiate_with_resolution(struct MaskSpline *spline, int width, int height, int *tot_diff_point))[2]; -float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(struct MaskSpline *spline, const int resol, int *tot_feather_point))[2]; +float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(struct MaskSpline *spline, int *tot_feather_point, + const int resol, const int do_collapse))[2]; float (*BKE_mask_spline_feather_differentiated_points_with_resolution(struct MaskSpline *spline, int width, int height, int *tot_feather_point))[2]; float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2]; @@ -206,20 +211,20 @@ void BKE_mask_init_layers(Mask *mask, struct layer_init_data *mlayer_data, int w #define MASKPOINT_DESEL_HANDLE(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 /* disable to test alternate rasterizer */ -#define USE_RASKTER +/* #define USE_RASKTER */ /* mask_rasterize.c */ #ifndef USE_RASKTER struct MaskRasterHandle; typedef struct MaskRasterHandle MaskRasterHandle; -MaskRasterHandle *BLI_maskrasterize_handle_new(void); -void BLI_maskrasterize_handle_free(MaskRasterHandle *mr_handle); -void BLI_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mask, +MaskRasterHandle *BKE_maskrasterize_handle_new(void); +void BKE_maskrasterize_handle_free(MaskRasterHandle *mr_handle); +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); -float BLI_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float xy[2]); +float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float xy[2]); #endif /* USE_RASKTER */ #endif /* __BKE_MASK_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index abd0c4d96db..6fac915d520 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -141,10 +141,11 @@ void BKE_mesh_from_metaball(struct ListBase *lb, struct Mesh *me); int BKE_mesh_nurbs_to_mdata(struct Object *ob, struct MVert **allvert, int *totvert, struct MEdge **alledge, int *totedge, struct MLoop **allloop, struct MPoly **allpoly, int *totloop, int *totpoly); -int BKE_mesh_nurbs_to_mdata_customdb(struct Object *ob, struct ListBase *dispbase, struct MVert **allvert, int *_totvert, +int BKE_mesh_nurbs_displist_to_mdata(struct Object *ob, struct ListBase *dispbase, struct MVert **allvert, int *_totvert, struct MEdge **alledge, int *_totedge, struct MLoop **allloop, struct MPoly **allpoly, int *_totloop, int *_totpoly); void BKE_mesh_from_nurbs(struct Object *ob); +void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase); void BKE_mesh_from_curve(struct Scene *scene, struct Object *ob); void free_dverts(struct MDeformVert *dvert, int totvert); void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index b8ba3095905..3aa7148d821 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -177,6 +177,8 @@ typedef enum eObjectSet { } eObjectSet; struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter); +struct LinkNode *BKE_object_groups(struct Object *ob); +void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object); #ifdef __cplusplus } 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. |