Merging r58475 through r58700 from trunk into soc-2013-depsgraph_mt
[blender.git] / source / blender / blenkernel / intern / curve.c
index 43e5cc101a76e7065c8af4e2ef8fdce1b27863a3..838774a9d80d3de38be683b9cb6b225015e70a41 100644 (file)
@@ -145,8 +145,6 @@ void BKE_curve_editNurb_free(Curve *cu)
 void BKE_curve_free(Curve *cu)
 {
        BKE_nurbList_free(&cu->nurb);
-       BLI_freelistN(&cu->bev);
-       BKE_displist_free(&cu->disp);
        BKE_curve_editfont_free(cu);
 
        BKE_curve_editNurb_free(cu);
@@ -161,8 +159,6 @@ void BKE_curve_free(Curve *cu)
                MEM_freeN(cu->strinfo);
        if (cu->bb)
                MEM_freeN(cu->bb);
-       if (cu->path)
-               free_path(cu->path);
        if (cu->tb)
                MEM_freeN(cu->tb);
 }
@@ -228,10 +224,6 @@ Curve *BKE_curve_copy(Curve *cu)
        cun->key = BKE_key_copy(cu->key);
        if (cun->key) cun->key->from = (ID *)cun;
 
-       cun->disp.first = cun->disp.last = NULL;
-       cun->bev.first = cun->bev.last = NULL;
-       cun->path = NULL;
-
        cun->editnurb = NULL;
        cun->editfont = NULL;
        cun->selboxes = NULL;
@@ -372,60 +364,79 @@ void BKE_curve_type_test(Object *ob)
                BKE_curve_curve_dimension_update((Curve *)ob->data);
 }
 
-void BKE_curve_texspace_calc(Curve *cu)
+void BKE_curve_boundbox_calc(Curve *cu, float r_loc[3], float r_size[3])
 {
-       DispList *dl;
        BoundBox *bb;
-       float *fp, min[3], max[3];
-       int tot, do_it = FALSE;
+       float min[3], max[3];
+       float mloc[3], msize[3];
 
-       if (cu->bb == NULL)
-               cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
+       if (cu->bb == NULL) cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
        bb = cu->bb;
 
-       INIT_MINMAX(min, max);
-
-       dl = cu->disp.first;
-       while (dl) {
-               tot = ELEM(dl->type, DL_INDEX3, DL_INDEX4) ? dl->nr : dl->nr * dl->parts;
+       if (!r_loc) r_loc = mloc;
+       if (!r_size) r_size = msize;
 
-               if (tot) do_it = TRUE;
-               fp = dl->verts;
-               while (tot--) {
-                       minmax_v3v3_v3(min, max, fp);
-                       fp += 3;
-               }
-               dl = dl->next;
-       }
-
-       if (do_it == FALSE) {
+       INIT_MINMAX(min, max);
+       /* TODO(sergey): makecode aware of radius and bevel somehow.. */
+       if (!BKE_curve_minmax(cu, true, min, max)) {
                min[0] = min[1] = min[2] = -1.0f;
                max[0] = max[1] = max[2] = 1.0f;
        }
 
+       mid_v3_v3v3(r_loc, min, max);
+
+       r_size[0] = (max[0] - min[0]) / 2.0f;
+       r_size[1] = (max[1] - min[1]) / 2.0f;
+       r_size[2] = (max[2] - min[2]) / 2.0f;
+
        BKE_boundbox_init_from_minmax(bb, min, max);
 
-       if (cu->texflag & CU_AUTOSPACE) {
-               mid_v3_v3v3(cu->loc, min, max);
-               cu->size[0] = (max[0] - min[0]) / 2.0f;
-               cu->size[1] = (max[1] - min[1]) / 2.0f;
-               cu->size[2] = (max[2] - min[2]) / 2.0f;
+       bb->flag &= ~BOUNDBOX_INVALID;
+}
 
-               zero_v3(cu->rot);
+BoundBox *BKE_curve_boundbox_get(Object *ob)
+{
+       Curve *cu = ob->data;
 
-               if (cu->size[0] == 0.0f) cu->size[0] = 1.0f;
-               else if (cu->size[0] > 0.0f && cu->size[0] < 0.00001f) cu->size[0] = 0.00001f;
-               else if (cu->size[0] < 0.0f && cu->size[0] > -0.00001f) cu->size[0] = -0.00001f;
+       if (ob->bb)
+               return ob->bb;
 
-               if (cu->size[1] == 0.0f) cu->size[1] = 1.0f;
-               else if (cu->size[1] > 0.0f && cu->size[1] < 0.00001f) cu->size[1] = 0.00001f;
-               else if (cu->size[1] < 0.0f && cu->size[1] > -0.00001f) cu->size[1] = -0.00001f;
+       if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_INVALID)) {
+               BKE_curve_texspace_calc(cu);
+       }
+
+       return cu->bb;
+}
 
