void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob) { /* make new mesh data from the original copy */ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH); ListBase nurblist = {NULL, NULL}; BKE_mesh_to_curve_nurblist(me_eval, &nurblist, 0); BKE_mesh_to_curve_nurblist(me_eval, &nurblist, 1); if (nurblist.first) { Curve *cu = BKE_curve_add(bmain, ob->id.name + 2, OB_CURVE); cu->flag |= CU_3D; cu->nurb = nurblist; id_us_min(&((Mesh *)ob->data)->id); ob->data = cu; ob->type = OB_CURVE; BKE_object_free_derived_caches(ob); } }
/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, const int mode, const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd) { struct Main *bmain = CTX_data_main(C); View3D *v3d = CTX_wm_view3d(C); /* may be NULL */ Scene *scene = CTX_data_scene(C); bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); bGPDstroke *gps, *prev_gps = NULL; Object *ob; Curve *cu; Nurb *nu = NULL; Base *base_orig = BASACT, *base_new = NULL; float minmax_weights[2] = {1.0f, 0.0f}; /* camera framing */ rctf subrect, *subrect_ptr = NULL; /* error checking */ if (ELEM(NULL, gpd, gpl, gpf)) return; /* only convert if there are any strokes on this layer's frame to convert */ if (BLI_listbase_is_empty(&gpf->strokes)) return; /* initialize camera framing */ if (gp_camera_view_subrect(C, &subrect)) { subrect_ptr = &subrect; } /* init the curve object (remove rotation and get curve data from it) * - must clear transforms set on object, as those skew our results */ ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info); cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE); base_new = BKE_scene_base_add(scene, ob); cu->flag |= CU_3D; gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime; /* add points to curve */ for (gps = gpf->strokes.first; gps; gps = gps->next) { const bool add_start_point = (link_strokes && !(prev_gps)); const bool add_end_point = (link_strokes && !(gps->next)); /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, and stitch them to previous one. */ bool stitch = false; if (prev_gps) { bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1]; bGPDspoint *pt2 = &gps->points[0]; if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) { stitch = true; } } /* Decide whether we connect this stroke to previous one */ if (!(stitch || link_strokes)) { nu = NULL; } switch (mode) { case GP_STROKECONVERT_PATH: gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, add_start_point, add_end_point, gtd); break; case GP_STROKECONVERT_CURVE: case GP_STROKECONVERT_POLY: /* convert after */ gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, add_start_point, add_end_point, gtd); break; default: BLI_assert(!"invalid mode"); break; } prev_gps = gps; } /* If link_strokes, be sure first and last points have a zero weight/size! */ if (link_strokes) { gp_stroke_finalize_curve_endpoints(cu); } /* Update curve's weights, if needed */ if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) { gp_stroke_norm_curve_weights(cu, minmax_weights); } /* Create the path animation, if needed */ gp_stroke_path_animation(C, reports, cu, gtd); if (mode == GP_STROKECONVERT_POLY) { for (nu = cu->nurb.first; nu; nu = nu->next) { BKE_nurb_type_convert(nu, CU_POLY, false); } } /* set the layer and select */ base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene); base_new->flag = ob->flag = base_new->flag | SELECT; }