Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/curve.cpp
- This file was moved from source/blender/blenkernel/intern/curve.c.
| Context not available. | |||||
| /** \file | /** \file | ||||
| * \ingroup bke | * \ingroup bke | ||||
| */ | */ | ||||
| #include "MEM_guardedalloc.h" | |||||
| extern "C" { | |||||
| #include <math.h> // floor | #include <math.h> // floor | ||||
| #include <string.h> | #include <string.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include "MEM_guardedalloc.h" | |||||
| #include "BLI_blenlib.h" | #include "BLI_blenlib.h" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BLI_ghash.h" | #include "BLI_ghash.h" | ||||
| #include "BLI_linklist.h" | #include "BLI_linklist.h" | ||||
| #include "BLI_polyfill_2d.h" | |||||
| #include "BLI_threads.h" | |||||
| #include "BLT_translation.h" | #include "BLT_translation.h" | ||||
| #include "DNA_anim_types.h" | #include "DNA_anim_types.h" | ||||
| Context not available. | |||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "DNA_vfont_types.h" | #include "DNA_vfont_types.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_mesh_types.h" | |||||
| #include "DNA_meshdata_types.h" | |||||
| #include "BKE_animsys.h" | #include "BKE_animsys.h" | ||||
| #include "BKE_curve.h" | #include "BKE_curve.h" | ||||
| #include "BKE_mesh.h" | |||||
| #include "BKE_displist.h" | #include "BKE_displist.h" | ||||
| #include "BKE_font.h" | #include "BKE_font.h" | ||||
| #include "BKE_idtype.h" | #include "BKE_idtype.h" | ||||
| Context not available. | |||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include "BKE_object.h" | #include "BKE_object.h" | ||||
| #include "BKE_material.h" | #include "BKE_material.h" | ||||
| #include "BKE_customdata.h" | |||||
| #include "DEG_depsgraph.h" | #include "DEG_depsgraph.h" | ||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "BKE_global.h" | |||||
| #include "CLG_log.h" | #include "CLG_log.h" | ||||
| } | |||||
| #include "surf_gridmesh.h" | |||||
| #include <map> | |||||
| #include <algorithm> | |||||
| /* globals */ | /* globals */ | ||||
| /* local */ | /* local */ | ||||
| Context not available. | |||||
| BLI_listbase_clear(&curve_dst->nurb); | BLI_listbase_clear(&curve_dst->nurb); | ||||
| BKE_nurbList_duplicate(&(curve_dst->nurb), &(curve_src->nurb)); | BKE_nurbList_duplicate(&(curve_dst->nurb), &(curve_src->nurb)); | ||||
| curve_dst->mat = MEM_dupallocN(curve_src->mat); | curve_dst->mat = (Material **)MEM_dupallocN(curve_src->mat); | ||||
| curve_dst->str = MEM_dupallocN(curve_src->str); | curve_dst->str = (char *)MEM_dupallocN(curve_src->str); | ||||
| curve_dst->strinfo = MEM_dupallocN(curve_src->strinfo); | curve_dst->strinfo = (CharInfo *)MEM_dupallocN(curve_src->strinfo); | ||||
| curve_dst->tb = MEM_dupallocN(curve_src->tb); | curve_dst->tb = (TextBox *)MEM_dupallocN(curve_src->tb); | ||||
| curve_dst->batch_cache = NULL; | curve_dst->batch_cache = NULL; | ||||
| if (curve_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) { | if (curve_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) { | ||||
| Context not available. | |||||
| { | { | ||||
| Curve *curve = (Curve *)id; | Curve *curve = (Curve *)id; | ||||
| BKE_animdata_free((ID *)curve, false); | |||||
| BKE_curve_batch_cache_free(curve); | BKE_curve_batch_cache_free(curve); | ||||
| BKE_nurbList_free(&curve->nurb); | BKE_nurbList_free(&curve->nurb); | ||||
| Context not available. | |||||
| static void curve_editNurb_keyIndex_cv_free_cb(void *val) | static void curve_editNurb_keyIndex_cv_free_cb(void *val) | ||||
| { | { | ||||
| CVKeyIndex *index = val; | CVKeyIndex *index = (CVKeyIndex *) val; | ||||
| MEM_freeN(index->orig_cv); | MEM_freeN(index->orig_cv); | ||||
| MEM_freeN(val); | MEM_freeN(val); | ||||
| } | } | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| void BKE_nurb_knot_calc_u(Nurb *nu) | |||||
| { | |||||
| int pnts=nu->pntsu, order=nu->orderu; | |||||
| BKE_nurbs_editKnot_destroy(nu); | |||||
| float *knots = (float*)MEM_mallocN(sizeof(float)*(pnts+2*order), "NURB_knots_u"); | |||||
| BKE_bspline_knot_calc(nu->flagu, pnts, order, knots); | |||||
| if (nu->knotsu) MEM_freeN(nu->knotsu); | |||||
| nu->knotsu = knots; | |||||
| } | |||||
| void BKE_nurb_knot_calc_v(Nurb *nu) | |||||
| { | |||||
| int pnts=nu->pntsv, order=nu->orderv; | |||||
| BKE_nurbs_editKnot_destroy(nu); | |||||
| float *knots = (float*)MEM_mallocN(sizeof(float)*(pnts+2*order), "NURB_knots_v"); | |||||
| BKE_bspline_knot_calc(nu->flagv, pnts, order, knots); | |||||
| if (nu->knotsv) MEM_freeN(nu->knotsv); | |||||
| nu->knotsv = knots; | |||||
| } | |||||
| void BKE_curve_init(Curve *cu, const short curve_type) | void BKE_curve_init(Curve *cu, const short curve_type) | ||||
| { | { | ||||
| curve_init_data(&cu->id); | curve_init_data(&cu->id); | ||||
| cu->type = curve_type; | cu->type = curve_type; | ||||
| if (cu->type == OB_FONT) { | if (cu->type == OB_FONT) { | ||||
| cu->flag |= CU_FRONT | CU_BACK; | cu->flag |= CU_FRONT | CU_BACK; | ||||
| cu->vfont = cu->vfontb = cu->vfonti = cu->vfontbi = BKE_vfont_builtin_get(); | cu->vfont = cu->vfontb = cu->vfonti = cu->vfontbi = BKE_vfont_builtin_get(); | ||||
| cu->vfont->id.us += 4; | cu->vfont->id.us += 4; | ||||
| cu->str = MEM_malloc_arrayN(12, sizeof(unsigned char), "str"); | cu->str = (char *)MEM_malloc_arrayN(12, sizeof(unsigned char), "str"); | ||||
| BLI_strncpy(cu->str, "Text", 12); | BLI_strncpy(cu->str, "Text", 12); | ||||
| cu->len = cu->len_wchar = cu->pos = 4; | cu->len = cu->len_wchar = cu->pos = 4; | ||||
| cu->strinfo = MEM_calloc_arrayN(12, sizeof(CharInfo), "strinfo new"); | cu->strinfo = (struct CharInfo *)MEM_calloc_arrayN(12, sizeof(CharInfo), "strinfo new"); | ||||
| cu->totbox = cu->actbox = 1; | cu->totbox = cu->actbox = 1; | ||||
| cu->tb = MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "textbox"); | cu->tb = (struct TextBox *)MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "textbox"); | ||||
| cu->tb[0].w = cu->tb[0].h = 0.0; | cu->tb[0].w = cu->tb[0].h = 0.0; | ||||
| } | } | ||||
| else if (cu->type == OB_SURF) { | else if (cu->type == OB_SURF) { | ||||
| cu->resolv = 4; | cu->resolu = cu->resolv = 8; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| { | { | ||||
| Curve *cu; | Curve *cu; | ||||
| cu = BKE_libblock_alloc(bmain, ID_CU, name, 0); | cu = (Curve *)BKE_libblock_alloc(bmain, ID_CU, name, 0); | ||||
| BKE_curve_init(cu, type); | BKE_curve_init(cu, type); | ||||
| return cu; | return cu; | ||||
| } | } | ||||
| Curve *BKE_curve_copy(Main *bmain, const Curve *cu) | Curve *BKE_curve_copy(Main *bmain, const Curve *cu) | ||||
| { | { | ||||
| Curve *cu_copy; | Curve *cu_copy; | ||||
| Context not available. | |||||
| return cu_copy; | return cu_copy; | ||||
| } | } | ||||
| /* Get list of nurbs from editnurbs structure */ | /* Get list of nurbs from editnurbs structure */ | ||||
| ListBase *BKE_curve_editNurbs_get(Curve *cu) | ListBase *BKE_curve_editNurbs_get(Curve *cu) | ||||
| { | { | ||||
| Context not available. | |||||
| if (!cu->type) { | if (!cu->type) { | ||||
| type = OB_CURVE; | type = OB_CURVE; | ||||
| for (nu = cu->nurb.first; nu; nu = nu->next) { | for (nu = (Nurb *)cu->nurb.first; nu; nu = (Nurb *)nu->next) { | ||||
| if (nu->pntsv > 1) { | if (nu->pntsv > 1) { | ||||
| type = OB_SURF; | type = OB_SURF; | ||||
| } | } | ||||
| Context not available. | |||||
| void BKE_curve_curve_dimension_update(Curve *cu) | void BKE_curve_curve_dimension_update(Curve *cu) | ||||
| { | { | ||||
| ListBase *nurbs = BKE_curve_nurbs_get(cu); | ListBase *nurbs = BKE_curve_nurbs_get(cu); | ||||
| Nurb *nu = nurbs->first; | Nurb *nu = (Nurb *)nurbs->first; | ||||
| if (cu->flag & CU_3D) { | if (cu->flag & CU_3D) { | ||||
| for (; nu; nu = nu->next) { | for (; nu; nu = nu->next) { | ||||
| Context not available. | |||||
| else { | else { | ||||
| for (; nu; nu = nu->next) { | for (; nu; nu = nu->next) { | ||||
| nu->flag |= CU_2D; | nu->flag |= CU_2D; | ||||
| BKE_nurb_test_2d(nu); | BKE_nurb_ensure_2d(nu); | ||||
| /* since the handles are moved they need to be auto-located again */ | /* since the handles are moved they need to be auto-located again */ | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| Context not available. | |||||
| void BKE_curve_type_test(Object *ob) | void BKE_curve_type_test(Object *ob) | ||||
| { | { | ||||
| ob->type = BKE_curve_type_get(ob->data); | ob->type = BKE_curve_type_get((Curve *)ob->data); | ||||
| if (ob->type == OB_CURVE) { | if (ob->type == OB_CURVE) { | ||||
| BKE_curve_curve_dimension_update((Curve *)ob->data); | BKE_curve_curve_dimension_update((Curve *)ob->data); | ||||
| Context not available. | |||||
| /* This is Object-level data access, | /* This is Object-level data access, | ||||
| * DO NOT touch to Mesh's bb, would be totally thread-unsafe. */ | * DO NOT touch to Mesh's bb, would be totally thread-unsafe. */ | ||||
| if (ob->runtime.bb == NULL || ob->runtime.bb->flag & BOUNDBOX_DIRTY) { | if (ob->runtime.bb == NULL || ob->runtime.bb->flag & BOUNDBOX_DIRTY) { | ||||
| Curve *cu = ob->data; | Curve *cu = (Curve *)ob->data; | ||||
| float min[3], max[3]; | float min[3], max[3]; | ||||
| INIT_MINMAX(min, max); | INIT_MINMAX(min, max); | ||||
| BKE_curve_minmax(cu, true, min, max); | BKE_curve_minmax(cu, true, min, max); | ||||
| if (ob->runtime.bb == NULL) { | if (ob->runtime.bb == NULL) { | ||||
| ob->runtime.bb = MEM_mallocN(sizeof(*ob->runtime.bb), __func__); | ob->runtime.bb = (struct BoundBox *)MEM_mallocN(sizeof(*ob->runtime.bb), __func__); | ||||
| } | } | ||||
| BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max); | BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max); | ||||
| ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY; | ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY; | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| struct NurbEditKnot* BKE_nurbs_editKnot_get(struct Nurb *nu) { | |||||
| if (nu->editknot) return nu->editknot; | |||||
| BKE_nurbs_editKnot_propagate_nurb2ek(nu); | |||||
| return nu->editknot; | |||||
| } | |||||
| void BKE_nurbs_editKnot_propagate_ek2nurb(struct Nurb *nu) { | |||||
| NurbEditKnot *ek = nu->editknot; | |||||
| if (!ek) return; | |||||
| int ek_knotu=0, ek_knotv=0; | |||||
| for (int i=0; i<ek->num_breaksu; i++) ek_knotu += ek->breaksu[i].multiplicity; | |||||
| BLI_assert(KNOTSU(nu)==ek_knotu); | |||||
| for (int i=0,flatidx=0; i<ek->num_breaksu; i++) { | |||||
| int mult = ek->breaksu[i].multiplicity; | |||||
| float breakpt = ek->breaksu[i].loc; | |||||
| for (int j=0; j<mult; j++) | |||||
| nu->knotsu[flatidx++] = breakpt; | |||||
| } | |||||
| if (ek->num_breaksv) { | |||||
| for (int i=0; i<ek->num_breaksv; i++) ek_knotv += ek->breaksv[i].multiplicity; | |||||
| BLI_assert(KNOTSV(nu)==ek_knotv); | |||||
| for (int i=0,flatidx=0; i<ek->num_breaksv; i++) { | |||||
| int mult = ek->breaksv[i].multiplicity; | |||||
| float breakpt = ek->breaksv[i].loc; | |||||
| for (int j=0; j<mult; j++) | |||||
| nu->knotsv[flatidx++] = breakpt; | |||||
| } | |||||
| } | |||||
| } | |||||
| /* Maintains flags for knots at a given location across knot update | |||||
| * Also clears NurbTrim SELECT flag whenever it allocates a new editknot (which | |||||
| * happens on editmode enter) */ | |||||
| void BKE_nurbs_editKnot_propagate_nurb2ek(struct Nurb *nu) { | |||||
| NurbEditKnot *ek = nu->editknot; | |||||
| NurbEditKnot old_ek; | |||||
| NurbTrim *nt; | |||||
| bool update_ek; | |||||
| if (ek) { | |||||
| old_ek = *ek; | |||||
| update_ek = true; | |||||
| } else { | |||||
| ek = nu->editknot = (NurbEditKnot*)MEM_callocN(sizeof(*ek),"NURBS_editknot_prop"); | |||||
| for (nt=(NurbTrim*)nu->trims.first; nt; nt=nt->next) { | |||||
| nt->flag &= ~SELECT; | |||||
| } | |||||
| update_ek = false; | |||||
| } | |||||
| int capu = ek->capu = KNOTSU(nu); | |||||
| ek->breaksu = (NurbBreakpt*)MEM_callocN(capu*sizeof(NurbBreakpt), "NURBS_editknot_u"); | |||||
| float last_knot=INFINITY; | |||||
| int old_idx=0, breakidx=-1; | |||||
| for (int i=0; i<KNOTSU(nu); i++) { | |||||
| float knot = nu->knotsu[i]; | |||||
| if (knot!=last_knot) { | |||||
| breakidx += 1; | |||||
| last_knot = knot; | |||||
| } | |||||
| if (update_ek) { /* try to propagate SELECT etc from old ek to new ek */ | |||||
| while (old_ek.breaksu[old_idx].loc<knot && old_idx<old_ek.num_breaksu) | |||||
| old_idx++; | |||||
| if (old_ek.breaksu[old_idx].loc==knot) | |||||
| ek->breaksu[breakidx].flag = old_ek.breaksu[old_idx].flag; | |||||
| } | |||||
| ek->breaksu[breakidx].loc = knot; | |||||
| ek->breaksu[breakidx].multiplicity += 1; | |||||
| } | |||||
| ek->num_breaksu = breakidx+1; | |||||
| if (nu->pntsv==1) { | |||||
| ek->num_breaksv = 0; /* This is a curve. There are no breakpoints in v direction. */ | |||||
| ek->breaksv = NULL; | |||||
| } else { | |||||
| int capv = ek->capv = KNOTSV(nu); | |||||
| ek->breaksv = (NurbBreakpt*)MEM_callocN(capv*sizeof(NurbBreakpt), "NURBS_editknot_v"); | |||||
| last_knot=INFINITY; | |||||
| old_idx=0; breakidx=-1; | |||||
| for (int i=0; i<KNOTSV(nu); i++) { | |||||
| float knot = nu->knotsv[i]; | |||||
| if (knot!=last_knot) { | |||||
| breakidx += 1; | |||||
| last_knot = knot; | |||||
| } | |||||
| if (update_ek) { /* try to propagate SELECT etc from old ek to new ek */ | |||||
| while (old_ek.breaksv[old_idx].loc<knot && old_idx<old_ek.num_breaksv) | |||||
| old_idx++; | |||||
| if (old_ek.breaksv[old_idx].loc==knot) | |||||
| ek->breaksv[breakidx].flag = old_ek.breaksv[old_idx].flag; | |||||
| } | |||||
| ek->breaksv[breakidx].loc = knot; | |||||
| ek->breaksv[breakidx].multiplicity += 1; | |||||
| } | |||||
| ek->num_breaksv = breakidx+1; | |||||
| } | |||||
| if (update_ek) { | |||||
| MEM_freeN(old_ek.breaksu); | |||||
| MEM_freeN(old_ek.breaksv); | |||||
| } | |||||
| // printf("U: Propagated {"); | |||||
| // for (int i=0; i<KNOTSU(nu); i++) printf("%3.1f ",nu->knotsu[i]); | |||||
| // printf("} -> {"); | |||||
| // for (int i=0; i<ek->num_breaksu; i++) printf("%3.1fx%i ",ek->breaksu[i].loc,ek->breaksu[i].multiplicity); | |||||
| // printf("}\n"); | |||||
| // printf("V: Propagated {"); | |||||
| // for (int i=0; i<KNOTSV(nu); i++) printf("%3.1f ",nu->knotsv[i]); | |||||
| // printf("} -> {"); | |||||
| // for (int i=0; i<ek->num_breaksv; i++) printf("%3.1fx%i ",ek->breaksv[i].loc,ek->breaksv[i].multiplicity); | |||||
| // printf("}\n"); | |||||
| } | |||||
| void BKE_nurbs_editKnot_destroy(struct Nurb *nu) { | |||||
| NurbEditKnot* ek = nu->editknot; | |||||
| if (!ek) return; | |||||
| if (ek->breaksu) MEM_freeN(ek->breaksu); | |||||
| if (ek->breaksv) MEM_freeN(ek->breaksv); | |||||
| MEM_freeN(nu->editknot); | |||||
| nu->editknot = NULL; | |||||
| } | |||||
| bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3]) | bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3]) | ||||
| { | { | ||||
| Nurb *nu; | Nurb *nu; | ||||
| int tot = 0; | int tot = 0; | ||||
| for (nu = nurb->first; nu; nu = nu->next) { | for (nu = (Nurb *)nurb->first; nu; nu = nu->next) { | ||||
| int tot_nu; | int tot_nu; | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| tot_nu = nu->pntsu; | tot_nu = nu->pntsu; | ||||
| Context not available. | |||||
| Nurb *nu; | Nurb *nu; | ||||
| int tot = 0; | int tot = 0; | ||||
| nu = nurb->first; | nu = (Nurb *)nurb->first; | ||||
| while (nu) { | while (nu) { | ||||
| if (nu->bezt) { | if (nu->bezt) { | ||||
| tot += 3 * nu->pntsu; | tot += 3 * nu->pntsu; | ||||
| Context not available. | |||||
| Nurb *nu; | Nurb *nu; | ||||
| int tot = 0; | int tot = 0; | ||||
| nu = nurb->first; | nu = (Nurb *)nurb->first; | ||||
| while (nu) { | while (nu) { | ||||
| if (nu->bezt) { | if (nu->bezt) { | ||||
| tot += nu->pntsu; | tot += nu->pntsu; | ||||
| Context not available. | |||||
| void BKE_nurb_free(Nurb *nu) | void BKE_nurb_free(Nurb *nu) | ||||
| { | { | ||||
| printf("BKE_nurb_free 0x%lx\n",(unsigned long)nu); | |||||
| if (nu == NULL) { | if (nu == NULL) { | ||||
| return; | return; | ||||
| Context not available. | |||||
| MEM_freeN(nu->knotsv); | MEM_freeN(nu->knotsv); | ||||
| } | } | ||||
| nu->knotsv = NULL; | nu->knotsv = NULL; | ||||
| /* if (nu->trim.first) freeNurblist(&(nu->trim)); */ | for (NurbTrim *nt = (NurbTrim*)nu->trims.first; nt;) { | ||||
| NurbTrim *nt_to_free = nt; | |||||
| nt = nt->next; | |||||
| BKE_nurbTrim_free(nt_to_free); | |||||
| } | |||||
| if (nu->UV_idxs) MEM_freeN(nu->UV_idxs); | |||||
| if (nu->UV_verts) MEM_freeN(nu->UV_verts); | |||||
| if (nu->editknot) BKE_nurbs_editKnot_destroy(nu); | |||||
| MEM_freeN(nu); | MEM_freeN(nu); | ||||
| } | } | ||||
| void BKE_nurbTrim_free(NurbTrim *nt) { | |||||
| BKE_nurbList_free(&nt->nurb_list); | |||||
| MEM_freeN(nt); | |||||
| } | |||||
| void BKE_nurbList_free(ListBase *lb) | void BKE_nurbList_free(ListBase *lb) | ||||
| { | { | ||||
| Nurb *nu, *next; | Nurb *nu, *next; | ||||
| Context not available. | |||||
| return; | return; | ||||
| } | } | ||||
| nu = lb->first; | nu = (Nurb *)lb->first; | ||||
| while (nu) { | while (nu) { | ||||
| next = nu->next; | next = nu->next; | ||||
| BKE_nurb_free(nu); | BKE_nurb_free(nu); | ||||
| Context not available. | |||||
| memcpy(newnu->bezt, nu->bezt, nu->pntsu * sizeof(BezTriple)); | memcpy(newnu->bezt, nu->bezt, nu->pntsu * sizeof(BezTriple)); | ||||
| } | } | ||||
| else { | else { | ||||
| len = nu->pntsu * nu->pntsv; | len = ( nu->pntsu) * | ||||
| ( nu->pntsv); | |||||
| newnu->bp = (BPoint *)MEM_malloc_arrayN(len, sizeof(BPoint), "duplicateNurb3"); | newnu->bp = (BPoint *)MEM_malloc_arrayN(len, sizeof(BPoint), "duplicateNurb3"); | ||||
| memcpy(newnu->bp, nu->bp, len * sizeof(BPoint)); | memcpy(newnu->bp, nu->bp, len * sizeof(BPoint)); | ||||
| Context not available. | |||||
| if (nu->knotsu) { | if (nu->knotsu) { | ||||
| len = KNOTSU(nu); | len = KNOTSU(nu); | ||||
| if (len) { | if (len) { | ||||
| newnu->knotsu = MEM_malloc_arrayN(len, sizeof(float), "duplicateNurb4"); | newnu->knotsu = (float*)MEM_malloc_arrayN(len, sizeof(float), "duplicateNurb4"); | ||||
| memcpy(newnu->knotsu, nu->knotsu, sizeof(float) * len); | memcpy(newnu->knotsu, nu->knotsu, sizeof(float) * len); | ||||
| } | } | ||||
| } | } | ||||
| if (nu->pntsv > 1 && nu->knotsv) { | if (nu->pntsv > 1 && nu->knotsv) { | ||||
| len = KNOTSV(nu); | len = KNOTSV(nu); | ||||
| if (len) { | if (len) { | ||||
| newnu->knotsv = MEM_malloc_arrayN(len, sizeof(float), "duplicateNurb5"); | newnu->knotsv = (float *)MEM_malloc_arrayN(len, sizeof(float), "duplicateNurb5"); | ||||
| memcpy(newnu->knotsv, nu->knotsv, sizeof(float) * len); | memcpy(newnu->knotsv, nu->knotsv, sizeof(float) * len); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| newnu->trims.first = newnu->trims.last = NULL; | |||||
| for (NurbTrim *nt = (NurbTrim*)nu->trims.first; nt; nt=nt->next) { | |||||
| NurbTrim *dup_nt = BKE_nurbTrim_duplicate(nt); | |||||
| dup_nt->parent_nurb = newnu; | |||||
| BLI_addtail(&newnu->trims, dup_nt); | |||||
| } | |||||
| BKE_nurbs_cached_UV_mesh_clear(newnu,false); | |||||
| return newnu; | return newnu; | ||||
| } | } | ||||
| Context not available. | |||||
| else { | else { | ||||
| newnu->bp = (BPoint *)MEM_malloc_arrayN(pntsu * pntsv, sizeof(BPoint), "copyNurb3"); | newnu->bp = (BPoint *)MEM_malloc_arrayN(pntsu * pntsv, sizeof(BPoint), "copyNurb3"); | ||||
| } | } | ||||
| newnu->trims.first = newnu->trims.last = NULL; | |||||
| for (NurbTrim *nt = (NurbTrim*)src->trims.first; nt; nt=nt->next) { | |||||
| NurbTrim *dup_nt = BKE_nurbTrim_duplicate(nt); | |||||
| BLI_addtail(&newnu->trims, dup_nt); | |||||
| } | |||||
| BKE_nurbs_cached_UV_mesh_clear(newnu,false); | |||||
| newnu->editknot = NULL; | |||||
| return newnu; | return newnu; | ||||
| } | } | ||||
| NurbTrim *BKE_nurbTrim_duplicate(NurbTrim *nt) { | |||||
| NurbTrim *ret = (NurbTrim*)MEM_callocN(sizeof(NurbTrim), "duplicateNurbTrim"); | |||||
| BKE_nurbList_duplicate(&ret->nurb_list, &nt->nurb_list); | |||||
| ret->type = nt->type; | |||||
| ret->parent_nurb = nt->parent_nurb; | |||||
| return ret; | |||||
| } | |||||
| int BKE_nurbTrim_tess(struct NurbTrim *nt, float (**uv_out)[2]) { | |||||
| int tot_tess_pts = 0; | |||||
| for (Nurb* nu = (Nurb*)nt->nurb_list.first; nu; nu=nu->next) { | |||||
| int tess_pts = nu->pntsu * nu->resolu + 1; | |||||
| if (nu->flagu&CU_NURB_ENDPOINT) tess_pts = (nu->pntsu+2-nu->orderu)*nu->resolu; | |||||
| tot_tess_pts += tess_pts; | |||||
| } | |||||
| float (*uv)[2] = (float(*)[2])MEM_mallocN(sizeof(*uv)*tot_tess_pts, "BKE_nurbTrim_tess"); | |||||
| *uv_out = uv; | |||||
| for (Nurb* nu = (Nurb*)nt->nurb_list.first; nu; nu=nu->next) { | |||||
| int tess_pts = nu->pntsu * nu->resolu + 1; | |||||
| if (nu->flagu&CU_NURB_ENDPOINT) tess_pts = (nu->pntsu+2-nu->orderu)*nu->resolu; | |||||
| float *U = nu->knotsu; | |||||
| int pntsu = nu->pntsu; | |||||
| BPoint *bp = nu->bp; | |||||
| int orderu = nu->orderu; | |||||
| float umin, umax; | |||||
| BKE_nurbs_domain(nu, &umin, &umax, NULL, NULL); | |||||
| float du = (umax-umin)/(tess_pts-1); | |||||
| for (int i=0; i<tess_pts; i++) { | |||||
| BPoint pt; | |||||
| float u = (i!=tess_pts-1)? umin+i*du : umax; | |||||
| BKE_nurbs_curve_eval(u, U, pntsu, orderu, bp, 1, 0, &pt); | |||||
| uv[i][0] = pt.vec[0]; | |||||
| uv[i][1] = pt.vec[1]; | |||||
| } | |||||
| uv += tess_pts; | |||||
| } | |||||
| return tot_tess_pts; | |||||
| } | |||||
| void BKE_nurbTrim_update_data(struct NurbTrim *nt) { | |||||
| BKE_nurbs_cached_UV_mesh_clear((Nurb*)nt->parent_nurb, true); | |||||
| } | |||||
| void BKE_nurbList_duplicate(ListBase *lb1, const ListBase *lb2) | void BKE_nurbList_duplicate(ListBase *lb1, const ListBase *lb2) | ||||
| { | { | ||||
| Nurb *nu, *nun; | Nurb *nu, *nun; | ||||
| BKE_nurbList_free(lb1); | BKE_nurbList_free(lb1); | ||||
| nu = lb2->first; | nu = (Nurb *)lb2->first; | ||||
| while (nu) { | while (nu) { | ||||
| nun = BKE_nurb_duplicate(nu); | nun = BKE_nurb_duplicate(nu); | ||||
| BLI_addtail(lb1, nun); | BLI_addtail(lb1, nun); | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| void BKE_nurb_test_2d(Nurb *nu) | void BKE_nurb_ensure_2d(Nurb *nu) | ||||
| { | { | ||||
| BezTriple *bezt; | BezTriple *bezt; | ||||
| BPoint *bp; | BPoint *bp; | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| else if (nu->type == CU_BEZIER) { | else if (nu->type == CU_BEZIER) { | ||||
| points = MEM_mallocN(sizeof(float[3]) * (resolu + 1), "getLength_bezier"); | points = (float *)MEM_mallocN(sizeof(float[3]) * (resolu + 1), "getLength_bezier"); | ||||
| a = nu->pntsu - 1; | a = nu->pntsu - 1; | ||||
| bezt = nu->bezt; | bezt = nu->bezt; | ||||
| if (nu->flagu & CU_NURB_CYCLIC) { | if (nu->flagu & CU_NURB_CYCLIC) { | ||||
| Context not available. | |||||
| else if (nu->type == CU_NURBS) { | else if (nu->type == CU_NURBS) { | ||||
| if (nu->pntsv == 1) { | if (nu->pntsv == 1) { | ||||
| /* important to zero for BKE_nurb_makeCurve. */ | /* important to zero for BKE_nurb_makeCurve. */ | ||||
| points = MEM_callocN(sizeof(float[3]) * pntsu * resolu, "getLength_nurbs"); | points = (float *)MEM_callocN(sizeof(float[3]) * pntsu * resolu, "getLength_nurbs"); | ||||
| BKE_nurb_makeCurve(nu, points, NULL, NULL, NULL, resolu, sizeof(float[3])); | BKE_nurb_makeCurve(nu, points, NULL, NULL, NULL, resolu, sizeof(float[3])); | ||||
| Context not available. | |||||
| BPoint *bp; | BPoint *bp; | ||||
| int i; | int i; | ||||
| nu->bp = MEM_recallocN(nu->bp, (nu->pntsu + number) * sizeof(BPoint)); | nu->bp = (BPoint *)MEM_recallocN(nu->bp, (nu->pntsu + number) * sizeof(BPoint)); | ||||
| for (i = 0, bp = &nu->bp[nu->pntsu]; i < number; i++, bp++) { | for (i = 0, bp = &nu->bp[nu->pntsu]; i < number; i++, bp++) { | ||||
| bp->radius = 1.0f; | bp->radius = 1.0f; | ||||
| } | } | ||||
| nu->pntsu += number; | nu->pntsu += number; | ||||
| BKE_nurbs_cached_UV_mesh_clear(nu, true); | |||||
| } | } | ||||
| void BKE_nurb_bezierPoints_add(Nurb *nu, int number) | void BKE_nurb_bezierPoints_add(Nurb *nu, int number) | ||||
| Context not available. | |||||
| BezTriple *bezt; | BezTriple *bezt; | ||||
| int i; | int i; | ||||
| nu->bezt = MEM_recallocN(nu->bezt, (nu->pntsu + number) * sizeof(BezTriple)); | nu->bezt = (BezTriple *)MEM_recallocN(nu->bezt, (nu->pntsu + number) * sizeof(BezTriple)); | ||||
| for (i = 0, bezt = &nu->bezt[nu->pntsu]; i < number; i++, bezt++) { | for (i = 0, bezt = &nu->bezt[nu->pntsu]; i < number; i++, bezt++) { | ||||
| bezt->radius = 1.0f; | bezt->radius = 1.0f; | ||||
| } | } | ||||
| nu->pntsu += number; | nu->pntsu += number; | ||||
| BKE_nurbs_cached_UV_mesh_clear(nu, true); | |||||
| } | } | ||||
| int BKE_nurb_index_from_uv(Nurb *nu, int u, int v) | int BKE_nurb_index_from_uv(Nurb *nu, int u, int v) | ||||
| Context not available. | |||||
| /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */ | /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */ | ||||
| static void calcknots(float *knots, const int pnts, const short order, const short flag) | |||||
| { | |||||
| /* knots: number of pnts NOT corrected for cyclic */ | |||||
| const int pnts_order = pnts + order; | |||||
| float k; | |||||
| int a; | |||||
| switch (flag & (CU_NURB_ENDPOINT | CU_NURB_BEZIER)) { | |||||
| case CU_NURB_ENDPOINT: | |||||
| k = 0.0; | |||||
| for (a = 1; a <= pnts_order; a++) { | |||||
| knots[a - 1] = k; | |||||
| if (a >= order && a <= pnts) { | |||||
| k += 1.0f; | |||||
| } | |||||
| } | |||||
| break; | |||||
| case CU_NURB_BEZIER: | |||||
| /* Warning, the order MUST be 2 or 4, | |||||
| * if this is not enforced, the displist will be corrupt */ | |||||
| if (order == 4) { | |||||
| k = 0.34; | |||||
| for (a = 0; a < pnts_order; a++) { | |||||
| knots[a] = floorf(k); | |||||
| k += (1.0f / 3.0f); | |||||
| } | |||||
| } | |||||
| else if (order == 3) { | |||||
| k = 0.6f; | |||||
| for (a = 0; a < pnts_order; a++) { | |||||
| if (a >= order && a <= pnts) { | |||||
| k += 0.5f; | |||||
| } | |||||
| knots[a] = floorf(k); | |||||
| } | |||||
| } | |||||
| else { | |||||
| CLOG_ERROR(&LOG, "bez nurb curve order is not 3 or 4, should never happen"); | |||||
| } | |||||
| break; | |||||
| default: | |||||
| for (a = 0; a < pnts_order; a++) { | |||||
| knots[a] = (float)a; | |||||
| } | |||||
| break; | |||||
| } | |||||
| } | |||||
| static void makecyclicknots(float *knots, int pnts, short order) | |||||
| /* pnts, order: number of pnts NOT corrected for cyclic */ | |||||
| { | |||||
| int a, b, order2, c; | |||||
| if (knots == NULL) { | |||||
| return; | |||||
| } | |||||
| order2 = order - 1; | |||||
| /* do first long rows (order -1), remove identical knots at endpoints */ | |||||
| if (order > 2) { | |||||
| b = pnts + order2; | |||||
| for (a = 1; a < order2; a++) { | |||||
| if (knots[b] != knots[b - a]) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (a == order2) { | |||||
| knots[pnts + order - 2] += 1.0f; | |||||
| } | |||||
| } | |||||
| b = order; | |||||
| c = pnts + order + order2; | |||||
| for (a = pnts + order2; a < c; a++) { | |||||
| knots[a] = knots[a - 1] + (knots[b] - knots[b - 1]); | |||||
| b--; | |||||
| } | |||||
| } | |||||
| static void makeknots(Nurb *nu, short uv) | |||||
| { | |||||
| if (nu->type == CU_NURBS) { | |||||
| if (uv == 1) { | |||||
| if (nu->knotsu) { | |||||
| MEM_freeN(nu->knotsu); | |||||
| } | |||||
| if (BKE_nurb_check_valid_u(nu)) { | |||||
| nu->knotsu = MEM_calloc_arrayN(KNOTSU(nu) + 1, sizeof(float), "makeknots"); | |||||
| if (nu->flagu & CU_NURB_CYCLIC) { | |||||
| calcknots(nu->knotsu, nu->pntsu, nu->orderu, 0); /* cyclic should be uniform */ | |||||
| makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu); | |||||
| } | |||||
| else { | |||||
| calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu); | |||||
| } | |||||
| } | |||||
| else { | |||||
| nu->knotsu = NULL; | |||||
| } | |||||
| } | |||||
| else if (uv == 2) { | |||||
| if (nu->knotsv) { | |||||
| MEM_freeN(nu->knotsv); | |||||
| } | |||||
| if (BKE_nurb_check_valid_v(nu)) { | |||||
| nu->knotsv = MEM_calloc_arrayN(KNOTSV(nu) + 1, sizeof(float), "makeknots"); | |||||
| if (nu->flagv & CU_NURB_CYCLIC) { | |||||
| calcknots(nu->knotsv, nu->pntsv, nu->orderv, 0); /* cyclic should be uniform */ | |||||
| makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv); | |||||
| } | |||||
| else { | |||||
| calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv); | |||||
| } | |||||
| } | |||||
| else { | |||||
| nu->knotsv = NULL; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| void BKE_nurb_knot_calc_u(Nurb *nu) | |||||
| { | |||||
| makeknots(nu, 1); | |||||
| } | |||||
| void BKE_nurb_knot_calc_v(Nurb *nu) | |||||
| { | |||||
| makeknots(nu, 2); | |||||
| } | |||||
| // static void calcknots(float *knots, const int pnts, const short order, const short flag) | |||||
| // { | |||||
| // /* knots: number of pnts NOT corrected for cyclic */ | |||||
| // const int pnts_order = pnts + order; | |||||
| // float k; | |||||
| // int a; | |||||
| // switch (flag & (CU_NURB_ENDPOINT | CU_NURB_BEZIER)) { | |||||
| // case CU_NURB_ENDPOINT: | |||||
| // k = 0.0; | |||||
| // for (a = 1; a <= pnts_order; a++) { | |||||
| // knots[a - 1] = k; | |||||
| // if (a >= order && a <= pnts) { | |||||
| // k += 1.0f; | |||||
| // } | |||||
| // } | |||||
| // break; | |||||
| // case CU_NURB_BEZIER: | |||||
| // /* Warning, the order MUST be 2 or 4, | |||||
| // * if this is not enforced, the displist will be corrupt */ | |||||
| // if (order == 4) { | |||||
| // k = 0.34; | |||||
| // for (a = 0; a < pnts_order; a++) { | |||||
| // knots[a] = floorf(k); | |||||
| // k += (1.0f / 3.0f); | |||||
| // } | |||||
| // } | |||||
| // else if (order == 3) { | |||||
| // k = 0.6f; | |||||
| // for (a = 0; a < pnts_order; a++) { | |||||
| // if (a >= order && a <= pnts) { | |||||
| // k += 0.5f; | |||||
| // } | |||||
| // knots[a] = floorf(k); | |||||
| // } | |||||
| // } | |||||
| // else { | |||||
| // CLOG_ERROR(&LOG, "bez nurb curve order is not 3 or 4, should never happen"); | |||||
| // } | |||||
| // break; | |||||
| // default: | |||||
| // for (a = 0; a < pnts_order; a++) { | |||||
| // knots[a] = (float)a; | |||||
| // } | |||||
| // break; | |||||
| // } | |||||
| // } | |||||
| // static void makecyclicknots(float *knots, int pnts, short order) | |||||
| // /* pnts, order: number of pnts NOT corrected for cyclic */ | |||||
| // { | |||||
| // int a, b, order2, c; | |||||
| // if (knots == NULL) { | |||||
| // return; | |||||
| // } | |||||
| // order2 = order - 1; | |||||
| // /* do first long rows (order -1), remove identical knots at endpoints */ | |||||
| // if (order > 2) { | |||||
| // b = pnts + order2; | |||||
| // for (a = 1; a < order2; a++) { | |||||
| // if (knots[b] != knots[b - a]) { | |||||
| // break; | |||||
| // } | |||||
| // } | |||||
| // if (a == order2) { | |||||
| // knots[pnts + order - 2] += 1.0f; | |||||
| // } | |||||
| // } | |||||
| // b = order; | |||||
| // c = pnts + order + order2; | |||||
| // for (a = pnts + order2; a < c; a++) { | |||||
| // knots[a] = knots[a - 1] + (knots[b] - knots[b - 1]); | |||||
| // b--; | |||||
| // } | |||||
| // } | |||||
| // static void makeknots(Nurb *nu, short uv) | |||||
| // { | |||||
| // if (nu->type == CU_NURBS) { | |||||
| // if (uv == 1) { | |||||
| // if (nu->knotsu) { | |||||
| // MEM_freeN(nu->knotsu); | |||||
| // } | |||||
| // if (BKE_nurb_check_valid_u(nu)) { | |||||
| // nu->knotsu = (float *)MEM_calloc_arrayN(KNOTSU(nu) + 1, sizeof(float), "makeknots"); | |||||
| // if (nu->flagu & CU_NURB_CYCLIC) { | |||||
| // calcknots(nu->knotsu, nu->pntsu, nu->orderu, 0); /* cyclic should be uniform */ | |||||
| // makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu); | |||||
| // } | |||||
| // else { | |||||
| // calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu); | |||||
| // } | |||||
| // } | |||||
| // else { | |||||
| // nu->knotsu = NULL; | |||||
| // } | |||||
| // } | |||||
| // else if (uv == 2) { | |||||
| // if (nu->knotsv) { | |||||
| // MEM_freeN(nu->knotsv); | |||||
| // } | |||||
| // if (BKE_nurb_check_valid_v(nu)) { | |||||
| // nu->knotsv = (float *)MEM_calloc_arrayN(KNOTSV(nu) + 1, sizeof(float), "makeknots"); | |||||
| // if (nu->flagv & CU_NURB_CYCLIC) { | |||||
| // calcknots(nu->knotsv, nu->pntsv, nu->orderv, 0); /* cyclic should be uniform */ | |||||
| // makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv); | |||||
| // } | |||||
| // else { | |||||
| // calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv); | |||||
| // } | |||||
| // } | |||||
| // else { | |||||
| // nu->knotsv = NULL; | |||||
| // } | |||||
| // } | |||||
| // } | |||||
| // } | |||||
| // void BKE_nurb_knot_calc_u(Nurb *nu) | |||||
| // { | |||||
| // makeknots(nu, 1); | |||||
| // } | |||||
| // void BKE_nurb_knot_calc_v(Nurb *nu) | |||||
| // { | |||||
| // makeknots(nu, 2); | |||||
| // } | |||||
| /* Fills <basis> with <pnts> weights corresponding to the curve evaluated | |||||
| * at point t. <start> is the index of the first nz basis function at t, <end> | |||||
| * is the index of the last nz basis function at t. | |||||
| */ | |||||
| static void basisNurb( | static void basisNurb( | ||||
| float t, short order, int pnts, float *knots, float *basis, int *start, int *end) | float t, short order, int pnts, float *knots, float *basis, int *start, int *end) | ||||
| { | { | ||||
| Context not available. | |||||
| /** | /** | ||||
| * \param coord_array: has to be (3 * 4 * resolu * resolv) in size, and zero-ed. | * \param coord_array: has to be (3 * 4 * resolu * resolv) in size, and zero-ed. | ||||
| */ | */ | ||||
| void BKE_nurb_makeFaces(const Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv) | // void BKE_nurb_makeFaces(const Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv) | ||||
| { | // { | ||||
| BPoint *bp; | // BPoint *bp; | ||||
| float *basisu, *basis, *basisv, *sum, *fp, *in; | // float *basisu, *basis, *basisv, *sum, *fp, *in; | ||||
| float u, v, ustart, uend, ustep, vstart, vend, vstep, sumdiv; | // float u, v, ustart, uend, ustep, vstart, vend, vstep, sumdiv; | ||||
| int i, j, iofs, jofs, cycl, len, curu, curv; | // int i, j, iofs, jofs, cycl, len, curu, curv; | ||||
| int istart, iend, jsta, jen, *jstart, *jend, ratcomp; | // int istart, iend, jsta, jen, *jstart, *jend, ratcomp; | ||||
| int totu = nu->pntsu * resolu, totv = nu->pntsv * resolv; | // int totu = nu->pntsu * resolu, totv = nu->pntsv * resolv; | ||||
| if (nu->knotsu == NULL || nu->knotsv == NULL) { | // if (nu->knotsu == NULL || nu->knotsv == NULL) { | ||||
| return; | // return; | ||||
| } | // } | ||||
| if (nu->orderu > nu->pntsu) { | // if (nu->orderu > nu->pntsu) { | ||||
| return; | // return; | ||||
| } | // } | ||||
| if (nu->orderv > nu->pntsv) { | // if (nu->orderv > nu->pntsv) { | ||||
| return; | // return; | ||||
| } | // } | ||||
| if (coord_array == NULL) { | // if (coord_array == NULL) { | ||||
| return; | // return; | ||||
| } | // } | ||||
| /* allocate and initialize */ | // /* allocate and initialize */ | ||||
| len = totu * totv; | // len = totu * totv; | ||||
| if (len == 0) { | // if (len == 0) { | ||||
| return; | // return; | ||||
| } | // } | ||||
| sum = (float *)MEM_calloc_arrayN(len, sizeof(float), "makeNurbfaces1"); | // sum = (float *)MEM_calloc_arrayN(len, sizeof(float), "makeNurbfaces1"); | ||||
| bp = nu->bp; | // bp = nu->bp; | ||||
| i = nu->pntsu * nu->pntsv; | // i = nu->pntsu * nu->pntsv; | ||||
| ratcomp = 0; | // ratcomp = 0; | ||||
| while (i--) { | // while (i--) { | ||||
| if (bp->vec[3] != 1.0f) { | // if (bp->vec[3] != 1.0f) { | ||||
| ratcomp = 1; | // ratcomp = 1; | ||||
| break; | // break; | ||||
| } | // } | ||||
| bp++; | // bp++; | ||||
| } | // } | ||||
| fp = nu->knotsu; | // fp = nu->knotsu; | ||||
| ustart = fp[nu->orderu - 1]; | // ustart = fp[nu->orderu - 1]; | ||||
| if (nu->flagu & CU_NURB_CYCLIC) { | // if (nu->flagu & CU_NURB_CYCLIC) { | ||||
| uend = fp[nu->pntsu + nu->orderu - 1]; | // uend = fp[nu->pntsu + nu->orderu - 1]; | ||||
| } | // } | ||||
| else { | // else { | ||||
| uend = fp[nu->pntsu]; | // uend = fp[nu->pntsu]; | ||||
| } | // } | ||||
| ustep = (uend - ustart) / ((nu->flagu & CU_NURB_CYCLIC) ? totu : totu - 1); | // ustep = (uend - ustart) / ((nu->flagu & CU_NURB_CYCLIC) ? totu : totu - 1); | ||||
| basisu = (float *)MEM_malloc_arrayN(KNOTSU(nu), sizeof(float), "makeNurbfaces3"); | // basisu = (float *)MEM_malloc_arrayN(KNOTSU(nu), sizeof(float), "makeNurbfaces3"); | ||||
| fp = nu->knotsv; | // fp = nu->knotsv; | ||||
| vstart = fp[nu->orderv - 1]; | // vstart = fp[nu->orderv - 1]; | ||||
| if (nu->flagv & CU_NURB_CYCLIC) { | // if (nu->flagv & CU_NURB_CYCLIC) { | ||||
| vend = fp[nu->pntsv + nu->orderv - 1]; | // vend = fp[nu->pntsv + nu->orderv - 1]; | ||||
| } | // } | ||||
| else { | // else { | ||||
| vend = fp[nu->pntsv]; | // vend = fp[nu->pntsv]; | ||||
| } | // } | ||||
| vstep = (vend - vstart) / ((nu->flagv & CU_NURB_CYCLIC) ? totv : totv - 1); | // vstep = (vend - vstart) / ((nu->flagv & CU_NURB_CYCLIC) ? totv : totv - 1); | ||||
| len = KNOTSV(nu); | // len = KNOTSV(nu); | ||||
| basisv = (float *)MEM_malloc_arrayN(len * totv, sizeof(float), "makeNurbfaces3"); | // basisv = (float *)MEM_malloc_arrayN(len * totv, sizeof(float), "makeNurbfaces3"); | ||||
| jstart = (int *)MEM_malloc_arrayN(totv, sizeof(float), "makeNurbfaces4"); | // jstart = (int *)MEM_malloc_arrayN(totv, sizeof(float), "makeNurbfaces4"); | ||||
| jend = (int *)MEM_malloc_arrayN(totv, sizeof(float), "makeNurbfaces5"); | // jend = (int *)MEM_malloc_arrayN(totv, sizeof(float), "makeNurbfaces5"); | ||||
| /* precalculation of basisv and jstart, jend */ | // /* precalculation of basisv and jstart, jend */ | ||||
| if (nu->flagv & CU_NURB_CYCLIC) { | // if (nu->flagv & CU_NURB_CYCLIC) { | ||||
| cycl = nu->orderv - 1; | // cycl = nu->orderv - 1; | ||||
| } | // } | ||||
| else { | // else { | ||||
| cycl = 0; | // cycl = 0; | ||||
| } | // } | ||||
| v = vstart; | // v = vstart; | ||||
| basis = basisv; | // basis = basisv; | ||||
| curv = totv; | // curv = totv; | ||||
| while (curv--) { | // while (curv--) { | ||||
| basisNurb(v, nu->orderv, nu->pntsv + cycl, nu->knotsv, basis, jstart + curv, jend + curv); | // basisNurb(v, nu->orderv, nu->pntsv + cycl, nu->knotsv, basis, jstart + curv, jend + curv); | ||||
| basis += KNOTSV(nu); | // basis += KNOTSV(nu); | ||||
| v += vstep; | // v += vstep; | ||||
| } | // } | ||||
| if (nu->flagu & CU_NURB_CYCLIC) { | // if (nu->flagu & CU_NURB_CYCLIC) { | ||||
| cycl = nu->orderu - 1; | // cycl = nu->orderu - 1; | ||||
| } | // } | ||||
| else { | // else { | ||||
| cycl = 0; | // cycl = 0; | ||||
| } | // } | ||||
| in = coord_array; | // in = coord_array; | ||||
| u = ustart; | // u = ustart; | ||||
| curu = totu; | // curu = totu; | ||||
| while (curu--) { | // while (curu--) { | ||||
| basisNurb(u, nu->orderu, nu->pntsu + cycl, nu->knotsu, basisu, &istart, &iend); | // basisNurb(u, nu->orderu, nu->pntsu + cycl, nu->knotsu, basisu, &istart, &iend); | ||||
| basis = basisv; | // basis = basisv; | ||||
| curv = totv; | // curv = totv; | ||||
| while (curv--) { | // while (curv--) { | ||||
| jsta = jstart[curv]; | // jsta = jstart[curv]; | ||||
| jen = jend[curv]; | // jen = jend[curv]; | ||||
| /* calculate sum */ | // /* calculate sum */ | ||||
| sumdiv = 0.0; | // sumdiv = 0.0; | ||||
| fp = sum; | // fp = sum; | ||||
| for (j = jsta; j <= jen; j++) { | // for (j = jsta; j <= jen; j++) { | ||||
| if (j >= nu->pntsv) { | // if (j >= nu->pntsv) { | ||||
| jofs = (j - nu->pntsv); | // jofs = (j - nu->pntsv); | ||||
| } | // } | ||||
| else { | // else { | ||||
| jofs = j; | // jofs = j; | ||||
| } | // } | ||||
| bp = nu->bp + nu->pntsu * jofs + istart - 1; | // bp = nu->bp + nu->pntsu * jofs + istart - 1; | ||||
| for (i = istart; i <= iend; i++, fp++) { | // for (i = istart; i <= iend; i++, fp++) { | ||||
| if (i >= nu->pntsu) { | // if (i >= nu->pntsu) { | ||||
| iofs = i - nu->pntsu; | // iofs = i - nu->pntsu; | ||||
| bp = nu->bp + nu->pntsu * jofs + iofs; | // bp = nu->bp + nu->pntsu * jofs + iofs; | ||||
| } | // } | ||||
| else { | // else { | ||||
| bp++; | // bp++; | ||||
| } | // } | ||||
| if (ratcomp) { | // if (ratcomp) { | ||||
| *fp = basisu[i] * basis[j] * bp->vec[3]; | // *fp = basisu[i] * basis[j] * bp->vec[3]; | ||||
| sumdiv += *fp; | // sumdiv += *fp; | ||||
| } | // } | ||||
| else { | // else { | ||||
| *fp = basisu[i] * basis[j]; | // *fp = basisu[i] * basis[j]; | ||||
| } | // } | ||||
| } | // } | ||||
| } | // } | ||||
| if (ratcomp) { | // if (ratcomp) { | ||||
| fp = sum; | // fp = sum; | ||||
| for (j = jsta; j <= jen; j++) { | // for (j = jsta; j <= jen; j++) { | ||||
| for (i = istart; i <= iend; i++, fp++) { | // for (i = istart; i <= iend; i++, fp++) { | ||||
| *fp /= sumdiv; | // *fp /= sumdiv; | ||||
| } | // } | ||||
| } | // } | ||||
| } | // } | ||||
| zero_v3(in); | // zero_v3(in); | ||||
| /* one! (1.0) real point now */ | // /* one! (1.0) real point now */ | ||||
| fp = sum; | // fp = sum; | ||||
| for (j = jsta; j <= jen; j++) { | // for (j = jsta; j <= jen; j++) { | ||||
| if (j >= nu->pntsv) { | // if (j >= nu->pntsv) { | ||||
| jofs = (j - nu->pntsv); | // jofs = (j - nu->pntsv); | ||||
| } | // } | ||||
| else { | // else { | ||||
| jofs = j; | // jofs = j; | ||||
| } | // } | ||||
| bp = nu->bp + nu->pntsu * jofs + istart - 1; | // bp = nu->bp + nu->pntsu * jofs + istart - 1; | ||||
| for (i = istart; i <= iend; i++, fp++) { | // for (i = istart; i <= iend; i++, fp++) { | ||||
| if (i >= nu->pntsu) { | // if (i >= nu->pntsu) { | ||||
| iofs = i - nu->pntsu; | // iofs = i - nu->pntsu; | ||||
| bp = nu->bp + nu->pntsu * jofs + iofs; | // bp = nu->bp + nu->pntsu * jofs + iofs; | ||||
| } | // } | ||||
| else { | // else { | ||||
| bp++; | // bp++; | ||||
| } | // } | ||||
| if (*fp != 0.0f) { | // if (*fp != 0.0f) { | ||||
| madd_v3_v3fl(in, bp->vec, *fp); | // madd_v3_v3fl(in, bp->vec, *fp); | ||||
| } | // } | ||||
| } | // } | ||||
| } | // } | ||||
| in += 3; | // in += 3; | ||||
| basis += KNOTSV(nu); | // basis += KNOTSV(nu); | ||||
| } | // } | ||||
| u += ustep; | // u += ustep; | ||||
| if (rowstride != 0) { | // if (rowstride != 0) { | ||||
| in = (float *)(((unsigned char *)in) + (rowstride - 3 * totv * sizeof(*in))); | // in = (float *)(((unsigned char *)in) + (rowstride - 3 * totv * sizeof(*in))); | ||||
| } | // } | ||||
| } | // } | ||||
| /* free */ | // /* free */ | ||||
| MEM_freeN(sum); | // MEM_freeN(sum); | ||||
| MEM_freeN(basisu); | // MEM_freeN(basisu); | ||||
| MEM_freeN(basisv); | // MEM_freeN(basisv); | ||||
| MEM_freeN(jstart); | // MEM_freeN(jstart); | ||||
| MEM_freeN(jend); | // MEM_freeN(jend); | ||||
| } | // } | ||||
| /** | /** | ||||
| * \param coord_array: Has to be 3 * 4 * pntsu * resolu in size and zero-ed | * \param coord_array: Has to be 3 * 4 * pntsu * resolu in size and zero-ed | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| coord_fp = POINTER_OFFSET(coord_fp, stride); | coord_fp = (float *)POINTER_OFFSET(coord_fp, stride); | ||||
| if (tilt_fp) { | if (tilt_fp) { | ||||
| tilt_fp = POINTER_OFFSET(tilt_fp, stride); | tilt_fp = (float *)POINTER_OFFSET(tilt_fp, stride); | ||||
| } | } | ||||
| if (radius_fp) { | if (radius_fp) { | ||||
| radius_fp = POINTER_OFFSET(radius_fp, stride); | radius_fp = (float *)POINTER_OFFSET(radius_fp, stride); | ||||
| } | } | ||||
| if (weight_fp) { | if (weight_fp) { | ||||
| weight_fp = POINTER_OFFSET(weight_fp, stride); | weight_fp = (float *)POINTER_OFFSET(weight_fp, stride); | ||||
| } | } | ||||
| u += ustep; | u += ustep; | ||||
| Context not available. | |||||
| r_points_offset, | r_points_offset, | ||||
| (int)resolu, | (int)resolu, | ||||
| stride); | stride); | ||||
| r_points_offset = POINTER_OFFSET(r_points_offset, resolu_stride); | r_points_offset = (float *)POINTER_OFFSET(r_points_offset, resolu_stride); | ||||
| } | } | ||||
| if (is_cyclic) { | if (is_cyclic) { | ||||
| Context not available. | |||||
| r_points_offset, | r_points_offset, | ||||
| (int)resolu, | (int)resolu, | ||||
| stride); | stride); | ||||
| r_points_offset = POINTER_OFFSET(r_points_offset, resolu_stride); | r_points_offset = (float *)POINTER_OFFSET(r_points_offset, resolu_stride); | ||||
| if (use_cyclic_duplicate_endpoint) { | if (use_cyclic_duplicate_endpoint) { | ||||
| *r_points_offset = *r_points; | *r_points_offset = *r_points; | ||||
| r_points_offset = POINTER_OFFSET(r_points_offset, stride); | r_points_offset = (float *)POINTER_OFFSET(r_points_offset, stride); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| float *r_points_last = POINTER_OFFSET(r_points, bezt_array_last * resolu_stride); | float *r_points_last = (float *)POINTER_OFFSET(r_points, bezt_array_last * resolu_stride); | ||||
| *r_points_last = bezt_array[bezt_array_last].vec[1][axis]; | *r_points_last = bezt_array[bezt_array_last].vec[1][axis]; | ||||
| r_points_offset = POINTER_OFFSET(r_points_offset, stride); | r_points_offset = (float *)POINTER_OFFSET(r_points_offset, stride); | ||||
| } | } | ||||
| BLI_assert(POINTER_OFFSET(r_points, points_len * stride) == r_points_offset); | BLI_assert(POINTER_OFFSET(r_points, points_len * stride) == r_points_offset); | ||||
| Context not available. | |||||
| for (a = 0; a <= it; a++) { | for (a = 0; a <= it; a++) { | ||||
| *p = q0; | *p = q0; | ||||
| p = POINTER_OFFSET(p, stride); | p = (float *)POINTER_OFFSET(p, stride); | ||||
| q0 += q1; | q0 += q1; | ||||
| q1 += q2; | q1 += q2; | ||||
| q2 += q3; | q2 += q3; | ||||
| Context not available. | |||||
| for (a = 0; a <= it; a++) { | for (a = 0; a <= it; a++) { | ||||
| *p = q0; | *p = q0; | ||||
| p = POINTER_OFFSET(p, stride); | p = (float *)POINTER_OFFSET(p, stride); | ||||
| q0 += q1; | q0 += q1; | ||||
| q1 += q2; | q1 += q2; | ||||
| } | } | ||||
| Context not available. | |||||
| (-18.0f * t + 6.0f) * p2[i] + (6.0f * t) * p3[i]; | (-18.0f * t + 6.0f) * p2[i] + (6.0f * t) * p3[i]; | ||||
| } | } | ||||
| normalize_v3(p); | normalize_v3(p); | ||||
| p = POINTER_OFFSET(p, stride); | p = (float *)POINTER_OFFSET(p, stride); | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| float *fp, facx, facy, angle, dangle; | float *fp, facx, facy, angle, dangle; | ||||
| int nr, a; | int nr, a; | ||||
| cu = ob->data; | cu = (Curve *)ob->data; | ||||
| BLI_listbase_clear(disp); | BLI_listbase_clear(disp); | ||||
| /* if a font object is being edited, then do nothing */ | /* if a font object is being edited, then do nothing */ | ||||
| Context not available. | |||||
| return; | return; | ||||
| } | } | ||||
| bevcu = cu->bevobj->data; | bevcu = (Curve *)cu->bevobj->data; | ||||
| if (bevcu->ext1 == 0.0f && bevcu->ext2 == 0.0f) { | if (bevcu->ext1 == 0.0f && bevcu->ext2 == 0.0f) { | ||||
| ListBase bevdisp = {NULL, NULL}; | ListBase bevdisp = {NULL, NULL}; | ||||
| facx = cu->bevobj->scale[0]; | facx = cu->bevobj->scale[0]; | ||||
| facy = cu->bevobj->scale[1]; | facy = cu->bevobj->scale[1]; | ||||
| if (cu->bevobj->runtime.curve_cache) { | if (cu->bevobj->runtime.curve_cache) { | ||||
| dl = cu->bevobj->runtime.curve_cache->disp.first; | dl = (DispList *)cu->bevobj->runtime.curve_cache->disp.first; | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(cu->bevobj->runtime.curve_cache != NULL); | BLI_assert(cu->bevobj->runtime.curve_cache != NULL); | ||||
| Context not available. | |||||
| while (dl) { | while (dl) { | ||||
| if (ELEM(dl->type, DL_POLY, DL_SEGM)) { | if (ELEM(dl->type, DL_POLY, DL_SEGM)) { | ||||
| dlnew = MEM_mallocN(sizeof(DispList), "makebevelcurve1"); | dlnew = (DispList *)MEM_mallocN(sizeof(DispList), "makebevelcurve1"); | ||||
| *dlnew = *dl; | *dlnew = *dl; | ||||
| dlnew->verts = MEM_malloc_arrayN( | dlnew->verts = (float *)MEM_malloc_arrayN( | ||||
| dl->parts * dl->nr, 3 * sizeof(float), "makebevelcurve1"); | dl->parts * dl->nr, 3 * sizeof(float), "makebevelcurve1"); | ||||
| memcpy(dlnew->verts, dl->verts, 3 * sizeof(float) * dl->parts * dl->nr); | memcpy(dlnew->verts, dl->verts, 3 * sizeof(float) * dl->parts * dl->nr); | ||||
| Context not available. | |||||
| /* pass */ | /* pass */ | ||||
| } | } | ||||
| else if (cu->ext2 == 0.0f) { | else if (cu->ext2 == 0.0f) { | ||||
| dl = MEM_callocN(sizeof(DispList), "makebevelcurve2"); | dl = (DispList *)MEM_callocN(sizeof(DispList), "makebevelcurve2"); | ||||
| dl->verts = MEM_malloc_arrayN(2, sizeof(float[3]), "makebevelcurve2"); | dl->verts = (float *)MEM_malloc_arrayN(2, sizeof(float[3]), "makebevelcurve2"); | ||||
| BLI_addtail(disp, dl); | BLI_addtail(disp, dl); | ||||
| dl->type = DL_SEGM; | dl->type = DL_SEGM; | ||||
| dl->parts = 1; | dl->parts = 1; | ||||
| Context not available. | |||||
| nr = 4 + 2 * cu->bevresol; | nr = 4 + 2 * cu->bevresol; | ||||
| dl = MEM_callocN(sizeof(DispList), "makebevelcurve p1"); | dl = (DispList *)MEM_callocN(sizeof(DispList), "makebevelcurve p1"); | ||||
| dl->verts = MEM_malloc_arrayN(nr, sizeof(float[3]), "makebevelcurve p1"); | dl->verts = (float *)MEM_malloc_arrayN(nr, sizeof(float[3]), "makebevelcurve p1"); | ||||
| BLI_addtail(disp, dl); | BLI_addtail(disp, dl); | ||||
| dl->type = DL_POLY; | dl->type = DL_POLY; | ||||
| dl->parts = 1; | dl->parts = 1; | ||||
| Context not available. | |||||
| } | } | ||||
| else { | else { | ||||
| /* The general case for nonzero extrusion or an incomplete loop. */ | /* The general case for nonzero extrusion or an incomplete loop. */ | ||||
| dl = MEM_callocN(sizeof(DispList), "makebevelcurve"); | dl = (DispList *)MEM_callocN(sizeof(DispList), "makebevelcurve"); | ||||
| if ((cu->flag & (CU_FRONT | CU_BACK)) == 0) { | if ((cu->flag & (CU_FRONT | CU_BACK)) == 0) { | ||||
| /* The full loop. */ | /* The full loop. */ | ||||
| nr = 4 * cu->bevresol + 6; | nr = 4 * cu->bevresol + 6; | ||||
| Context not available. | |||||
| dl->flag = (cu->flag & CU_FRONT) ? DL_FRONT_CURVE : DL_BACK_CURVE; | dl->flag = (cu->flag & CU_FRONT) ? DL_FRONT_CURVE : DL_BACK_CURVE; | ||||
| } | } | ||||
| dl->verts = MEM_malloc_arrayN(nr, sizeof(float[3]), "makebevelcurve"); | dl->verts = (float *)MEM_malloc_arrayN(nr, sizeof(float[3]), "makebevelcurve"); | ||||
| BLI_addtail(disp, dl); | BLI_addtail(disp, dl); | ||||
| /* Use a different type depending on whether the loop is complete or not. */ | /* Use a different type depending on whether the loop is complete or not. */ | ||||
| dl->type = ((cu->flag & (CU_FRONT | CU_BACK)) == 0) ? DL_POLY : DL_SEGM; | dl->type = ((cu->flag & (CU_FRONT | CU_BACK)) == 0) ? DL_POLY : DL_SEGM; | ||||
| Context not available. | |||||
| static int vergxcobev(const void *a1, const void *a2) | static int vergxcobev(const void *a1, const void *a2) | ||||
| { | { | ||||
| const struct BevelSort *x1 = a1, *x2 = a2; | const struct BevelSort *x1 = (BevelSort *)a1, *x2 = (BevelSort *)a2; | ||||
| if (x1->left > x2->left) { | if (x1->left > x2->left) { | ||||
| return 1; | return 1; | ||||
| Context not available. | |||||
| t[3] * next->tilt; | t[3] * next->tilt; | ||||
| } | } | ||||
| tilt_array = POINTER_OFFSET(tilt_array, stride); | tilt_array = (float *)POINTER_OFFSET(tilt_array, stride); | ||||
| } | } | ||||
| if (radius_array) { | if (radius_array) { | ||||
| Context not available. | |||||
| t[3] * next->radius; | t[3] * next->radius; | ||||
| } | } | ||||
| radius_array = POINTER_OFFSET(radius_array, stride); | radius_array = (float *)POINTER_OFFSET(radius_array, stride); | ||||
| } | } | ||||
| if (weight_array) { | if (weight_array) { | ||||
| Context not available. | |||||
| *weight_array = prevbezt->weight + (bezt->weight - prevbezt->weight) * | *weight_array = prevbezt->weight + (bezt->weight - prevbezt->weight) * | ||||
| (3.0f * fac * fac - 2.0f * fac * fac * fac); | (3.0f * fac * fac - 2.0f * fac * fac * fac); | ||||
| weight_array = POINTER_OFFSET(weight_array, stride); | weight_array = (float *)POINTER_OFFSET(weight_array, stride); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| void BKE_curve_bevelList_free(ListBase *bev) | void BKE_curve_bevelList_free(ListBase *bev) | ||||
| { | { | ||||
| BevList *bl, *blnext; | BevList *bl, *blnext; | ||||
| for (bl = bev->first; bl != NULL; bl = blnext) { | for (bl = (BevList *)bev->first; bl != NULL; bl = blnext) { | ||||
| blnext = bl->next; | blnext = bl->next; | ||||
| if (bl->seglen != NULL) { | if (bl->seglen != NULL) { | ||||
| MEM_freeN(bl->seglen); | MEM_freeN(bl->seglen); | ||||
| Context not available. | |||||
| */ | */ | ||||
| /* this function needs an object, because of tflag and upflag */ | /* this function needs an object, because of tflag and upflag */ | ||||
| Curve *cu = ob->data; | Curve *cu = (Curve *)ob->data; | ||||
| Nurb *nu; | Nurb *nu; | ||||
| BezTriple *bezt, *prevbezt; | BezTriple *bezt, *prevbezt; | ||||
| BPoint *bp; | BPoint *bp; | ||||
| Context not available. | |||||
| /* STEP 1: MAKE POLYS */ | /* STEP 1: MAKE POLYS */ | ||||
| BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev); | BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev); | ||||
| nu = nurbs->first; | nu = (Nurb *)nurbs->first; | ||||
| if (cu->editnurb && ob->type != OB_FONT) { | if (cu->editnurb && ob->type != OB_FONT) { | ||||
| is_editmode = 1; | is_editmode = 1; | ||||
| } | } | ||||
| Context not available. | |||||
| /* check we are a single point? also check we are not a surface and that the orderu is sane, | /* check we are a single point? also check we are not a surface and that the orderu is sane, | ||||
| * enforced in the UI but can go wrong possibly */ | * enforced in the UI but can go wrong possibly */ | ||||
| if (!BKE_nurb_check_valid_u(nu)) { | if (!BKE_nurb_check_valid_u(nu)) { | ||||
| bl = MEM_callocN(sizeof(BevList), "makeBevelList1"); | bl = (BevList *)MEM_callocN(sizeof(BevList), "makeBevelList1"); | ||||
| bl->bevpoints = MEM_calloc_arrayN(1, sizeof(BevPoint), "makeBevelPoints1"); | bl->bevpoints = (BevPoint *)MEM_calloc_arrayN(1, sizeof(BevPoint), "makeBevelPoints1"); | ||||
| BLI_addtail(bev, bl); | BLI_addtail(bev, bl); | ||||
| bl->nr = 0; | bl->nr = 0; | ||||
| bl->charidx = nu->charidx; | bl->charidx = nu->charidx; | ||||
| Context not available. | |||||
| if (nu->type == CU_POLY) { | if (nu->type == CU_POLY) { | ||||
| len = nu->pntsu; | len = nu->pntsu; | ||||
| bl = MEM_callocN(sizeof(BevList), "makeBevelList2"); | bl = (BevList *)MEM_callocN(sizeof(BevList), "makeBevelList2"); | ||||
| bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints2"); | bl->bevpoints = (BevPoint *)MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints2"); | ||||
| if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { | if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { | ||||
| bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList2_seglen"); | bl->seglen = (float *)MEM_malloc_arrayN( | ||||
| bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelList2_segbevcount"); | segcount, sizeof(float), "makeBevelList2_seglen"); | ||||
| bl->segbevcount = (int *)MEM_malloc_arrayN( | |||||
| segcount, sizeof(int), "makeBevelList2_segbevcount"); | |||||
| } | } | ||||
| BLI_addtail(bev, bl); | BLI_addtail(bev, bl); | ||||
| Context not available. | |||||
| /* in case last point is not cyclic */ | /* in case last point is not cyclic */ | ||||
| len = segcount * resolu + 1; | len = segcount * resolu + 1; | ||||
| bl = MEM_callocN(sizeof(BevList), "makeBevelBPoints"); | bl = (BevList *)MEM_callocN(sizeof(BevList), "makeBevelBPoints"); | ||||
| bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelBPointsPoints"); | bl->bevpoints = (BevPoint *)MEM_calloc_arrayN( | ||||
| len, sizeof(BevPoint), "makeBevelBPointsPoints"); | |||||
| if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { | if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { | ||||
| bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelBPoints_seglen"); | bl->seglen = (float *)MEM_malloc_arrayN( | ||||
| bl->segbevcount = MEM_malloc_arrayN( | segcount, sizeof(float), "makeBevelBPoints_seglen"); | ||||
| bl->segbevcount = (int *)MEM_malloc_arrayN( | |||||
| segcount, sizeof(int), "makeBevelBPoints_segbevcount"); | segcount, sizeof(int), "makeBevelBPoints_segbevcount"); | ||||
| } | } | ||||
| BLI_addtail(bev, bl); | BLI_addtail(bev, bl); | ||||
| Context not available. | |||||
| if (nu->pntsv == 1) { | if (nu->pntsv == 1) { | ||||
| len = (resolu * segcount); | len = (resolu * segcount); | ||||
| bl = MEM_callocN(sizeof(BevList), "makeBevelList3"); | bl = (BevList *)MEM_callocN(sizeof(BevList), "makeBevelList3"); | ||||
| bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints3"); | bl->bevpoints = (BevPoint *)MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints3"); | ||||
| if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { | if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { | ||||
| bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList3_seglen"); | bl->seglen = (float *)MEM_malloc_arrayN( | ||||
| bl->segbevcount = MEM_malloc_arrayN( | segcount, sizeof(float), "makeBevelList3_seglen"); | ||||
| bl->segbevcount = (int *)MEM_malloc_arrayN( | |||||
| segcount, sizeof(int), "makeBevelList3_segbevcount"); | segcount, sizeof(int), "makeBevelList3_segbevcount"); | ||||
| } | } | ||||
| BLI_addtail(bev, bl); | BLI_addtail(bev, bl); | ||||
| Context not available. | |||||
| } | } | ||||
| /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */ | /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */ | ||||
| bl = bev->first; | bl = (BevList *)bev->first; | ||||
| while (bl) { | while (bl) { | ||||
| if (bl->nr) { /* null bevel items come from single points */ | if (bl->nr) { /* null bevel items come from single points */ | ||||
| bool is_cyclic = bl->poly != -1; | bool is_cyclic = bl->poly != -1; | ||||
| Context not available. | |||||
| } | } | ||||
| bl = bl->next; | bl = bl->next; | ||||
| } | } | ||||
| bl = bev->first; | bl = (BevList *)bev->first; | ||||
| while (bl) { | while (bl) { | ||||
| blnext = bl->next; | blnext = bl->next; | ||||
| if (bl->nr && bl->dupe_nr) { | if (bl->nr && bl->dupe_nr) { | ||||
| nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */ | nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */ | ||||
| blnew = MEM_mallocN(sizeof(BevList), "makeBevelList4"); | blnew = (BevList *)MEM_callocN(sizeof(BevList), "makeBevelList4"); | ||||
| memcpy(blnew, bl, sizeof(BevList)); | memcpy(blnew, bl, sizeof(BevList)); | ||||
| blnew->bevpoints = MEM_calloc_arrayN(nr, sizeof(BevPoint), "makeBevelPoints4"); | blnew->bevpoints = (BevPoint *)MEM_calloc_arrayN(nr, sizeof(BevPoint), "makeBevelPoints4"); | ||||
| if (!blnew->bevpoints) { | if (!blnew->bevpoints) { | ||||
| MEM_freeN(blnew); | MEM_freeN(blnew); | ||||
| break; | break; | ||||
| Context not available. | |||||
| } | } | ||||
| /* STEP 3: POLYS COUNT AND AUTOHOLE */ | /* STEP 3: POLYS COUNT AND AUTOHOLE */ | ||||
| bl = bev->first; | bl = (BevList *)bev->first; | ||||
| poly = 0; | poly = 0; | ||||
| while (bl) { | while (bl) { | ||||
| if (bl->nr && bl->poly >= 0) { | if (bl->nr && bl->poly >= 0) { | ||||
| Context not available. | |||||
| /* find extreme left points, also test (turning) direction */ | /* find extreme left points, also test (turning) direction */ | ||||
| if (poly > 0) { | if (poly > 0) { | ||||
| sd = sortdata = MEM_malloc_arrayN(poly, sizeof(struct BevelSort), "makeBevelList5"); | sd = sortdata = (BevelSort *)MEM_malloc_arrayN( | ||||
| bl = bev->first; | poly, sizeof(struct BevelSort), "makeBevelList5"); | ||||
| bl = (BevList *)bev->first; | |||||
| while (bl) { | while (bl) { | ||||
| if (bl->poly > 0) { | if (bl->poly > 0) { | ||||
| BevPoint *bevp; | BevPoint *bevp; | ||||
| Context not available. | |||||
| /* STEP 4: 2D-COSINES or 3D ORIENTATION */ | /* STEP 4: 2D-COSINES or 3D ORIENTATION */ | ||||
| if ((cu->flag & CU_3D) == 0) { | if ((cu->flag & CU_3D) == 0) { | ||||
| /* 2D Curves */ | /* 2D Curves */ | ||||
| for (bl = bev->first; bl; bl = bl->next) { | for (bl = (BevList *)bev->first; bl; bl = bl->next) { | ||||
| if (bl->nr < 2) { | if (bl->nr < 2) { | ||||
| BevPoint *bevp = bl->bevpoints; | BevPoint *bevp = bl->bevpoints; | ||||
| unit_qt(bevp->quat); | unit_qt(bevp->quat); | ||||
| Context not available. | |||||
| } | } | ||||
| else { | else { | ||||
| /* 3D Curves */ | /* 3D Curves */ | ||||
| for (bl = bev->first; bl; bl = bl->next) { | for (bl = (BevList *)bev->first; bl; bl = bl->next) { | ||||
| if (bl->nr < 2) { | if (bl->nr < 2) { | ||||
| BevPoint *bevp = bl->bevpoints; | BevPoint *bevp = bl->bevpoints; | ||||
| unit_qt(bevp->quat); | unit_qt(bevp->quat); | ||||
| Context not available. | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| float *fptr = buffer; | float *fptr = (float *)buffer; | ||||
| for (int i = 0; i < num_floats; i++, fptr += count) { | for (int i = 0; i < num_floats; i++, fptr += count) { | ||||
| *floats[i] = fptr; | *floats[i] = fptr; | ||||
| Context not available. | |||||
| void BKE_nurb_handle_calc( | void BKE_nurb_handle_calc( | ||||
| BezTriple *bezt, BezTriple *prev, BezTriple *next, const bool is_fcurve, const char smoothing) | BezTriple *bezt, BezTriple *prev, BezTriple *next, const bool is_fcurve, const char smoothing) | ||||
| { | { | ||||
| calchandleNurb_intern(bezt, prev, next, SELECT, is_fcurve, false, smoothing); | calchandleNurb_intern(bezt, prev, next, (eBezTriple_Flag)SELECT, is_fcurve, false, smoothing); | ||||
| } | } | ||||
| /** | /** | ||||
| Context not available. | |||||
| const bool is_fcurve, | const bool is_fcurve, | ||||
| const char smoothing) | const char smoothing) | ||||
| { | { | ||||
| calchandleNurb_intern(bezt, prev, next, handle_sel_flag, is_fcurve, false, smoothing); | calchandleNurb_intern( | ||||
| bezt, prev, next, (eBezTriple_Flag)handle_sel_flag, is_fcurve, false, smoothing); | |||||
| } | } | ||||
| void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */ | void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */ | ||||
| { | { | ||||
| calchandlesNurb_intern(nu, SELECT, false); | calchandlesNurb_intern(nu, (eBezTriple_Flag)SELECT, false); | ||||
| } | } | ||||
| /** | /** | ||||
| Context not available. | |||||
| { | { | ||||
| Nurb *nu; | Nurb *nu; | ||||
| nu = editnurb->first; | nu = (Nurb *)editnurb->first; | ||||
| while (nu) { | while (nu) { | ||||
| BKE_nurb_handles_autocalc(nu, flag); | BKE_nurb_handles_autocalc(nu, flag); | ||||
| nu = nu->next; | nu = nu->next; | ||||
| Context not available. | |||||
| int a; | int a; | ||||
| if (ELEM(code, HD_AUTO, HD_VECT)) { | if (ELEM(code, HD_AUTO, HD_VECT)) { | ||||
| nu = editnurb->first; | nu = (Nurb *)editnurb->first; | ||||
| while (nu) { | while (nu) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| bezt = nu->bezt; | bezt = nu->bezt; | ||||
| Context not available. | |||||
| } | } | ||||
| else { | else { | ||||
| /* Toggle */ | /* Toggle */ | ||||
| for (nu = editnurb->first; nu; nu = nu->next) { | for (nu = (Nurb *)editnurb->first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| bezt = nu->bezt; | bezt = nu->bezt; | ||||
| a = nu->pntsu; | a = nu->pntsu; | ||||
| Context not available. | |||||
| } | } | ||||
| h_new = (h_new == HD_FREE) ? HD_ALIGN : HD_FREE; | h_new = (h_new == HD_FREE) ? HD_ALIGN : HD_FREE; | ||||
| } | } | ||||
| for (nu = editnurb->first; nu; nu = nu->next) { | for (nu = (Nurb *)editnurb->first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| bezt = nu->bezt; | bezt = nu->bezt; | ||||
| a = nu->pntsu; | a = nu->pntsu; | ||||
| Context not available. | |||||
| BezTriple *bezt; | BezTriple *bezt; | ||||
| int a; | int a; | ||||
| for (nu = editnurb->first; nu; nu = nu->next) { | for (nu = (Nurb *)editnurb->first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| bool changed = false; | bool changed = false; | ||||
| Context not available. | |||||
| BPoint *bp; | BPoint *bp; | ||||
| int a; | int a; | ||||
| for (nu = editnurb->first; nu; nu = nu->next) { | for (nu = (Nurb *)editnurb->first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| a = nu->pntsu; | a = nu->pntsu; | ||||
| bezt = nu->bezt; | bezt = nu->bezt; | ||||
| Context not available. | |||||
| /* and make in increasing order again */ | /* and make in increasing order again */ | ||||
| a = KNOTSU(nu); | a = KNOTSU(nu); | ||||
| fp1 = nu->knotsu; | fp1 = nu->knotsu; | ||||
| fp2 = tempf = MEM_malloc_arrayN(a, sizeof(float), "switchdirect"); | fp2 = tempf = (float *)MEM_malloc_arrayN(a, sizeof(float), "switchdirect"); | ||||
| a--; | a--; | ||||
| fp2[a] = fp1[a]; | fp2[a] = fp1[a]; | ||||
| while (a--) { | while (a--) { | ||||
| Context not available. | |||||
| void BKE_curve_nurbs_vert_coords_get(ListBase *lb, float (*vert_coords)[3], int vert_len) | void BKE_curve_nurbs_vert_coords_get(ListBase *lb, float (*vert_coords)[3], int vert_len) | ||||
| { | { | ||||
| float *co = vert_coords[0]; | float *co = vert_coords[0]; | ||||
| for (Nurb *nu = lb->first; nu; nu = nu->next) { | for (Nurb *nu = (Nurb *)lb->first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| BezTriple *bezt = nu->bezt; | BezTriple *bezt = nu->bezt; | ||||
| for (int i = 0; i < nu->pntsu; i++, bezt++) { | for (int i = 0; i < nu->pntsu; i++, bezt++) { | ||||
| Context not available. | |||||
| float (*BKE_curve_nurbs_vert_coords_alloc(ListBase *lb, int *r_vert_len))[3] | float (*BKE_curve_nurbs_vert_coords_alloc(ListBase *lb, int *r_vert_len))[3] | ||||
| { | { | ||||
| const int vert_len = BKE_nurbList_verts_count(lb); | const int vert_len = BKE_nurbList_verts_count(lb); | ||||
| float(*vert_coords)[3] = MEM_malloc_arrayN(vert_len, sizeof(*vert_coords), __func__); | float(*vert_coords)[3] = (float(*)[3])MEM_malloc_arrayN( | ||||
| vert_len, sizeof(*vert_coords), __func__); | |||||
| BKE_curve_nurbs_vert_coords_get(lb, vert_coords, vert_len); | BKE_curve_nurbs_vert_coords_get(lb, vert_coords, vert_len); | ||||
| *r_vert_len = vert_len; | *r_vert_len = vert_len; | ||||
| return vert_coords; | return vert_coords; | ||||
| Context not available. | |||||
| Nurb *nu; | Nurb *nu; | ||||
| int i; | int i; | ||||
| for (nu = lb->first; nu; nu = nu->next) { | for (nu = (Nurb *)lb->first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| BezTriple *bezt = nu->bezt; | BezTriple *bezt = nu->bezt; | ||||
| Context not available. | |||||
| if (constrain_2d) { | if (constrain_2d) { | ||||
| if (nu->flag & CU_2D) { | if (nu->flag & CU_2D) { | ||||
| BKE_nurb_test_2d(nu); | BKE_nurb_ensure_2d(nu); | ||||
| } | } | ||||
| } | } | ||||
| calchandlesNurb_intern(nu, SELECT, true); | calchandlesNurb_intern(nu, (eBezTriple_Flag)SELECT, true); | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| { | { | ||||
| const float *co = vert_coords[0]; | const float *co = vert_coords[0]; | ||||
| for (Nurb *nu = lb->first; nu; nu = nu->next) { | for (Nurb *nu = (Nurb *)lb->first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| BezTriple *bezt = nu->bezt; | BezTriple *bezt = nu->bezt; | ||||
| Context not available. | |||||
| if (constrain_2d) { | if (constrain_2d) { | ||||
| if (nu->flag & CU_2D) { | if (nu->flag & CU_2D) { | ||||
| BKE_nurb_test_2d(nu); | BKE_nurb_ensure_2d(nu); | ||||
| } | } | ||||
| } | } | ||||
| calchandlesNurb_intern(nu, SELECT, true); | calchandlesNurb_intern(nu, (eBezTriple_Flag)SELECT, true); | ||||
| } | } | ||||
| } | } | ||||
| float (*BKE_curve_nurbs_key_vert_coords_alloc(ListBase *lb, float *key, int *r_vert_len))[3] | float (*BKE_curve_nurbs_key_vert_coords_alloc(ListBase *lb, float *key, int *r_vert_len))[3] | ||||
| { | { | ||||
| int vert_len = BKE_nurbList_verts_count(lb); | int vert_len = BKE_nurbList_verts_count(lb); | ||||
| float(*cos)[3] = MEM_malloc_arrayN(vert_len, sizeof(*cos), __func__); | float(*cos)[3] = (float(*)[3])MEM_malloc_arrayN(vert_len, sizeof(*cos), __func__); | ||||
| float *co = cos[0]; | float *co = cos[0]; | ||||
| for (Nurb *nu = lb->first; nu; nu = nu->next) { | for (Nurb *nu = (Nurb *)lb->first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| BezTriple *bezt = nu->bezt; | BezTriple *bezt = nu->bezt; | ||||
| Context not available. | |||||
| Nurb *nu; | Nurb *nu; | ||||
| int i; | int i; | ||||
| for (nu = lb->first; nu; nu = nu->next) { | for (nu = (Nurb *)lb->first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| BezTriple *bezt = nu->bezt; | BezTriple *bezt = nu->bezt; | ||||
| Context not available. | |||||
| nu->orderu = max_ii(2, nu->pntsu); | nu->orderu = max_ii(2, nu->pntsu); | ||||
| changed = true; | changed = true; | ||||
| } | } | ||||
| if (nu->orderu > NURBS_MAX_ORDER) { | |||||
| nu->orderu = NURBS_MAX_ORDER; | |||||
| changed = true; | |||||
| } | |||||
| if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) { | if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) { | ||||
| CLAMP(nu->orderu, 3, 4); | CLAMP(nu->orderu, 3, 4); | ||||
| changed = true; | changed = true; | ||||
| Context not available. | |||||
| nu->orderv = max_ii(2, nu->pntsv); | nu->orderv = max_ii(2, nu->pntsv); | ||||
| changed = true; | changed = true; | ||||
| } | } | ||||
| if (nu->orderv > NURBS_MAX_ORDER) { | |||||
| nu->orderv = NURBS_MAX_ORDER; | |||||
| changed = true; | |||||
| } | |||||
| if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) { | if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) { | ||||
| CLAMP(nu->orderv, 3, 4); | CLAMP(nu->orderv, 3, 4); | ||||
| changed = true; | changed = true; | ||||
| Context not available. | |||||
| else if (nu->type == CU_BEZIER) { /* Bezier */ | else if (nu->type == CU_BEZIER) { /* Bezier */ | ||||
| if (type == CU_POLY || type == CU_NURBS) { | if (type == CU_POLY || type == CU_NURBS) { | ||||
| nr = use_handles ? (3 * nu->pntsu) : nu->pntsu; | nr = use_handles ? (3 * nu->pntsu) : nu->pntsu; | ||||
| nu->bp = MEM_calloc_arrayN(nr, sizeof(BPoint), "setsplinetype"); | nu->bp = (BPoint *)MEM_calloc_arrayN(nr, sizeof(BPoint), "setsplinetype"); | ||||
| a = nu->pntsu; | a = nu->pntsu; | ||||
| bezt = nu->bezt; | bezt = nu->bezt; | ||||
| bp = nu->bp; | bp = nu->bp; | ||||
| Context not available. | |||||
| return false; /* conversion impossible */ | return false; /* conversion impossible */ | ||||
| } | } | ||||
| else { | else { | ||||
| bezt = MEM_calloc_arrayN(nr, sizeof(BezTriple), "setsplinetype2"); | bezt =(BezTriple *) MEM_calloc_arrayN(nr, sizeof(BezTriple), "setsplinetype2"); | ||||
| nu->bezt = bezt; | nu->bezt = bezt; | ||||
| a = nr; | a = nr; | ||||
| bp = nu->bp; | bp = nu->bp; | ||||
| Context not available. | |||||
| Nurb *BKE_curve_nurb_active_get(Curve *cu) | Nurb *BKE_curve_nurb_active_get(Curve *cu) | ||||
| { | { | ||||
| ListBase *nurbs = BKE_curve_editNurbs_get(cu); | ListBase *nurbs = BKE_curve_editNurbs_get(cu); | ||||
| return BLI_findlink(nurbs, cu->actnu); | return (Nurb *)BLI_findlink(nurbs, cu->actnu); | ||||
| } | } | ||||
| /* Get active vert for curve */ | /* Get active vert for curve */ | ||||
| Context not available. | |||||
| if (cu->actvert != CU_ACT_NONE) { | if (cu->actvert != CU_ACT_NONE) { | ||||
| ListBase *nurbs = BKE_curve_editNurbs_get(cu); | ListBase *nurbs = BKE_curve_editNurbs_get(cu); | ||||
| nu = BLI_findlink(nurbs, cu->actnu); | nu = (Nurb *)BLI_findlink(nurbs, cu->actnu); | ||||
| if (nu) { | if (nu) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| Context not available. | |||||
| if (BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) { | if (BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| BezTriple *bezt = vert; | BezTriple *bezt = (BezTriple *)vert; | ||||
| if (BEZT_ISSEL_ANY(bezt) == 0) { | if (BEZT_ISSEL_ANY(bezt) == 0) { | ||||
| cu->actvert = CU_ACT_NONE; | cu->actvert = CU_ACT_NONE; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| BPoint *bp = vert; | BPoint *bp = (BPoint *)vert; | ||||
| if ((bp->f1 & SELECT) == 0) { | if ((bp->f1 & SELECT) == 0) { | ||||
| cu->actvert = CU_ACT_NONE; | cu->actvert = CU_ACT_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| use_radius = false; | use_radius = false; | ||||
| } | } | ||||
| /* Do bounding box based on splines. */ | /* Do bounding box based on splines. */ | ||||
| for (Nurb *nu = nurb_lb->first; nu; nu = nu->next) { | for (Nurb *nu = (Nurb *)nurb_lb->first; nu; nu = nu->next) { | ||||
| BKE_nurb_minmax(nu, use_radius, min, max); | BKE_nurb_minmax(nu, use_radius, min, max); | ||||
| } | } | ||||
| const bool result = (BLI_listbase_is_empty(nurb_lb) == false); | const bool result = (BLI_listbase_is_empty(nurb_lb) == false); | ||||
| Context not available. | |||||
| return result; | return result; | ||||
| } | } | ||||
| /* Fills cent with the median of the control points. Does not alter cu. */ | |||||
| bool BKE_curve_center_median(Curve *cu, float cent[3]) | bool BKE_curve_center_median(Curve *cu, float cent[3]) | ||||
| { | { | ||||
| ListBase *nurb_lb = BKE_curve_nurbs_get(cu); | ListBase *nurb_lb = BKE_curve_nurbs_get(cu); | ||||
| Context not available. | |||||
| zero_v3(cent); | zero_v3(cent); | ||||
| for (nu = nurb_lb->first; nu; nu = nu->next) { | for (nu = (Nurb *)nurb_lb->first; nu; nu = nu->next) { | ||||
| int i; | int i; | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| Context not available. | |||||
| return (total != 0); | return (total != 0); | ||||
| } | } | ||||
| /* Fills cent with the center of the AABB. Does not alter cu. */ | |||||
| bool BKE_curve_center_bounds(Curve *cu, float cent[3]) | bool BKE_curve_center_bounds(Curve *cu, float cent[3]) | ||||
| { | { | ||||
| float min[3], max[3]; | float min[3], max[3]; | ||||
| Context not available. | |||||
| BezTriple *bezt; | BezTriple *bezt; | ||||
| int i; | int i; | ||||
| for (nu = cu->nurb.first; nu; nu = nu->next) { | for (nu = (Nurb *)cu->nurb.first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| i = nu->pntsu; | i = nu->pntsu; | ||||
| for (bezt = nu->bezt; i--; bezt++) { | for (bezt = nu->bezt; i--; bezt++) { | ||||
| Context not available. | |||||
| if (do_keys && cu->key) { | if (do_keys && cu->key) { | ||||
| KeyBlock *kb; | KeyBlock *kb; | ||||
| for (kb = cu->key->block.first; kb; kb = kb->next) { | for (kb = (KeyBlock *)cu->key->block.first; kb; kb = kb->next) { | ||||
| float *fp = kb->data; | float *fp = (float *)kb->data; | ||||
| int n = kb->totelem; | int n = kb->totelem; | ||||
| for (nu = cu->nurb.first; nu; nu = nu->next) { | for (nu = (Nurb *)cu->nurb.first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| for (i = nu->pntsu; i && (n -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0; i--) { | for (i = nu->pntsu; i && (n -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0; i--) { | ||||
| mul_m4_v3(mat, &fp[0]); | mul_m4_v3(mat, &fp[0]); | ||||
| Context not available. | |||||
| Nurb *nu; | Nurb *nu; | ||||
| int i; | int i; | ||||
| for (nu = nurb_lb->first; nu; nu = nu->next) { | for (nu = (Nurb *)nurb_lb->first; nu; nu = nu->next) { | ||||
| BezTriple *bezt; | BezTriple *bezt; | ||||
| BPoint *bp; | BPoint *bp; | ||||
| Context not available. | |||||
| if (do_keys && cu->key) { | if (do_keys && cu->key) { | ||||
| KeyBlock *kb; | KeyBlock *kb; | ||||
| for (kb = cu->key->block.first; kb; kb = kb->next) { | for (kb = (KeyBlock *)cu->key->block.first; kb; kb = kb->next) { | ||||
| float *fp = kb->data; | float *fp = (float *)kb->data; | ||||
| int n = kb->totelem; | int n = kb->totelem; | ||||
| for (nu = cu->nurb.first; nu; nu = nu->next) { | for (nu = (Nurb *)cu->nurb.first; nu; nu = nu->next) { | ||||
| if (nu->type == CU_BEZIER) { | if (nu->type == CU_BEZIER) { | ||||
| for (i = nu->pntsu; i && (n -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0; i--) { | for (i = nu->pntsu; i && (n -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0; i--) { | ||||
| add_v3_v3(&fp[0], offset); | add_v3_v3(&fp[0], offset); | ||||
| Context not available. | |||||
| else { | else { | ||||
| Nurb *nu; | Nurb *nu; | ||||
| for (nu = cu->nurb.first; nu; nu = nu->next) { | for (nu = (Nurb *)cu->nurb.first; nu; nu = nu->next) { | ||||
| if (nu->mat_nr && nu->mat_nr >= index) { | if (nu->mat_nr && nu->mat_nr >= index) { | ||||
| nu->mat_nr--; | nu->mat_nr--; | ||||
| } | } | ||||
| Context not available. | |||||
| else { | else { | ||||
| Nurb *nu; | Nurb *nu; | ||||
| for (nu = cu->nurb.first; nu; nu = nu->next) { | for (nu = (Nurb *)cu->nurb.first; nu; nu = nu->next) { | ||||
| if (nu->mat_nr == index) { | if (nu->mat_nr == index) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| Context not available. | |||||
| else { | else { | ||||
| Nurb *nu; | Nurb *nu; | ||||
| for (nu = cu->nurb.first; nu; nu = nu->next) { | for (nu = (Nurb *)cu->nurb.first; nu; nu = nu->next) { | ||||
| nu->mat_nr = 0; | nu->mat_nr = 0; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| else { | else { | ||||
| Nurb *nu; | Nurb *nu; | ||||
| const int max_idx = max_ii(0, cu->totcol - 1); | const int max_idx = max_ii(0, cu->totcol - 1); | ||||
| for (nu = cu->nurb.first; nu; nu = nu->next) { | for (nu = (Nurb *)cu->nurb.first; nu; nu = nu->next) { | ||||
| if (nu->mat_nr > max_idx) { | if (nu->mat_nr > max_idx) { | ||||
| nu->mat_nr = 0; | nu->mat_nr = 0; | ||||
| is_valid = false; | is_valid = false; | ||||
| Context not available. | |||||
| ListBase *nurbs = BKE_curve_editNurbs_get(cu); | ListBase *nurbs = BKE_curve_editNurbs_get(cu); | ||||
| if (nurbs) { | if (nurbs) { | ||||
| for (nu = nurbs->first; nu; nu = nu->next) { | for (nu = (Nurb *)nurbs->first; nu; nu = nu->next) { | ||||
| MAT_NR_REMAP(nu->mat_nr); | MAT_NR_REMAP(nu->mat_nr); | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| r_rect->ymin = r_rect->ymax - tb->h; | r_rect->ymin = r_rect->ymax - tb->h; | ||||
| } | } | ||||
| void BKE_nurbs_uvbounds(struct Nurb *nu, float *umin, float *umax, float *vmin, float *vmax) { | |||||
| *umin = nu->knotsu[0]; | |||||
| *umax = nu->knotsu[KNOTSU(nu)-1]; | |||||
| if (nu->pntsv==1) { /* Curve, does not have v breakpoints */ | |||||
| *vmin = *vmax = 0; | |||||
| } else { /* Surface, has full set of v breakpoints */ | |||||
| *vmin = nu->knotsv[0]; | |||||
| *vmax = nu->knotsv[KNOTSV(nu)-1]; | |||||
| } | |||||
| } | |||||
| void BKE_nurbs_domain(struct Nurb *nu, float *umin, float *umax, float *vmin, float *vmax) { | |||||
| int pu = nu->orderu-1; /* p{u,v} is the degree of the curve in the {u,v} direction */ | |||||
| int pv = nu->orderv-1; | |||||
| *umin = nu->knotsu[pu]; | |||||
| *umax = nu->knotsu[KNOTSU(nu)-pu-1]; | |||||
| if (nu->knotsv && nu->pntsv>1) { | |||||
| if (vmin) *vmin = nu->knotsv[pv]; | |||||
| if (vmax) *vmax = nu->knotsv[KNOTSV(nu)-pv-1]; | |||||
| } else { | |||||
| if (vmin) *vmin = 0; | |||||
| if (vmax) *vmax = 0; | |||||
| } | |||||
| } | |||||
| void BKE_nurbs_printknots(struct Nurb *nu) { | |||||
| int i,numknot; | |||||
| float umin, umax, vmin, vmax; | |||||
| printf("knotsu = {"); | |||||
| for (i=0,numknot=KNOTSU(nu); i<numknot; i++) { | |||||
| printf((i==numknot-1)?"%3f}\n":"%3f, ",nu->knotsu[i]); | |||||
| } | |||||
| printf("knotsv = {"); | |||||
| for (i=0,numknot=KNOTSV(nu); i<numknot; i++) { | |||||
| printf((i==numknot-1)?"%3f}\n":"%3f, ",nu->knotsv[i]); | |||||
| } | |||||
| BKE_nurbs_domain(nu, &umin, &umax, &vmin, &vmax); | |||||
| printf("domain = [%3f,%3f]x[%3f,%3f]\n",umin,umax,vmin,vmax); | |||||
| BKE_nurbs_uvbounds(nu, &umin, &umax, &vmin, &vmax); | |||||
| printf("uvbounds = [%3f,%3f]x[%3f,%3f]\n",umin,umax,vmin,vmax); | |||||
| } | |||||
| /* **** Depsgraph evaluation **** */ | /* **** Depsgraph evaluation **** */ | ||||
| void BKE_curve_eval_geometry(Depsgraph *depsgraph, Curve *curve) | void BKE_curve_eval_geometry(Depsgraph *depsgraph, Curve *curve) | ||||
| Context not available. | |||||
| BKE_curve_batch_cache_free_cb(cu); | BKE_curve_batch_cache_free_cb(cu); | ||||
| } | } | ||||
| } | } | ||||
| // float subj0[] = {0.512000,0.938000, 0.374000,0.950000, 0.248000,0.908000, 0.170000,0.866000, 0.092000,0.740000, 0.092000,0.602000, 0.092000,0.440000, 0.116000,0.260000, 0.254000,0.110000, 0.476000,0.074000, 0.746000,0.092000, 0.836000,0.206000, 0.848000,0.422000, 0.812000,0.644000, 0.716000,0.686000, 0.614000,0.734000, 0.488000,0.728000, 0.386000,0.710000, 0.260000,0.626000, 0.272000,0.476000, 0.350000,0.338000, 0.482000,0.278000, 0.632000,0.308000, 0.644000,0.404000, 0.638000,0.494000, 0.590000,0.572000, 0.494000,0.584000, 0.422000,0.518000, 0.458000,0.392000, 0.548000,0.398000, 0.506000,0.506000, 0.572000,0.506000, 0.596000,0.386000, 0.566000,0.338000, 0.470000,0.338000, 0.368000,0.434000, 0.374000,0.608000, 0.578000,0.656000, 0.680000,0.644000, 0.740000,0.554000, 0.782000,0.308000, 0.758000,0.224000, 0.548000,0.164000, 0.338000,0.224000, 0.212000,0.374000, 0.170000,0.626000, 0.236000,0.764000, 0.368000,0.824000, 0.524000,0.836000, 1.184000,0.848000}; int subj0_nv=50; | |||||
| // void BKE_nurb_compute_trimmed_UV_mesh(struct Nurb* nu) { | |||||
| // bool remap_coords = true; // Remove trimmed verts (only useful for meshgen) | |||||
| GridMesh *BKE_nurb_compute_trimmed_GridMesh(struct Nurb* nu) { | |||||
| // Figure out the domain | |||||
| // int totu=(nu->pntsu-nu->orderu+1)*nu->resolu, totv=(nu->pntsv-nu->orderv+1)*nu->resolv; | |||||
| float ustart,uend,vstart,vend; | |||||
| BKE_nurbs_domain(nu,&ustart,&uend,&vstart,&vend); | |||||
| int totu_knot = round(uend-ustart)*nu->resolu; | |||||
| int totv_knot = round(vend-vstart)*nu->resolv; | |||||
| int totu_geom = (nu->pntsu-1)*nu->resolu; | |||||
| int totv_geom = (nu->pntsv-1)*nu->resolv; | |||||
| int totu=totu_knot, totv=totv_knot; | |||||
| if (totu<2 || totv<2 || totu_knot>totu_geom || totv_knot>totv_geom) { | |||||
| printf("Nonsensical NURBS tessellation level. Using geometric fallback.\n"); | |||||
| totu = totu_geom; | |||||
| totv = totv_geom; | |||||
| } | |||||
| // Trim the uniform grid in 2D UV space | |||||
| GridMesh *gm = new GridMesh(); | |||||
| gm->set_ll_ur(ustart,vstart,uend,vend); | |||||
| gm->init_grid(totu,totv); | |||||
| // Trim | |||||
| // gm->begin_recording(); | |||||
| for (NurbTrim *nt=(NurbTrim*)nu->trims.first; nt; nt=nt->next) { | |||||
| float (*trim_uv_pts)[2]; | |||||
| int num_trimpts = BKE_nurbTrim_tess(nt, &trim_uv_pts); | |||||
| int trim_poly = gm->poly_new((float*)trim_uv_pts, num_trimpts*2); | |||||
| switch (nt->type) { | |||||
| case CU_TRIM_AND: | |||||
| gm->bool_AND(trim_poly); | |||||
| break; | |||||
| case CU_TRIM_SUB: | |||||
| gm->bool_SUB(trim_poly); | |||||
| break; | |||||
| default: | |||||
| fprintf(stderr,"WARNING: invalid trim type %i!\n",nt->type); | |||||
| gm->bool_SUB(trim_poly); | |||||
| } | |||||
| MEM_freeN(trim_uv_pts); | |||||
| } | |||||
| // static ThreadMutex *mutex = NULL; | |||||
| // if (!mutex) { | |||||
| // mutex = (ThreadMutex*)MEM_callocN(sizeof(ThreadMutex), "ThreadMutex"); | |||||
| // BLI_mutex_init(mutex); | |||||
| // } | |||||
| // BLI_mutex_lock(mutex); | |||||
| // gm->dump_recording(); | |||||
| // BLI_mutex_unlock(mutex); | |||||
| return gm; | |||||
| } | |||||
| void BKE_nurb_compute_trimmed_UV_mesh(struct Nurb* nu) { | |||||
| GridMesh *gm = BKE_nurb_compute_trimmed_GridMesh(nu); | |||||
| // Extract the results | |||||
| int totu=gm->nx, totv=gm->ny; | |||||
| std::map<int,int> *used_idxs; | |||||
| GridMeshCoord *coords = gm->coords; | |||||
| float *final_coords; | |||||
| int coords_len = (totu+1)*(totv+1)*2; | |||||
| used_idxs = new std::map<int,int>(); | |||||
| int idxs_len = 4 * 3*sizeof(int)*totu*totv; | |||||
| int *idxs = (int*)MEM_mallocN(sizeof(int)*idxs_len, "NURBS_tess_2.0"); | |||||
| int ii=0; // Index index | |||||
| #define TESS_MAX_POLY_VERTS 4096 | |||||
| float coords_tmp[TESS_MAX_POLY_VERTS][2]; | |||||
| int reindex_tmp[TESS_MAX_POLY_VERTS]; | |||||
| unsigned idx_tmp[TESS_MAX_POLY_VERTS][3]; | |||||
| std::vector<int> degenerate_polys; | |||||
| // Loop through every cell, triangulate its polys, push them onto idxs | |||||
| for (int j=0; j<totv; j++) { | |||||
| for (int i=0; i<totu; i++) { | |||||
| int cell = gm->poly_for_cell(i, j); | |||||
| GridMeshVert *v = &gm->v[0]; | |||||
| for (int poly=cell; poly; poly=v[poly].next_poly) { | |||||
| if (!v[poly].next) { | |||||
| continue; | |||||
| } | |||||
| if (v[poly].is_pristine) { | |||||
| int ll_gp = gm->gridpt_for_cell(i, j); | |||||
| if (ii+6>=idxs_len) { | |||||
| //printf("1Growing idxs %i to %i\n",idxs_len,idxs_len*2); | |||||
| idxs_len *= 2; | |||||
| idxs = (int*)MEM_reallocN_id(idxs, sizeof(int)*idxs_len, "NURBS_tess_2.1"); | |||||
| } | |||||
| int ll=ll_gp, lr=ll_gp+1, ur=ll_gp+(totu+1)+1, ul=ll_gp+(totu+1); | |||||
| idxs[ii++]=ll; idxs[ii++]=lr; idxs[ii++]=ur; | |||||
| idxs[ii++]=ur; idxs[ii++]=ul; idxs[ii++]=ll; | |||||
| (*used_idxs)[ll]=0; (*used_idxs)[lr]=0; | |||||
| (*used_idxs)[ul]=0; (*used_idxs)[ur]=0; | |||||
| } else { | |||||
| int num_verts=0; int vert=poly; | |||||
| do { | |||||
| int idx = v[vert].coord_idx; | |||||
| GridMeshCoord& crd = coords[idx]; | |||||
| coords_tmp[num_verts][0] = crd.x; | |||||
| coords_tmp[num_verts][1] = crd.y; | |||||
| reindex_tmp[num_verts] = idx; | |||||
| num_verts++; | |||||
| vert=v[vert].next; | |||||
| if (num_verts>=TESS_MAX_POLY_VERTS) { | |||||
| printf("WARNING: maximum tessellation polygon verts (%i) exceeded. %i<-%i->%i\n",TESS_MAX_POLY_VERTS,v[vert].prev,vert,v[vert].next); | |||||
| break; | |||||
| } | |||||
| } while (vert!=poly); | |||||
| BLI_polyfill_calc(coords_tmp, | |||||
| num_verts, | |||||
| 0, // tell polyfill to do concave check | |||||
| idx_tmp); | |||||
| if (ii+(num_verts-2)*3>=idxs_len) { | |||||
| int new_idxlen = idxs_len*2 + (num_verts-2)*3; | |||||
| //printf("2Growing idxs %i to %i\n",idxs_len,new_idxlen); | |||||
| idxs = (int*)MEM_reallocN_id(idxs, sizeof(int)*new_idxlen, "NURBS_tess_2.2"); | |||||
| idxs_len = new_idxlen; | |||||
| } | |||||
| for (int z=0; z<num_verts-2; z++) { | |||||
| int i1=reindex_tmp[idx_tmp[z][0]]; | |||||
| int i2=reindex_tmp[idx_tmp[z][1]]; | |||||
| int i3=reindex_tmp[idx_tmp[z][2]]; | |||||
| idxs[ii++]=i1; idxs[ii++]=i2; idxs[ii++]=i3; | |||||
| (*used_idxs)[i1]=0; | |||||
| (*used_idxs)[i2]=0; | |||||
| (*used_idxs)[i3]=0; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /* Remap Coords */ | |||||
| int num_used_idxs = int(used_idxs->size()); | |||||
| final_coords = (float*)MEM_mallocN(2*sizeof(float)*num_used_idxs, "NURBS_tess_2.3"); | |||||
| coords_len = num_used_idxs; | |||||
| int newidx=0; | |||||
| std::map<int,int>::iterator it=used_idxs->begin(),end=used_idxs->end(); | |||||
| for (; it!=end; it++) { | |||||
| int old_idx = it->first; | |||||
| final_coords[2*newidx+0] = gm->coords[old_idx].x; | |||||
| final_coords[2*newidx+1] = gm->coords[old_idx].y; | |||||
| it->second = newidx; | |||||
| newidx += 1; | |||||
| } | |||||
| // ii, the index index, points to the end of idxs, the index array | |||||
| for (int i=0; i<ii; i++) { | |||||
| idxs[i] = (*used_idxs)[idxs[i]]; | |||||
| } | |||||
| /* End remap coords */ | |||||
| nu->UV_verts_count = coords_len; | |||||
| nu->UV_tri_count = ii/3; | |||||
| if (nu->UV_verts) MEM_freeN(nu->UV_verts); | |||||
| nu->UV_verts = final_coords; | |||||
| if (nu->UV_idxs) MEM_freeN(nu->UV_idxs); | |||||
| nu->UV_idxs = idxs; | |||||
| delete gm; | |||||
| } | |||||
| void BKE_nurbs_cached_UV_mesh_clear(struct Nurb* nu, bool free_mem) { | |||||
| nu->UV_verts_count = nu->UV_tri_count = 0; | |||||
| if (free_mem) { | |||||
| if (nu->UV_verts) MEM_freeN(nu->UV_verts); | |||||
| if (nu->UV_idxs) MEM_freeN(nu->UV_idxs); | |||||
| } | |||||
| nu->UV_verts = NULL; | |||||
| nu->UV_idxs = NULL; | |||||
| } | |||||
| void BKE_nurb_make_displist(struct Nurb *nu, struct DispList *dl) { | |||||
| if (!nu->UV_verts) BKE_nurb_compute_trimmed_UV_mesh(nu); | |||||
| float (*coords)[3] = (float(*)[3])MEM_mallocN(sizeof(*coords)*nu->UV_verts_count, "NURBS_tess_3dpts_1"); | |||||
| float (*nors)[3] = (float(*)[3])MEM_mallocN(sizeof(*nors)*nu->UV_verts_count, "NURBS_tess_3dpts_2"); | |||||
| int (*idxs)[3] = (int(*)[3])MEM_mallocN(sizeof(*idxs)*nu->UV_tri_count, "NURBS_tess_3dpts_3"); | |||||
| memcpy(idxs, nu->UV_idxs, sizeof(*idxs)*nu->UV_tri_count); | |||||
| // Push trimmed UV mesh forward through the NURBS map | |||||
| BSplineCacheU cacheU; // Make repeated evals at same u coord efficient | |||||
| cacheU.u = 1.0; // First eval should always miss | |||||
| cacheU.iu=1; | |||||
| for (int coord=0; coord<nu->UV_verts_count; coord++) { | |||||
| float *uv_in = (float*)&nu->UV_verts[2*coord]; | |||||
| float *xyz_out = (float*)&coords[coord]; | |||||
| float *norm_out = (float*)&nors[coord]; | |||||
| BPoint out[3]; // { surf_pt, u_partial_deriv, v_partal_deriv } | |||||
| int cyclicu = ((nu->flagu & CU_NURB_CYCLIC) ? 1 : 0); | |||||
| int cyclicv = ((nu->flagv & CU_NURB_CYCLIC) && (nu->orderv > 3) ? 1 : 0); | |||||
| BKE_nurbs_surf_eval(uv_in[0], | |||||
| uv_in[1], | |||||
| cyclicu, | |||||
| cyclicv, | |||||
| nu->pntsu, nu->orderu, nu->knotsu, | |||||
| nu->pntsv, nu->orderv, nu->knotsv, | |||||
| nu->bp, 1, out, &cacheU); | |||||
| copy_v3_v3(xyz_out, out[0].vec); | |||||
| cross_v3_v3v3(norm_out, out[1].vec, out[2].vec); | |||||
| } | |||||
| dl->col = nu->mat_nr; | |||||
| dl->charidx = nu->charidx; | |||||
| dl->rt = nu->flag & ~CU_2D; | |||||
| dl->verts = (float*)coords; | |||||
| dl->index = (int*)idxs; | |||||
| dl->nors = (float*)nors; | |||||
| dl->type = DL_INDEX3; | |||||
| dl->parts = nu->UV_tri_count; | |||||
| dl->nr = nu->UV_verts_count; | |||||
| if (nu->flag&CU_SMOOTH) | |||||
| dl->rt |= CU_SMOOTH; | |||||
| } | |||||
| /* Helper for BKE_surf_to_mesh */ | |||||
| struct NurbsMeshInfo { | |||||
| /* Output from Pass 1 */ | |||||
| int num_vert, num_edge, num_loop, num_poly; | |||||
| GridMesh *gm; | |||||
| std::map<int,int> remap_vert; | |||||
| std::map<std::pair<int,int>,int> remap_edge; | |||||
| /* Input to Pass 2 */ | |||||
| int base_loopid; | |||||
| MVert *verts; | |||||
| MEdge *edges; | |||||
| MLoop *loops; | |||||
| MLoopUV *uvs; | |||||
| MPoly *polys; | |||||
| }; | |||||
| /* Helper for BKE_surf_to_mesh */ | |||||
| static void nurbs_meshinfo_pass_1(Nurb *nu, NurbsMeshInfo &nmi) { | |||||
| GridMesh *gm = BKE_nurb_compute_trimmed_GridMesh(nu); | |||||
| nmi.gm = gm; | |||||
| std::map<int,int> &remap_vert = nmi.remap_vert; | |||||
| std::map<std::pair<int,int>,int> &remap_edge = nmi.remap_edge; | |||||
| int vertid=0, edgeid=0, loopid=0, polyid=0; | |||||
| for (GridMeshIterator gmi=gm->begin(); !gmi.done(); gmi.next()) { | |||||
| int poly = gmi.poly; | |||||
| int vert=poly; do { | |||||
| int coordidx = gm->v[vert].coord_idx; | |||||
| std::map<int,int>::iterator crd = remap_vert.find(coordidx); | |||||
| if (crd==remap_vert.end()) { | |||||
| remap_vert[coordidx] = vertid++; | |||||
| } | |||||
| int nextvert = gm->v[vert].next; | |||||
| int c1=coordidx, c2=gm->v[nextvert].coord_idx; | |||||
| std::pair<int,int> thisedge = (c1<c2)? std::make_pair(c1,c2) : std::make_pair(c2,c1); | |||||
| std::map<std::pair<int,int>,int>::iterator edg = remap_edge.find(thisedge); | |||||
| if (edg==remap_edge.end()) { | |||||
| remap_edge[thisedge] = edgeid++; | |||||
| } | |||||
| loopid++; | |||||
| vert = nextvert; | |||||
| } while (vert!=poly); | |||||
| polyid++; | |||||
| } | |||||
| nmi.num_vert = vertid; | |||||
| nmi.num_edge = edgeid; | |||||
| nmi.num_loop = loopid; | |||||
| nmi.num_poly = polyid; | |||||
| } | |||||
| /* Helper for BKE_surf_to_mesh */ | |||||
| static void nurbs_meshinfo_pass_2(Nurb *nu, NurbsMeshInfo &nmi) { | |||||
| /* Cache some data we'll need for surface eval */ | |||||
| int pntsu=nu->pntsu, orderu=nu->orderu, pntsv=nu->pntsv, orderv=nu->orderv; | |||||
| float *U=nu->knotsu, *V=nu->knotsv; | |||||
| BPoint *bp=nu->bp; | |||||
| /* Fill the newly allocated storage */ | |||||
| int loopnum=0, polynum=0; | |||||
| for (GridMeshIterator gmi=nmi.gm->begin(); !gmi.done(); gmi.next()) { | |||||
| int poly = gmi.poly; | |||||
| int vert=poly; | |||||
| GridMeshVert *gmvert = &nmi.gm->v[vert]; | |||||
| int coordidx = gmvert->coord_idx; | |||||
| int remapped_vert_idx = nmi.remap_vert[coordidx]; | |||||
| int num_edge_in_poly=0, first_loop_of_poly=loopnum; | |||||
| /* Loop over each edge {vert,nextvert} in gmi.poly */ | |||||
| do { | |||||
| num_edge_in_poly++; | |||||
| int nextvert = gmvert->next; | |||||
| GridMeshVert *gmnextvert = &nmi.gm->v[nextvert]; | |||||
| int nextcoordidx = gmnextvert->coord_idx; | |||||
| int remapped_nextvert_idx = nmi.remap_vert[nextcoordidx]; | |||||
| /* Get pointers to the structures at this poly edge */ | |||||
| MVert *mesh_v = nmi.verts + remapped_vert_idx; | |||||
| GridMeshCoord *gmcoord = &nmi.gm->coords[coordidx]; | |||||
| int c1=coordidx, c2=nextcoordidx; | |||||
| std::pair<int,int> thisedge = (c1<c2)? std::make_pair(c1,c2) : std::make_pair(c2,c1); | |||||
| int remapped_edge_idx = nmi.remap_edge[thisedge]; | |||||
| MEdge *mesh_e = nmi.edges + remapped_edge_idx; | |||||
| MLoopUV *mesh_luv = nmi.uvs + (loopnum); | |||||
| MLoop *mesh_l = nmi.loops + (loopnum++); | |||||
| /* MVert (location, normal) */ | |||||
| BPoint surfpt[3]; // Coord, d/du, d/dv. The latter two are actually vectors. | |||||
| BKE_nurbs_surf_eval(gmcoord->x, | |||||
| gmcoord->y, | |||||
| ((nu->flagu & CU_NURB_CYCLIC) ? 1 : 0), | |||||
| ((nu->flagv & CU_NURB_CYCLIC) ? 1 : 0), | |||||
| pntsu,orderu,U, pntsv,orderv,V, | |||||
| bp, 1, surfpt); | |||||
| copy_v3_v3(mesh_v->co, surfpt[0].vec); | |||||
| float norm[3]; | |||||
| cross_v3_v3v3(norm, surfpt[1].vec, surfpt[2].vec); | |||||
| normalize_v3(norm); | |||||
| normal_float_to_short_v3(mesh_v->no, norm); | |||||
| /* MEdge, MLoop, MLoopUV */ | |||||
| mesh_e->v1 = remapped_vert_idx; | |||||
| mesh_e->v2 = remapped_nextvert_idx; | |||||
| mesh_l->v = remapped_vert_idx; | |||||
| mesh_l->e = remapped_edge_idx; | |||||
| mesh_luv->uv[0] = gmcoord->x; | |||||
| mesh_luv->uv[1] = gmcoord->y; | |||||
| vert = nextvert; | |||||
| gmvert = gmnextvert; | |||||
| remapped_vert_idx = remapped_nextvert_idx; | |||||
| coordidx = gmvert->coord_idx; | |||||
| } while (vert!=poly); | |||||
| MPoly *mesh_p = nmi.polys + (polynum++); | |||||
| mesh_p->loopstart = nmi.base_loopid + first_loop_of_poly; | |||||
| mesh_p->totloop = num_edge_in_poly; | |||||
| if (nu->flag&ME_SMOOTH) mesh_p->flag |= ME_SMOOTH; | |||||
| } | |||||
| } | |||||
| /* Transforms the surface object ob into a mesh representation. */ | |||||
| void BKE_surf_to_mesh(Main *bmain, Object *ob) | |||||
| { | |||||
| BLI_assert(ob->type == OB_SURF); | |||||
| Curve *cu = (Curve*)ob->data; | |||||
| BLI_assert(cu->type == OB_SURF); | |||||
| /* Pass 0: Count # of surfaces in the Curve object */ | |||||
| int num_nurbs=0; | |||||
| for (Nurb *nu = (Nurb*)cu->nurb.first; nu; nu=nu->next) num_nurbs++; | |||||
| std::vector<NurbsMeshInfo> NMIs(num_nurbs); | |||||
| /* Pass 1, for each NURBS surface, | |||||
| * a. invokes the GridMesh surface tessellator | |||||
| * b. counts the number of verts, edges, loops, and polys outputted by #1 | |||||
| * c. computes de-duplicated and compacted indices for verts and edges | |||||
| * d. stores the output in a NurbsMeshInfo object for subsequent passes | |||||
| * e. keeps track of totals because all surfs in the new mesh share vert/edge/etc buffers | |||||
| */ | |||||
| int totvert=0, totedge=0, totloop=0, totpoly=0; | |||||
| Nurb *nu = (Nurb*)cu->nurb.first; | |||||
| for (int i=0; i<num_nurbs; i++) { | |||||
| NurbsMeshInfo &nmi = NMIs[i]; | |||||
| nurbs_meshinfo_pass_1(nu, nmi); | |||||
| totvert += nmi.num_vert; | |||||
| totloop += nmi.num_loop; | |||||
| totedge += nmi.num_edge; | |||||
| totpoly += nmi.num_poly; | |||||
| nu=nu->next; | |||||
| } | |||||
| /* Allocate mesh storage now that we know total counts */ | |||||
| MVert *allvert = (MVert*)MEM_callocN(sizeof(MVert)*totvert+4, "NURBS2mesh_verts"); | |||||
| MEdge *alledge = (MEdge*)MEM_callocN(sizeof(MEdge)*totedge+4, "NURBS2mesh_edges"); | |||||
| MLoop *allloop = (MLoop*)MEM_callocN(sizeof(MLoop)*totloop+4, "NURBS2mesh_loop"); | |||||
| MPoly *allpoly = (MPoly*)MEM_callocN(sizeof(MPoly)*totpoly+4, "NURBS2mesh_poly"); | |||||
| MLoopUV *alluv = (MLoopUV*)MEM_callocN(sizeof(MLoopUV)*totloop+4, "NURBS2mesh_uv"); | |||||
| /* Pass 2 fills the newly allocated buffers */ | |||||
| nu = (Nurb*)cu->nurb.first; | |||||
| int filled_v=0, filled_e=0, filled_l=0, filled_p=0; | |||||
| int base_loopid=0; | |||||
| for (int i=0; i<num_nurbs; i++) { | |||||
| NurbsMeshInfo &nmi = NMIs[i]; | |||||
| nmi.verts = allvert+filled_v; | |||||
| nmi.edges = alledge+filled_e; | |||||
| nmi.loops = allloop+filled_l; | |||||
| nmi.polys = allpoly+filled_p; | |||||
| nmi.uvs = alluv+filled_l; | |||||
| nmi.base_loopid = base_loopid; | |||||
| nurbs_meshinfo_pass_2(nu, nmi); | |||||
| filled_v += nmi.num_vert; | |||||
| filled_e += nmi.num_edge; | |||||
| filled_l += nmi.num_loop; | |||||
| filled_p += nmi.num_poly; | |||||
| base_loopid += nmi.num_loop; | |||||
| nu=nu->next; | |||||
| } | |||||
| /* Put all the mesh data together in a Mesh object */ | |||||
| Mesh *me = BKE_mesh_add(bmain, "Mesh"); | |||||
| me->totvert=totvert; | |||||
| me->totedge=totedge; | |||||
| me->totloop=totloop; | |||||
| me->totpoly=totpoly; | |||||
| me->mvert = (MVert*)CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert); | |||||
| me->medge = (MEdge*)CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge); | |||||
| me->mloop = (MLoop*)CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop); | |||||
| me->mpoly = (MPoly*)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly); | |||||
| // me->mtpoly = (MTexPoly*)CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, "Orco"); | |||||
| me->mloopuv = (MLoopUV*)CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, "Orco"); | |||||
| /* Switch out the Curve datablock for a Mesh datablock */ | |||||
| BKE_mesh_texspace_calc(me); | |||||
| me->mat = cu->mat; cu->mat = NULL; | |||||
| BKE_object_free_curve_cache(ob); | |||||
| if (ob->data) { | |||||
| // BKE_id_free_us(bmain, ob->data); | |||||
| } | |||||
| ob->data = me; | |||||
| ob->type = OB_MESH; | |||||
| /* other users */ | |||||
| Object *ob1 = (Object*)bmain->objects.first; | |||||
| while (ob1) { | |||||
| if (ob1->data == cu) { | |||||
| ob1->type = OB_MESH; | |||||
| ob1->data = ob->data; | |||||
| id_us_plus((ID *)ob->data); | |||||
| } | |||||
| ob1 = (Object*)ob1->id.next; | |||||
| } | |||||
| } | |||||
| Context not available. | |||||