-               if (cu->size[2] == 0.0f) cu->size[2] = 1.0f;
-               else if (cu->size[2] > 0.0f && cu->size[2] < 0.00001f) cu->size[2] = 0.00001f;
-               else if (cu->size[2] < 0.0f && cu->size[2] > -0.00001f) cu->size[2] = -0.00001f;
+void BKE_curve_texspace_calc(Curve *cu)
+{
+       float loc[3], size[3];
+       int a;
 
+       BKE_curve_boundbox_calc(cu, loc, size);
+
+       if (cu->texflag & CU_AUTOSPACE) {
+               for (a = 0; a < 3; a++) {
+                       if (size[a] == 0.0f) size[a] = 1.0f;
+                       else if (size[a] > 0.0f && size[a] < 0.00001f) size[a] = 0.00001f;
+                       else if (size[a] < 0.0f && size[a] > -0.00001f) size[a] = -0.00001f;
+               }
+
+               copy_v3_v3(cu->loc, loc);
+               copy_v3_v3(cu->size, size);
+               zero_v3(cu->rot);
+       }
+}
+
+void BKE_curve_texspace_get(Curve *cu, float r_loc[3], float r_rot[3], float r_size[3])
+{
+       if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_INVALID)) {
+               BKE_curve_texspace_calc(cu);
        }
+
+       if (r_loc) copy_v3_v3(r_loc,  cu->loc);
+       if (r_rot) copy_v3_v3(r_rot,  cu->rot);
+       if (r_size) copy_v3_v3(r_size, cu->size);
 }
 
 int BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3])
@@ -614,18 +625,34 @@ void BKE_nurb_test2D(Nurb *nu)
        }
 }
 
-void BKE_nurb_minmax(Nurb *nu, float min[3], float max[3])
+/* if use_radius is truth, minmax will take points' radius into account,
+ * which will make boundbox closer to bevelled curve.
+ */
+void BKE_nurb_minmax(Nurb *nu, bool use_radius, float min[3], float max[3])
 {
        BezTriple *bezt;
        BPoint *bp;
        int a;
+       float point[3];
 
        if (nu->type == CU_BEZIER) {
                a = nu->pntsu;
                bezt = nu->bezt;
                while (a--) {
+                       if (use_radius) {
+                               float radius_vector[3];
+                               radius_vector[0] = radius_vector[1] = radius_vector[2] = bezt->radius;
+
+                               add_v3_v3v3(point, bezt->vec[1], radius_vector);
+                               minmax_v3v3_v3(min, max, point);
+
+                               sub_v3_v3v3(point, bezt->vec[1], radius_vector);
+                               minmax_v3v3_v3(min, max, point);
+                       }
+                       else {
+                               minmax_v3v3_v3(min, max, bezt->vec[1]);
+                       }
                        minmax_v3v3_v3(min, max, bezt->vec[0]);
-                       minmax_v3v3_v3(min, max, bezt->vec[1]);
                        minmax_v3v3_v3(min, max, bezt->vec[2]);
                        bezt++;
                }
@@ -634,7 +661,20 @@ void BKE_nurb_minmax(Nurb *nu, float min[3], float max[3])
                a = nu->pntsu * nu->pntsv;
                bp = nu->bp;
                while (a--) {
-                       minmax_v3v3_v3(min, max, bp->vec);
+                       if (nu->pntsv == 1 && use_radius) {
+                               float radius_vector[3];
+                               radius_vector[0] = radius_vector[1] = radius_vector[2] = bp->radius;
+
+                               add_v3_v3v3(point, bp->vec, radius_vector);
+                               minmax_v3v3_v3(min, max, point);
+
+                               sub_v3_v3v3(point, bp->vec, radius_vector);
+                               minmax_v3v3_v3(min, max, point);
+                       }
+                       else {
+                               /* Surfaces doesn't use bevel, so no need to take radius into account. */
+                               minmax_v3v3_v3(min, max, bp->vec);
+                       }
                        bp++;
                }
        }
@@ -1586,10 +1626,10 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, int forRende
                                dl = bevdisp.first;
                        }
                        else {
-                               dl = cu->bevobj->disp.first;
+                               dl = cu->bevobj->curve_cache ? cu->bevobj->curve_cache->disp.first : NULL;
                                if (dl == NULL) {
                                        BKE_displist_make_curveTypes(scene, cu->bevobj, 0);
-                                       dl = cu->bevobj->disp.first;
+                                       dl = cu->bevobj->curve_cache->disp.first;
                                }
                        }
 
