[Bf-blender-cvs] [39a4200ddb2] greasepencil-object: Merge branch 'master' into greasepencil-object
Antonio Vazquez
noreply at git.blender.org
Sat Dec 12 18:56:07 CET 2020
Commit: 39a4200ddb2caf3c1713aecebadcf425424ec066
Author: Antonio Vazquez
Date: Sat Dec 12 18:55:57 2020 +0100
Branches: greasepencil-object
https://developer.blender.org/rB39a4200ddb2caf3c1713aecebadcf425424ec066
Merge branch 'master' into greasepencil-object
Conflicts:
source/blender/blenkernel/BKE_gpencil_geom.h
source/blender/blenkernel/intern/gpencil_geom.c
===================================================================
===================================================================
diff --cc source/blender/blenkernel/BKE_gpencil_geom.h
index f7b91e29536,111f9030463..83eb4fd20af
--- a/source/blender/blenkernel/BKE_gpencil_geom.h
+++ b/source/blender/blenkernel/BKE_gpencil_geom.h
@@@ -167,24 -164,11 +167,29 @@@ bool BKE_gpencil_convert_mesh(struct Ma
const bool use_seams,
const bool use_faces);
+ void BKE_gpencil_stroke_uniform_subdivide(struct bGPdata *gpd,
+ struct bGPDstroke *gps,
+ const uint32_t target_number,
+ const bool select);
+
+void BKE_gpencil_stroke_to_view_space(struct RegionView3D *rv3d,
+ struct bGPDstroke *gps,
+ float diff_mat[4][4]);
+void BKE_gpencil_stroke_from_view_space(struct RegionView3D *rv3d,
+ struct bGPDstroke *gps,
+ float diff_mat[4][4]);
+struct bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
+ struct bGPdata *gpd,
+ const struct bGPDlayer *gpl,
+ struct bGPDstroke *gps,
+ int subdivisions,
+ float diff_mat[4][4]);
+struct bGPDstroke *BKE_gpencil_stroke_perimeter_from_view_2d(struct ARegion *region,
+ const struct bGPdata *gpd,
+ const struct bGPDlayer *gpl,
+ struct bGPDstroke *gps,
+ int subdivisions,
+ float diff_mat[4][4]);
#ifdef __cplusplus
}
#endif
diff --cc source/blender/blenkernel/intern/gpencil_geom.c
index ccec461019c,85b02d2ba3b..8d25928e2d4
--- a/source/blender/blenkernel/intern/gpencil_geom.c
+++ b/source/blender/blenkernel/intern/gpencil_geom.c
@@@ -3227,602 -3226,196 +3228,796 @@@ void BKE_gpencil_stroke_join(bGPDstrok
}
}
+ /* Stroke Uniform Subdivide ------------------------------------- */
+
+ typedef struct tSamplePoint {
+ struct tSamplePoint *next, *prev;
+ float x, y, z;
+ float pressure, strength, time;
+ float vertex_color[4];
+ struct MDeformWeight *dw;
+ int totweight;
+ } tSamplePoint;
+
+ typedef struct tSampleEdge {
+ float length_sq;
+ tSamplePoint *from;
+ tSamplePoint *to;
+ } tSampleEdge;
+
+ /* Helper: creates a tSamplePoint from a bGPDspoint and (optionally) a MDeformVert. */
+ static tSamplePoint *new_sample_point_from_gp_point(const bGPDspoint *pt, const MDeformVert *dvert)
+ {
+ tSamplePoint *new_pt = MEM_callocN(sizeof(tSamplePoint), __func__);
+ copy_v3_v3(&new_pt->x, &pt->x);
+ new_pt->pressure = pt->pressure;
+ new_pt->strength = pt->strength;
+ new_pt->time = pt->time;
+ copy_v4_v4((float *)&new_pt->vertex_color, (float *)&pt->vert_color);
+ if (dvert != NULL) {
+ new_pt->totweight = dvert->totweight;
+ new_pt->dw = MEM_callocN(sizeof(MDeformWeight) * new_pt->totweight, __func__);
+ for (uint i = 0; i < new_pt->totweight; ++i) {
+ MDeformWeight *dw = &new_pt->dw[i];
+ MDeformWeight *dw_from = &dvert->dw[i];
+ dw->def_nr = dw_from->def_nr;
+ dw->weight = dw_from->weight;
+ }
+ }
+ return new_pt;
+ }
+
+ /* Helper: creates a tSampleEdge from two tSamplePoints. Also calculates the length (squared) of
+ * the edge. */
+ static tSampleEdge *new_sample_edge_from_sample_points(tSamplePoint *from, tSamplePoint *to)
+ {
+ tSampleEdge *new_edge = MEM_callocN(sizeof(tSampleEdge), __func__);
+ new_edge->from = from;
+ new_edge->to = to;
+ new_edge->length_sq = len_squared_v3v3(&from->x, &to->x);
+ return new_edge;
+ }
+
+ /**
+ * Subdivide the grease pencil stroke so the number of points is target_number.
+ * Does not change the shape of the stroke. The new points will be distributed as
+ * uniformly as possible by repeatedly subdividing the current longest edge.
+ *
+ * \param gps: The stroke to be upsampled.
+ * \param target_number: The number of points the upsampled stroke should have.
+ * \param select: Select/Deselect the stroke.
+ */
+ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
+ bGPDstroke *gps,
+ const uint32_t target_number,
+ const bool select)
+ {
+ /* Stroke needs at least two points and strictly less points than the target number. */
+ if (gps == NULL || gps->totpoints < 2 || gps->totpoints >= target_number) {
+ return;
+ }
+
+ const int totpoints = gps->totpoints;
+ const bool has_dverts = (gps->dvert != NULL);
+ const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC);
+
+ ListBase points = {NULL, NULL};
+ Heap *edges = BLI_heap_new();
+
+ /* Add all points into list. */
+ for (uint32_t i = 0; i < totpoints; ++i) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = has_dverts ? &gps->dvert[i] : NULL;
+ tSamplePoint *sp = new_sample_point_from_gp_point(pt, dvert);
+ BLI_addtail(&points, sp);
+ }
+
+ /* Iterate over edges and insert them into the heap. */
+ for (tSamplePoint *pt = ((tSamplePoint *)points.first)->next; pt != NULL; pt = pt->next) {
+ tSampleEdge *se = new_sample_edge_from_sample_points(pt->prev, pt);
+ /* BLI_heap is a min-heap, but we need the largest key to be at the top, so we take the
+ * negative of the squared length. */
+ BLI_heap_insert(edges, -(se->length_sq), se);
+ }
+
+ if (is_cyclic) {
+ tSamplePoint *sp_first = points.first;
+ tSamplePoint *sp_last = points.last;
+ tSampleEdge *se = new_sample_edge_from_sample_points(sp_last, sp_first);
+ BLI_heap_insert(edges, -(se->length_sq), se);
+ }
+
+ int num_points_needed = target_number - totpoints;
+ BLI_assert(num_points_needed > 0);
+
+ while (num_points_needed > 0) {
+ tSampleEdge *se = BLI_heap_pop_min(edges);
+ tSamplePoint *sp = se->from;
+ tSamplePoint *sp_next = se->to;
+
+ /* Subdivide the edge. */
+ tSamplePoint *new_sp = MEM_callocN(sizeof(tSamplePoint), __func__);
+ interp_v3_v3v3(&new_sp->x, &sp->x, &sp_next->x, 0.5f);
+ new_sp->pressure = interpf(sp->pressure, sp_next->pressure, 0.5f);
+ new_sp->strength = interpf(sp->strength, sp_next->strength, 0.5f);
+ new_sp->time = interpf(sp->time, sp_next->time, 0.5f);
+ interp_v4_v4v4((float *)&new_sp->vertex_color,
+ (float *)&sp->vertex_color,
+ (float *)&sp_next->vertex_color,
+ 0.5f);
+ if (sp->dw && sp_next->dw) {
+ new_sp->totweight = MIN2(sp->totweight, sp_next->totweight);
+ new_sp->dw = MEM_callocN(sizeof(MDeformWeight) * new_sp->totweight, __func__);
+ for (uint32_t i = 0; i < new_sp->totweight; ++i) {
+ MDeformWeight *dw = &new_sp->dw[i];
+ MDeformWeight *dw_from = &sp->dw[i];
+ MDeformWeight *dw_to = &sp_next->dw[i];
+ dw->def_nr = dw_from->def_nr;
+ dw->weight = interpf(dw_from->weight, dw_to->weight, 0.5f);
+ }
+ }
+ BLI_insertlinkafter(&points, sp, new_sp);
+
+ tSampleEdge *se_prev = new_sample_edge_from_sample_points(sp, new_sp);
+ tSampleEdge *se_next = new_sample_edge_from_sample_points(new_sp, sp_next);
+ BLI_heap_insert(edges, -(se_prev->length_sq), se_prev);
+ BLI_heap_insert(edges, -(se_next->length_sq), se_next);
+
+ MEM_freeN(se);
+ num_points_needed--;
+ }
+
+ /* Edges are no longer needed. Heap is freed. */
+ BLI_heap_free(edges, (HeapFreeFP)MEM_freeN);
+
+ gps->totpoints = target_number;
+ gps->points = MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints);
+ if (has_dverts) {
+ gps->dvert = MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints);
+ }
+
+ /* Convert list back to stroke point array. */
+ tSamplePoint *sp = points.first;
+ for (uint32_t i = 0; i < gps->totpoints && sp; ++i, sp = sp->next) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+
+ copy_v3_v3(&pt->x, &sp->x);
+ pt->pressure = sp->pressure;
+ pt->strength = sp->strength;
+ pt->time = sp->time;
+ copy_v4_v4((float *)&pt->vert_color, (float *)&sp->vertex_color);
+
+ if (sp->dw) {
+ dvert->totweight = sp->totweight;
+ dvert->dw = MEM_callocN(sizeof(MDeformWeight) * dvert->totweight, __func__);
+ for (uint32_t j = 0; j < dvert->totweight; ++j) {
+ MDeformWeight *dw = &dvert->dw[j];
+ MDeformWeight *dw_from = &sp->dw[j];
+ dw->def_nr = dw_from->def_nr;
+ dw->weight = dw_from->weight;
+ }
+ }
+ if (select) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ }
+
+ if (select) {
+ gps->flag |= GP_STROKE_SELECT;
+ }
+
+ /* Free the sample points. Important to use the mutable loop here because we are erasing the list
+ * elements. */
+ LISTBASE_FOREACH_MUTABLE (tSamplePoint *, temp, &points) {
+ if (temp->dw != NULL) {
+ MEM_freeN(temp->dw);
+ }
+ MEM_SAFE_FREE(temp);
+ }
+
+ /* Update the geometry of the stroke. */
+ BKE_gpencil_stroke_geometry_update(gpd, gps);
+ }
+
++}
++
+/**
+ * Stroke to view space
+ * Transforms a stroke to view space. This allows for manipulations in 2D but also easy conversion
+ * back to 3D.
+ * Note: also takes care of parent space transform
+ */
+void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d, bGPDstroke *gps, float diff_mat[4][4])
+{
+ float tmp[3];
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ /* point to parent space */
+ mul_v3_m4v3(tmp, diff_mat, &pt->x);
+ /* point to view space */
+ mul_m4_v3(rv3
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list