Exemplo n.º 1
0
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;
}