@@ -2407,7 +2447,7 @@ static void make_bevel_list_2D(BevList *bl)
        }
 }
 
-void BKE_curve_bevelList_make(Object *ob)
+void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
 {
        /*
         * - convert all curves to polys, with indication of resol and flags for double-vertices
@@ -2426,24 +2466,23 @@ void BKE_curve_bevelList_make(Object *ob)
        int a, b, nr, poly, resolu = 0, len = 0;
        int do_tilt, do_radius, do_weight;
        int is_editmode = 0;
+       ListBase *bev;
 
        /* this function needs an object, because of tflag and upflag */
        cu = ob->data;
 
+       bev = &ob->curve_cache->bev;
+
        /* do we need to calculate the radius for each point? */
        /* do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 : 1; */
 
        /* STEP 1: MAKE POLYS  */
 
-       BLI_freelistN(&(cu->bev));
+       BLI_freelistN(&(ob->curve_cache->bev));
+       nu = nurbs->first;
        if (cu->editnurb && ob->type != OB_FONT) {
-               ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-               nu = nurbs->first;
                is_editmode = 1;
        }
-       else {
-               nu = cu->nurb.first;
-       }
 
        for (; nu; nu = nu->next) {
                
@@ -2459,12 +2498,12 @@ void BKE_curve_bevelList_make(Object *ob)
                 * enforced in the UI but can go wrong possibly */
                if (!BKE_nurb_check_valid_u(nu)) {
                        bl = MEM_callocN(sizeof(BevList) + 1 * sizeof(BevPoint), "makeBevelList1");
-                       BLI_addtail(&(cu->bev), bl);
+                       BLI_addtail(bev, bl);
                        bl->nr = 0;
                        bl->charidx = nu->charidx;
                }
                else {
-                       if (G.is_rendering && cu->resolu_ren != 0)
+                       if (for_render && cu->resolu_ren != 0)
                                resolu = cu->resolu_ren;
                        else
                                resolu = nu->resolu;
@@ -2472,7 +2511,7 @@ void BKE_curve_bevelList_make(Object *ob)
                        if (nu->type == CU_POLY) {
                                len = nu->pntsu;
                                bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2");
-                               BLI_addtail(&(cu->bev), bl);
+                               BLI_addtail(bev, bl);
 
                                bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
                                bl->nr = len;
@@ -2495,7 +2534,7 @@ void BKE_curve_bevelList_make(Object *ob)
                                /* in case last point is not cyclic */
                                len = resolu * (nu->pntsu + (nu->flagu & CU_NURB_CYCLIC) - 1) + 1;
                                bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints");
-                               BLI_addtail(&(cu->bev), bl);
+                               BLI_addtail(bev, bl);
 
                                bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
                                bl->charidx = nu->charidx;
@@ -2581,7 +2620,7 @@ void BKE_curve_bevelList_make(Object *ob)
                                        len = (resolu * SEGMENTSU(nu));
 
                                        bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3");
-                                       BLI_addtail(&(cu->bev), bl);
+                                       BLI_addtail(bev, bl);
                                        bl->nr = len;
                                        bl->dupe_nr = 0;
                                        bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
@@ -2599,7 +2638,7 @@ void BKE_curve_bevelList_make(Object *ob)
        }
 
        /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */
-       bl = cu->bev.first;
+       bl = bev->first;
        while (bl) {
                if (bl->nr) { /* null bevel items come from single points */
                        nr = bl->nr;
@@ -2621,7 +2660,7 @@ void BKE_curve_bevelList_make(Object *ob)
                }
                bl = bl->next;
        }
-       bl = cu->bev.first;
+       bl = bev->first;
        while (bl) {
                blnext = bl->next;
                if (bl->nr && bl->dupe_nr) {
@@ -2629,8 +2668,8 @@ void BKE_curve_bevelList_make(Object *ob)
                        blnew = MEM_mallocN(sizeof(BevList) + nr * sizeof(BevPoint), "makeBevelList4");
                        memcpy(blnew, bl, sizeof(BevList));
                        blnew->nr = 0;
-                       BLI_remlink(&(cu->bev), bl);
-                       BLI_insertlinkbefore(&(cu->bev), blnext, blnew);    /* to make sure bevlijst is tuned with nurblist */
+                       BLI_remlink(bev, bl);
+                       BLI_insertlinkbefore(bev, blnext, blnew);    /* to make sure bevlijst is tuned with nurblist */
                        bevp0 = (BevPoint *)(bl + 1);
                        bevp1 = (BevPoint *)(blnew + 1);
                        nr = bl->nr;
@@ -2649,7 +2688,7 @@ void BKE_curve_bevelList_make(Object *ob)
        }
 
        /* STEP 3: POLYS COUNT AND AUTOHOLE */
-       bl = cu->bev.first;
+       bl = bev->first;
        poly = 0;
        while (bl) {
                if (bl->nr && bl->poly >= 0) {
@@ -2663,7 +2702,7 @@ void BKE_curve_bevelList_make(Object *ob)
        /* find extreme left points, also test (turning) direction */
        if (poly > 0) {
                sd = sortdata = MEM_mallocN(sizeof(struct bevelsort) * poly, "makeBevelList5");
-               bl = cu->bev.first;
+               bl = bev->first;
                while (bl) {
                        if (bl->poly > 0) {
 
@@ -2743,7 +2782,7 @@ void BKE_curve_bevelList_make(Object *ob)
        /* STEP 4: 2D-COSINES or 3D ORIENTATION */
        if ((cu->flag & CU_3D) == 0) {
                /* 2D Curves */
-               for (bl = cu->bev.first; bl; bl = bl->next) {
+               for (bl = bev->first; bl; bl = bl->next) {
                        if (bl->nr < 2) {
                                /* do nothing */
                        }
@@ -2757,7 +2796,7 @@ void BKE_curve_bevelList_make(Object *ob)
        }
        else {
                /* 3D Curves */
-               for (bl = cu->bev.first; bl; bl = bl->next) {
+               for (bl = bev->first; bl; bl = bl->next) {
                        if (bl->nr < 2) {
                                /* do nothing */
                        }
@@ -3346,7 +3385,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
 }
 
 
-float (*BKE_curve_vertexCos_get(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r))[3]
+float (*BKE_curve_nurbs_vertexCos_get(ListBase *lb, int *numVerts_r))[3]
 {
        int i, numVerts = *numVerts_r = BKE_nurbList_verts_count(lb);
        float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "cu_vcos");
@@ -3375,7 +3414,7 @@ float (*BKE_curve_vertexCos_get(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r
        return cos;
 }
 
-void BK_curve_vertexCos_apply(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos)[3])
+void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3])
 {
        float *co = vertexCos[0];
        Nurb *nu;
@@ -3403,7 +3442,7 @@ void BK_curve_vertexCos_apply(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos
        }
 }
 
-float (*BKE_curve_keyVertexCos_get(Curve *UNUSED(cu), ListBase *lb, float *key))[3]
+float (*BKE_curve_nurbs_keyVertexCos_get(ListBase *lb, float *key))[3]
 {
        int i, numVerts = BKE_nurbList_verts_count(lb);
        float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "cu_vcos");
@@ -3434,7 +3473,7 @@ float (*BKE_curve_keyVertexCos_get(Curve *UNUSED(cu), ListBase *lb, float *key))
        return cos;
 }
 
-void BKE_curve_keyVertexTilts_apply(Curve *UNUSED(cu), ListBase *lb, float *key)
+void BKE_curve_nurbs_keyVertexTilts_apply(ListBase *lb, float *key)
 {
        Nurb *nu;
        int i;
@@ -3685,13 +3724,13 @@ ListBase *BKE_curve_nurbs_get(Curve *cu)
 
 
 /* basic vertex data functions */
-bool BKE_curve_minmax(Curve *cu, float min[3], float max[3])
+bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
 {
        ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
        Nurb *nu;
 
        for (nu = nurb_lb->first; nu; nu = nu->next)
-               BKE_nurb_minmax(nu, min, max);
+               BKE_nurb_minmax(nu, use_radius, min, max);
 
        return (nurb_lb->first != NULL);
 }
@@ -3738,7 +3777,7 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3])
 {
        float min[3], max[3];
        INIT_MINMAX(min, max);
-       if (BKE_curve_minmax(cu, min, max)) {
+       if (BKE_curve_minmax(cu, false, min, max)) {
                mid_v3_v3v3(cent, min, max);
                return true;
        }