static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, const bool for_render, const bool use_render_resolution) { Nurb *nu; DispList *dl; BezTriple *bezt, *prevbezt; BPoint *bp; float *data; int a, len, resolu; const bool editmode = (!for_render && (cu->editnurb || cu->editfont)); nu = nubase->first; while (nu) { if (nu->hide == 0 || editmode == false) { if (use_render_resolution && cu->resolu_ren != 0) resolu = cu->resolu_ren; else resolu = nu->resolu; if (!BKE_nurb_check_valid_u(nu)) { /* pass */ } else if (nu->type == CU_BEZIER) { /* count */ len = 0; a = nu->pntsu - 1; if (nu->flagu & CU_NURB_CYCLIC) a++; prevbezt = nu->bezt; bezt = prevbezt + 1; while (a--) { if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) bezt = nu->bezt; if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) len++; else len += resolu; if (a == 0 && (nu->flagu & CU_NURB_CYCLIC) == 0) len++; prevbezt = bezt; bezt++; } dl = MEM_callocN(sizeof(DispList), "makeDispListbez"); /* len+1 because of 'forward_diff_bezier' function */ dl->verts = MEM_mallocN((len + 1) * sizeof(float[3]), "dlverts"); BLI_addtail(dispbase, dl); dl->parts = 1; dl->nr = len; dl->col = nu->mat_nr; dl->charidx = nu->charidx; data = dl->verts; /* check that (len != 2) so we don't immediately loop back on ourselves */ if (nu->flagu & CU_NURB_CYCLIC && (dl->nr != 2)) { dl->type = DL_POLY; a = nu->pntsu; } else { dl->type = DL_SEGM; a = nu->pntsu - 1; } prevbezt = nu->bezt; bezt = prevbezt + 1; while (a--) { if (a == 0 && dl->type == DL_POLY) bezt = nu->bezt; if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) { copy_v3_v3(data, prevbezt->vec[1]); data += 3; } else { int j; for (j = 0; j < 3; j++) { BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], prevbezt->vec[2][j], bezt->vec[0][j], bezt->vec[1][j], data + j, resolu, 3 * sizeof(float)); } data += 3 * resolu; } if (a == 0 && dl->type == DL_SEGM) { copy_v3_v3(data, bezt->vec[1]); } prevbezt = bezt; bezt++; } } else if (nu->type == CU_NURBS) { len = (resolu * SEGMENTSU(nu)); dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); BLI_addtail(dispbase, dl); dl->parts = 1; dl->nr = len; dl->col = nu->mat_nr; dl->charidx = nu->charidx; data = dl->verts; if (nu->flagu & CU_NURB_CYCLIC) dl->type = DL_POLY; else dl->type = DL_SEGM; BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, 3 * sizeof(float)); } else if (nu->type == CU_POLY) { len = nu->pntsu; dl = MEM_callocN(sizeof(DispList), "makeDispListpoly"); dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); BLI_addtail(dispbase, dl); dl->parts = 1; dl->nr = len; dl->col = nu->mat_nr; dl->charidx = nu->charidx; data = dl->verts; if ((nu->flagu & CU_NURB_CYCLIC) && (dl->nr != 2)) { dl->type = DL_POLY; } else { dl->type = DL_SEGM; } a = len; bp = nu->bp; while (a--) { copy_v3_v3(data, bp->vec); bp++; data += 3; } } } nu = nu->next; } }
static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu, int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend) { float tmpf, total_length = 0.0f; int end = 0, i; if ((BKE_nurb_check_valid_u(nu) == false) || /* not essential, but skips unnecessary calculation */ (min_ff(cu->bevfac1, cu->bevfac2) == 0.0f && max_ff(cu->bevfac1, cu->bevfac2) == 1.0f)) { calc_bevfac_mapping_default(bl, r_start, r_firstblend, r_steps, r_lastblend); return; } if (ELEM(cu->bevfac1_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE) || ELEM(cu->bevfac2_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE)) { for (i = 0; i < SEGMENTSU(nu); i++) { total_length += bl->seglen[i]; } } switch (cu->bevfac1_mapping) { case CU_BEVFAC_MAP_RESOLU: { const float start_fl = cu->bevfac1 * (bl->nr - 1); *r_start = (int)start_fl; *r_firstblend = 1.0f - (start_fl - (*r_start)); break; } case CU_BEVFAC_MAP_SEGMENT: { calc_bevfac_segment_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend); *r_firstblend = 1.0f - *r_firstblend; break; } case CU_BEVFAC_MAP_SPLINE: { calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend); *r_firstblend = 1.0f - *r_firstblend; break; } } switch (cu->bevfac2_mapping) { case CU_BEVFAC_MAP_RESOLU: { const float end_fl = cu->bevfac2 * (bl->nr - 1); end = (int)end_fl; *r_steps = 2 + end - *r_start; *r_lastblend = end_fl - end; break; } case CU_BEVFAC_MAP_SEGMENT: { calc_bevfac_segment_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend); *r_steps = end - *r_start + 2; break; } case CU_BEVFAC_MAP_SPLINE: { calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend); *r_steps = end - *r_start + 2; break; } } if (end < *r_start || (end == *r_start && *r_lastblend < 1.0f - *r_firstblend )) { SWAP(int, *r_start, end); tmpf = *r_lastblend; *r_lastblend = 1.0f - *r_firstblend; *r_firstblend = 1.0f - tmpf; *r_steps = end - *r_start + 2; }
void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, DerivedMesh **r_dm_final, const bool for_render, const bool for_orco, const bool use_render_resolution) { ListBase nubase = {NULL, NULL}; Nurb *nu; Curve *cu = ob->data; DispList *dl; float *data; int len; if (!for_render && cu->editnurb) { BKE_nurbList_duplicate(&nubase, BKE_curve_editNurbs_get(cu)); } else { BKE_nurbList_duplicate(&nubase, &cu->nurb); } if (!for_orco) curve_calc_modifiers_pre(scene, ob, &nubase, for_render, use_render_resolution); for (nu = nubase.first; nu; nu = nu->next) { if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) { int resolu = nu->resolu, resolv = nu->resolv; if (use_render_resolution) { if (cu->resolu_ren) resolu = cu->resolu_ren; if (cu->resolv_ren) resolv = cu->resolv_ren; } if (nu->pntsv == 1) { len = SEGMENTSU(nu) * resolu; dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); BLI_addtail(dispbase, dl); dl->parts = 1; dl->nr = len; dl->col = nu->mat_nr; dl->charidx = nu->charidx; /* dl->rt will be used as flag for render face and */ /* CU_2D conflicts with R_NOPUNOFLIP */ dl->rt = nu->flag & ~CU_2D; data = dl->verts; if (nu->flagu & CU_NURB_CYCLIC) dl->type = DL_POLY; else dl->type = DL_SEGM; BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, 3 * sizeof(float)); } else { len = (nu->pntsu * resolu) * (nu->pntsv * resolv); dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); BLI_addtail(dispbase, dl); dl->col = nu->mat_nr; dl->charidx = nu->charidx; /* dl->rt will be used as flag for render face and */ /* CU_2D conflicts with R_NOPUNOFLIP */ dl->rt = nu->flag & ~CU_2D; data = dl->verts; dl->type = DL_SURF; dl->parts = (nu->pntsu * resolu); /* in reverse, because makeNurbfaces works that way */ dl->nr = (nu->pntsv * resolv); if (nu->flagv & CU_NURB_CYCLIC) dl->flag |= DL_CYCL_U; /* reverse too! */ if (nu->flagu & CU_NURB_CYCLIC) dl->flag |= DL_CYCL_V; BKE_nurb_makeFaces(nu, data, 0, resolu, resolv); /* gl array drawing: using indices */ displist_surf_indices(dl); } } } if (!for_orco) { BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase); curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution); } BKE_nurbList_free(&nubase); }
/* calculate a curve-deform path for a curve * - only called from displist.c -> do_makeDispListCurveTypes */ void calc_curvepath(Object *ob) { BevList *bl; BevPoint *bevp, *bevpn, *bevpfirst, *bevplast; PathPoint *pp; Curve *cu; Nurb *nu; Path *path; float *fp, *dist, *maxdist, xyz[3]; float fac, d=0, fac1, fac2; int a, tot, cycl=0; ListBase *nurbs; /* in a path vertices are with equal differences: path->len = number of verts */ /* NOW WITH BEVELCURVE!!! */ if (ob==NULL || ob->type != OB_CURVE) return; cu= ob->data; nurbs= BKE_curve_nurbs(cu); nu= nurbs->first; if (cu->path) free_path(cu->path); cu->path= NULL; bl= cu->bev.first; if (bl==NULL || !bl->nr) return; cu->path=path= MEM_callocN(sizeof(Path), "calc_curvepath"); /* if POLY: last vertice != first vertice */ cycl= (bl->poly!= -1); if (cycl) tot= bl->nr; else tot= bl->nr-1; path->len= tot+1; /* exception: vector handle paths and polygon paths should be subdivided at least a factor resolu */ if (path->len<nu->resolu*SEGMENTSU(nu)) path->len= nu->resolu*SEGMENTSU(nu); dist= (float *)MEM_mallocN((tot+1)*4, "calcpathdist"); /* all lengths in *dist */ bevp= bevpfirst= (BevPoint *)(bl+1); fp= dist; *fp= 0; for (a=0; a<tot; a++) { fp++; if (cycl && a==tot-1) sub_v3_v3v3(xyz, bevpfirst->vec, bevp->vec); else sub_v3_v3v3(xyz, (bevp+1)->vec, bevp->vec); *fp= *(fp-1)+len_v3(xyz); bevp++; } path->totdist= *fp; /* the path verts in path->data */ /* now also with TILT value */ pp= path->data = (PathPoint *)MEM_callocN(sizeof(PathPoint)*path->len, "pathdata"); bevp= bevpfirst; bevpn= bevp+1; bevplast= bevpfirst + (bl->nr-1); fp= dist+1; maxdist= dist+tot; fac= 1.0f/((float)path->len-1.0f); fac = fac * path->totdist; for (a=0; a<path->len; a++) { d= ((float)a)*fac; /* we're looking for location (distance) 'd' in the array */ while ((d>= *fp) && fp<maxdist) { fp++; if (bevp<bevplast) bevp++; bevpn= bevp+1; if (bevpn>bevplast) { if (cycl) bevpn= bevpfirst; else bevpn= bevplast; } } fac1= *(fp)- *(fp-1); fac2= *(fp)-d; fac1= fac2/fac1; fac2= 1.0f-fac1; interp_v3_v3v3(pp->vec, bevp->vec, bevpn->vec, fac2); pp->vec[3]= fac1*bevp->alfa + fac2*bevpn->alfa; pp->radius= fac1*bevp->radius + fac2*bevpn->radius; pp->weight= fac1*bevp->weight + fac2*bevpn->weight; interp_qt_qtqt(pp->quat, bevp->quat, bevpn->quat, fac2); normalize_qt(pp->quat); pp++; } MEM_freeN(dist); }
static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, int forRender) { Nurb *nu; DispList *dl; BezTriple *bezt, *prevbezt; BPoint *bp; float *data; int a, len, resolu; nu= nubase->first; while(nu) { if(nu->hide==0) { if(forRender && cu->resolu_ren!=0) resolu= cu->resolu_ren; else resolu= nu->resolu; if(!check_valid_nurb_u(nu)); else if(nu->type == CU_BEZIER) { /* count */ len= 0; a= nu->pntsu-1; if(nu->flagu & CU_NURB_CYCLIC) a++; prevbezt= nu->bezt; bezt= prevbezt+1; while(a--) { if(a==0 && (nu->flagu & CU_NURB_CYCLIC)) bezt= nu->bezt; if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++; else len+= resolu; if(a==0 && (nu->flagu & CU_NURB_CYCLIC)==0) len++; prevbezt= bezt; bezt++; } dl= MEM_callocN(sizeof(DispList), "makeDispListbez"); /* len+1 because of 'forward_diff_bezier' function */ dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts"); BLI_addtail(dispbase, dl); dl->parts= 1; dl->nr= len; dl->col= nu->mat_nr; dl->charidx= nu->charidx; data= dl->verts; if(nu->flagu & CU_NURB_CYCLIC) { dl->type= DL_POLY; a= nu->pntsu; } else { dl->type= DL_SEGM; a= nu->pntsu-1; } prevbezt= nu->bezt; bezt= prevbezt+1; while(a--) { if(a==0 && dl->type== DL_POLY) bezt= nu->bezt; if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) { VECCOPY(data, prevbezt->vec[1]); data+= 3; } else { int j; for(j=0; j<3; j++) { forward_diff_bezier( prevbezt->vec[1][j], prevbezt->vec[2][j], bezt->vec[0][j], bezt->vec[1][j], data+j, resolu, 3*sizeof(float)); } data+= 3*resolu; } if(a==0 && dl->type==DL_SEGM) { VECCOPY(data, bezt->vec[1]); } prevbezt= bezt; bezt++; } } else if(nu->type == CU_NURBS) { len= (resolu*SEGMENTSU(nu)); dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); BLI_addtail(dispbase, dl); dl->parts= 1; dl->nr= len; dl->col= nu->mat_nr; dl->charidx = nu->charidx; data= dl->verts; if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float)); } else if(nu->type == CU_POLY) { len= nu->pntsu; dl= MEM_callocN(sizeof(DispList), "makeDispListpoly"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); BLI_addtail(dispbase, dl); dl->parts= 1; dl->nr= len; dl->col= nu->mat_nr; dl->charidx = nu->charidx; data= dl->verts; if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; a= len; bp= nu->bp; while(a--) { VECCOPY(data, bp->vec); bp++; data+= 3; } } } nu= nu->next; } }
void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, DerivedMesh **derivedFinal, int forRender, int forOrco) { ListBase *nubase; Nurb *nu; Curve *cu = ob->data; DispList *dl; float *data; int len; int numVerts; float (*originalVerts)[3]; float (*deformedVerts)[3]; if(!forRender && cu->editnurb) nubase= ED_curve_editnurbs(cu); else nubase= &cu->nurb; if(!forOrco) curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts); for (nu=nubase->first; nu; nu=nu->next) { if(forRender || nu->hide==0) { int resolu= nu->resolu, resolv= nu->resolv; if(forRender){ if(cu->resolu_ren) resolu= cu->resolu_ren; if(cu->resolv_ren) resolv= cu->resolv_ren; } if(nu->pntsv==1) { len= SEGMENTSU(nu)*resolu; dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); BLI_addtail(dispbase, dl); dl->parts= 1; dl->nr= len; dl->col= nu->mat_nr; dl->charidx= nu->charidx; /* dl->rt will be used as flag for render face and */ /* CU_2D conflicts with R_NOPUNOFLIP */ dl->rt= nu->flag & ~CU_2D; data= dl->verts; if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float)); } else { len= (nu->pntsu*resolu) * (nu->pntsv*resolv); dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); BLI_addtail(dispbase, dl); dl->col= nu->mat_nr; dl->charidx= nu->charidx; /* dl->rt will be used as flag for render face and */ /* CU_2D conflicts with R_NOPUNOFLIP */ dl->rt= nu->flag & ~CU_2D; data= dl->verts; dl->type= DL_SURF; dl->parts= (nu->pntsu*resolu); /* in reverse, because makeNurbfaces works that way */ dl->nr= (nu->pntsv*resolv); if(nu->flagv & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_U; /* reverse too! */ if(nu->flagu & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_V; makeNurbfaces(nu, data, 0, resolu, resolv); /* gl array drawing: using indices */ displist_surf_indices(dl); } } } /* make copy of 'undeformed" displist for texture space calculation actually, it's not totally undeformed -- pre-tesselation modifiers are already applied, thats how it worked for years, so keep for compatibility (sergey) */ copy_displist(&cu->disp, dispbase); if (!forRender) { tex_space_curve(cu); } if(!forOrco) curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, originalVerts, deformedVerts); }