Merging r59136 through r59152 from trunk into soc-2013-depsgraph_mt
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 15 Aug 2013 08:23:16 +0000 (08:23 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 15 Aug 2013 08:23:16 +0000 (08:23 +0000)
1  2 
intern/guardedalloc/intern/mallocn.c
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenloader/intern/readfile.c

index 1d5ba91db9df3e0ee549efa6f9a3199e351dd2ce,06ae2ee864d5470ed0abb008a239ed916fc8a4ff..520df7880554df5eab1d85115800ee897345c9f3
@@@ -280,12 -280,6 +280,12 @@@ static void mem_lock_thread(void
  
  static void mem_unlock_thread(void)
  {
 +#ifdef DEBUG_THREADS
 +      if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
 +              assert(!"Thread lock was removed while allocation from thread is in progress");
 +      }
 +#endif
 +
        if (thread_unlock_callback)
                thread_unlock_callback();
  }
@@@ -1148,12 -1142,12 +1148,12 @@@ void *MEM_dupallocN(const void *vmemh
        return newp;
  }
  
- void *MEM_reallocN(void *vmemh, size_t len)
+ void *MEM_reallocN_id(void *vmemh, size_t len, const char *UNUSED(str))
  {
        return realloc(vmemh, len);
  }
  
- void *MEM_recallocN(void *vmemh, size_t len)
+ void *MEM_recallocN_id(void *vmemh, size_t len, const char *UNUSED(str))
  {
        void *newp = NULL;
  
index 6e78cf681e136cf6e57ff2ceed2ad6f8a95327c5,baa90e7a856752be9f9f7ad9d59336da011f4be4..1d48063e1439a8736130e2d797d8ec4e5269857d
@@@ -42,13 -42,6 +42,13 @@@ struct Main
  struct Nurb;
  struct Object;
  struct Scene;
 +struct Path;
 +
 +typedef struct CurveCache {
 +      ListBase disp;
 +      ListBase bev;
 +      struct Path *path;
 +} CurveCache;
  
  #define KNOTSU(nu)      ( (nu)->orderu + (nu)->pntsu + (((nu)->flagu & CU_NURB_CYCLIC) ? ((nu)->orderu - 1) : 0) )
  #define KNOTSV(nu)      ( (nu)->orderv + (nu)->pntsv + (((nu)->flagv & CU_NURB_CYCLIC) ? ((nu)->orderv - 1) : 0) )
@@@ -70,25 -63,22 +70,26 @@@ void BKE_curve_make_local(struct Curve 
  short BKE_curve_type_get(struct Curve *cu);
  void BKE_curve_type_test(struct Object *ob);
  void BKE_curve_curve_dimension_update(struct Curve *cu);
 +
 +void BKE_curve_boundbox_calc(struct Curve *cu, float r_loc[3], float r_size[3]);
 +struct BoundBox *BKE_curve_boundbox_get(struct Object *ob);
  void BKE_curve_texspace_calc(struct Curve *cu);
 +void BKE_curve_texspace_get(struct Curve *cu, float r_loc[3], float r_rot[3], float r_size[3]);
  
 -bool BKE_curve_minmax(struct Curve *cu, float min[3], float max[3]);
 +bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max[3]);
  bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
  bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
  void BKE_curve_translate(struct Curve *cu, float offset[3], int do_keys);
- void BKE_curve_delete_material_index(struct Curve *cu, int index);
+ void BKE_curve_material_index_remove(struct Curve *cu, int index);
+ void BKE_curve_material_index_clear(struct Curve *cu);
  
  ListBase *BKE_curve_nurbs_get(struct Curve *cu);
  
 -float (*BKE_curve_vertexCos_get(struct Curve *cu, struct ListBase *lb, int *numVerts_r))[3];
 -void BK_curve_vertexCos_apply(struct Curve *cu, struct ListBase *lb, float (*vertexCos)[3]);
 +float (*BKE_curve_nurbs_vertexCos_get(struct ListBase *lb, int *numVerts_r))[3];
 +void BK_curve_nurbs_vertexCos_apply(struct ListBase *lb, float (*vertexCos)[3]);
  
 -float (*BKE_curve_keyVertexCos_get(struct Curve *cu, struct ListBase *lb, float *key))[3];
 -void BKE_curve_keyVertexTilts_apply(struct Curve *cu, struct ListBase *lb, float *key);
 +float (*BKE_curve_nurbs_keyVertexCos_get(struct ListBase *lb, float *key))[3];
 +void BKE_curve_nurbs_keyVertexTilts_apply(struct ListBase *lb, float *key);
  
  void BKE_curve_editNurb_keyIndex_free(struct EditNurb *editnurb);
  void BKE_curve_editNurb_free(struct Curve *cu);
@@@ -97,7 -87,7 +98,7 @@@ struct ListBase *BKE_curve_editNurbs_ge
  float *BKE_curve_make_orco(struct Scene *scene, struct Object *ob, int *r_numVerts);
  float *BKE_curve_surf_make_orco(struct Object *ob);
  
 -void BKE_curve_bevelList_make(struct Object *ob);
 +void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render);
  void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob,  struct ListBase *disp, int forRender, int renderResolution);
  
  void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
@@@ -119,7 -109,7 +120,7 @@@ void BKE_nurb_free(struct Nurb *nu)
  struct Nurb *BKE_nurb_duplicate(struct Nurb *nu);
  
  void BKE_nurb_test2D(struct Nurb *nu);
 -void BKE_nurb_minmax(struct Nurb *nu, float min[3], float max[3]);
 +void BKE_nurb_minmax(struct Nurb *nu, bool use_radius, float min[3], float max[3]);
  
  void BKE_nurb_makeFaces(struct Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv);
  void BKE_nurb_makeCurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride);
index d677a6b07e47452984c68d317479faf2f4fb9cc5,801ed4f00a58b5ae269671d3e8681dd6cb3aea42..4b98723b1b430355b2d402dbcf3a26c430a342dc
@@@ -145,6 -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);
                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);
  }
@@@ -224,6 -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;
@@@ -364,79 -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])
@@@ -625,34 -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++;
                }
                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++;
                }
        }
@@@ -1626,10 -1586,10 +1626,10 @@@ void BKE_curve_bevel_make(Scene *scene
                                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;
                                }
                        }
  
@@@ -2412,12 -2372,23 +2412,23 @@@ static void make_bevel_list_2D(BevList 
        /* note: bevp->dir and bevp->quat are not needed for beveling but are
         * used when making a path from a 2D curve, therefor they need to be set - Campbell */
  
-       BevPoint *bevp2 = (BevPoint *)(bl + 1);
-       BevPoint *bevp1 = bevp2 + (bl->nr - 1);
-       BevPoint *bevp0 = bevp1 - 1;
+       BevPoint *bevp0, *bevp1, *bevp2;
        int nr;
  
-       nr = bl->nr;
+       if (bl->poly != -1) {
+               bevp2 = (BevPoint *)(bl + 1);
+               bevp1 = bevp2 + (bl->nr - 1);
+               bevp0 = bevp1 - 1;
+               nr = bl->nr;
+       }
+       else {
+               bevp0 = (BevPoint *)(bl + 1);
+               bevp1 = bevp0 + 1;
+               bevp2 = bevp1 + 1;
+               nr = bl->nr - 2;
+       }
        while (nr--) {
                const float x1 = bevp1->vec[0] - bevp0->vec[0];
                const float x2 = bevp1->vec[0] - bevp2->vec[0];
  
        /* correct non-cyclic cases */
        if (bl->poly == -1) {
-               BevPoint *bevp = (BevPoint *)(bl + 1);
-               bevp1 = bevp + 1;
-               bevp->sina = bevp1->sina;
-               bevp->cosa = bevp1->cosa;
+               BevPoint *bevp;
+               float angle;
+               /* first */
+               bevp = (BevPoint *)(bl + 1);
+               angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0;
+               bevp->sina = sinf(angle);
+               bevp->cosa = cosf(angle);
+               vec_to_quat(bevp->quat, bevp->dir, 5, 1);
+               /* last */
                bevp = (BevPoint *)(bl + 1);
                bevp += (bl->nr - 1);
-               bevp1 = bevp - 1;
-               bevp->sina = bevp1->sina;
-               bevp->cosa = bevp1->cosa;
+               angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0;
+               bevp->sina = sinf(angle);
+               bevp->cosa = cosf(angle);
+               vec_to_quat(bevp->quat, bevp->dir, 5, 1);
        }
  }
  
@@@ -2468,7 -2447,7 +2487,7 @@@ static void bevlist_firstlast_direction
        }
  }
  
 -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
        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) {
                
                 * 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;
                        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;
                                /* 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;
                                        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;
        }
  
        /* 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;
                }
                bl = bl->next;
        }
 -      bl = cu->bev.first;
 +      bl = bev->first;
        while (bl) {
                blnext = bl->next;
                if (bl->nr && bl->dupe_nr) {
                        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;
        }
  
        /* STEP 3: POLYS COUNT AND AUTOHOLE */
 -      bl = cu->bev.first;
 +      bl = bev->first;
        poly = 0;
        while (bl) {
                if (bl->nr && bl->poly >= 0) {
        /* 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) {
  
        /* 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 */
                        }
        }
        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 */
                        }
@@@ -3421,7 -3401,7 +3440,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");
        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;
        }
  }
  
 -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");
        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;
@@@ -3760,13 -3740,13 +3779,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);
  }
@@@ -3813,7 -3793,7 +3832,7 @@@ bool BKE_curve_center_bounds(Curve *cu
  {
        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;
        }
@@@ -3858,7 -3838,7 +3877,7 @@@ void BKE_curve_translate(Curve *cu, flo
        }
  }
  
- void BKE_curve_delete_material_index(Curve *cu, int index)
+ void BKE_curve_material_index_remove(Curve *cu, int index)
  {
        const int curvetype = BKE_curve_type_get(cu);
  
                for (nu = cu->nurb.first; nu; nu = nu->next) {
                        if (nu->mat_nr && nu->mat_nr >= index) {
                                nu->mat_nr--;
-                               if (curvetype == OB_CURVE)
+                               if (curvetype == OB_CURVE) {
                                        nu->charidx--;
+                               }
+                       }
+               }
+       }
+ }
+ void BKE_curve_material_index_clear(Curve *cu)
+ {
+       const int curvetype = BKE_curve_type_get(cu);
+       if (curvetype == OB_FONT) {
+               struct CharInfo *info = cu->strinfo;
+               int i;
+               for (i = cu->len - 1; i >= 0; i--, info++) {
+                       info->mat_nr = 0;
+               }
+       }
+       else {
+               Nurb *nu;
+               for (nu = cu->nurb.first; nu; nu = nu->next) {
+                       nu->mat_nr = 0;
+                       if (curvetype == OB_CURVE) {
+                               nu->charidx = 0;
                        }
                }
        }
index cb6308b70618cd771be089f6996c7e0133edf19a,c23b4ac4408bf79dd4409983c42bafa6fa41215b..f3dc64a72796f1fdc6051a40db87c3f954107919
@@@ -537,17 -537,17 +537,17 @@@ short *give_totcolp_id(ID *id
        return NULL;
  }
  
- static void data_delete_material_index_id(ID *id, short index)
+ static void material_data_index_remove_id(ID *id, short index)
  {
        /* ensure we don't try get materials from non-obdata */
        BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
  
        switch (GS(id->name)) {
                case ID_ME:
-                       BKE_mesh_delete_material_index((Mesh *)id, index);
+                       BKE_mesh_material_index_remove((Mesh *)id, index);
                        break;
                case ID_CU:
-                       BKE_curve_delete_material_index((Curve *)id, index);
+                       BKE_curve_material_index_remove((Curve *)id, index);
                        break;
                case ID_MB:
                        /* meta-elems don't have materials atm */
        }
  }
  
- void material_append_id(ID *id, Material *ma)
+ static void material_data_index_clear_id(ID *id)
+ {
+       /* ensure we don't try get materials from non-obdata */
+       BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
+       switch (GS(id->name)) {
+               case ID_ME:
+                       BKE_mesh_material_index_clear((Mesh *)id);
+                       break;
+               case ID_CU:
+                       BKE_curve_material_index_clear((Curve *)id);
+                       break;
+               case ID_MB:
+                       /* meta-elems don't have materials atm */
+                       break;
+       }
+ }
+ void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user)
+ {
+       Material ***matar = give_matarar_id(id);
+       short *totcolp = give_totcolp_id(id);
+       if (matar == NULL) {
+               return;
+       }
+       if (do_id_user && totcol < (*totcolp)) {
+               short i;
+               for (i = totcol; i < (*totcolp); i++) {
+                       id_us_min((ID *)(*matar)[i]);
+               }
+       }
+       if (totcol == 0) {
+               if (*totcolp) {
+                       MEM_freeN(*matar);
+                       *matar = NULL;
+               }
+       }
+       else {
+               *matar = MEM_recallocN(*matar, sizeof(void *) * totcol);
+       }
+       *totcolp = totcol;
+ }
+ void BKE_material_append_id(ID *id, Material *ma)
  {
        Material ***matar;
        if ((matar = give_matarar_id(id))) {
        }
  }
  
- Material *material_pop_id(ID *id, int index_i, bool remove_material_slot)
+ Material *BKE_material_pop_id(ID *id, int index_i, bool update_data)
  {
        short index = (short)index_i;
        Material *ret = NULL;
                                test_object_materials(G.main, id);
                        }
  
-                       if (remove_material_slot) {
+                       if (update_data) {
                                /* decrease mat_nr index */
-                               data_delete_material_index_id(id, index);
+                               material_data_index_remove_id(id, index);
                        }
                }
        }
        return ret;
  }
  
+ void BKE_material_clear_id(struct ID *id, bool update_data)
+ {
+       Material ***matar;
+       if ((matar = give_matarar_id(id))) {
+               short *totcol = give_totcolp_id(id);
+               *totcol = 0;
+               if (*matar) {
+                       MEM_freeN(*matar);
+                       *matar = NULL;
+               }
+               if (update_data) {
+                       /* decrease mat_nr index */
+                       material_data_index_clear_id(id);
+               }
+       }
+ }
  Material *give_current_material(Object *ob, short act)
  {
        Material ***matarar, *ma;
@@@ -672,11 -736,18 +736,18 @@@ Material *give_node_material(Material *
        return NULL;
  }
  
- void resize_object_material(Object *ob, const short totcol)
+ void BKE_material_resize_object(Object *ob, const short totcol, bool do_id_user)
  {
        Material **newmatar;
        char *newmatbits;
  
+       if (do_id_user && totcol < ob->totcol) {
+               short i;
+               for (i = totcol; i < ob->totcol; i++) {
+                       id_us_min((ID *)ob->mat[i]);
+               }
+       }
        if (totcol == 0) {
                if (ob->totcol) {
                        MEM_freeN(ob->mat);
                ob->mat = newmatar;
                ob->matbits = newmatbits;
        }
+       /* XXX, why not realloc on shrink? - campbell */
        ob->totcol = totcol;
        if (ob->totcol && ob->actcol == 0) ob->actcol = 1;
        if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
@@@ -714,7 -787,7 +787,7 @@@ void test_object_materials(Main *bmain
  
        for (ob = bmain->object.first; ob; ob = ob->id.next) {
                if (ob->data == id) {
-                       resize_object_material(ob, *totcol);
+                       BKE_material_resize_object(ob, *totcol, false);
                }
        }
  }
@@@ -1217,10 -1290,8 +1290,10 @@@ int object_remove_material_slot(Object 
  
        /* check indices from mesh */
        if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
-               data_delete_material_index_id((ID *)ob->data, actcol - 1);
+               material_data_index_remove_id((ID *)ob->data, actcol - 1);
 -              BKE_displist_free(&ob->disp);
 +              if (ob->curve_cache) {
 +                      BKE_displist_free(&ob->curve_cache->disp);
 +              }
        }
  
        return TRUE;
@@@ -1695,7 -1766,7 +1768,7 @@@ static short mesh_getmaterialnumber(Mes
  /* append material */
  static short mesh_addmaterial(Mesh *me, Material *ma)
  {
-       material_append_id(&me->id, NULL);
+       BKE_material_append_id(&me->id, NULL);
        me->mat[me->totcol - 1] = ma;
  
        id_us_plus(&ma->id);
@@@ -1834,7 -1905,7 +1907,7 @@@ static void convert_tfacematerial(Main 
                /* remove material from mesh */
                for (a = 0; a < me->totcol; ) {
                        if (me->mat[a] == ma) {
-                               material_pop_id(&me->id, a, true);
+                               BKE_material_pop_id(&me->id, a, true);
                        }
                        else {
                                a++;
index f1729b8e098c65ab8f94bdfbbeb83e17fbaa0fc1,0db1f92f70f86c168981672215faf370b1dc4fac..3b6040a2917860696b53c726a402450108b4d7b4
@@@ -657,8 -657,6 +657,8 @@@ void BKE_mesh_boundbox_calc(Mesh *me, f
        r_size[2] = (max[2] - min[2]) / 2.0f;
        
        BKE_boundbox_init_from_minmax(bb, min, max);
 +
 +      bb->flag &= ~BOUNDBOX_INVALID;
  }
  
  void BKE_mesh_texspace_calc(Mesh *me)
@@@ -688,16 -686,15 +688,16 @@@ BoundBox *BKE_mesh_boundbox_get(Object 
        if (ob->bb)
                return ob->bb;
  
 -      if (!me->bb)
 +      if (me->bb == NULL || (me->bb->flag & BOUNDBOX_INVALID)) {
                BKE_mesh_texspace_calc(me);
 +      }
  
        return me->bb;
  }
  
  void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_size[3])
  {
 -      if (!me->bb) {
 +      if (me->bb == NULL || (me->bb->flag & BOUNDBOX_INVALID)) {
                BKE_mesh_texspace_calc(me);
        }
  
@@@ -1310,13 -1307,7 +1310,13 @@@ int BKE_mesh_nurbs_to_mdata(Object *ob
                              MEdge **alledge, int *totedge, MLoop **allloop, MPoly **allpoly,
                              int *totloop, int *totpoly)
  {
 -      return BKE_mesh_nurbs_displist_to_mdata(ob, &ob->disp,
 +      ListBase disp = {NULL, NULL};
 +
 +      if (ob->curve_cache) {
 +              disp = ob->curve_cache->disp;
 +      }
 +
 +      return BKE_mesh_nurbs_displist_to_mdata(ob, &disp,
                                                allvert, totvert,
                                                alledge, totedge,
                                                allloop, allpoly, NULL,
@@@ -1662,13 -1653,8 +1662,13 @@@ void BKE_mesh_from_nurbs(Object *ob
  {
        Curve *cu = (Curve *) ob->data;
        bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
 +      ListBase disp = {NULL, NULL};
 +
 +      if (ob->curve_cache) {
 +              disp = ob->curve_cache->disp;
 +      }
  
 -      BKE_mesh_from_nurbs_displist(ob, &ob->disp, use_orco_uv);
 +      BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv);
  }
  
  typedef struct EdgeLink {
@@@ -1866,20 -1852,37 +1866,37 @@@ void BKE_mesh_to_curve(Scene *scene, Ob
        }
  }
  
- void BKE_mesh_delete_material_index(Mesh *me, short index)
+ void BKE_mesh_material_index_remove(Mesh *me, short index)
  {
+       MPoly *mp;
+       MFace *mf;
        int i;
  
-       for (i = 0; i < me->totpoly; i++) {
-               MPoly *mp = &((MPoly *) me->mpoly)[i];
-               if (mp->mat_nr && mp->mat_nr >= index)
+       for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) {
+               if (mp->mat_nr && mp->mat_nr >= index) {
                        mp->mat_nr--;
+               }
        }
-       
-       for (i = 0; i < me->totface; i++) {
-               MFace *mf = &((MFace *) me->mface)[i];
-               if (mf->mat_nr && mf->mat_nr >= index)
+       for (mf = me->mface, i = 0; i < me->totface; i++, mf++) {
+               if (mf->mat_nr && mf->mat_nr >= index) {
                        mf->mat_nr--;
+               }
+       }
+ }
+ void BKE_mesh_material_index_clear(Mesh *me)
+ {
+       MPoly *mp;
+       MFace *mf;
+       int i;
+       for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) {
+               mp->mat_nr = 0;
+       }
+       for (mf = me->mface, i = 0; i < me->totface; i++, mf++) {
+               mf->mat_nr = 0;
        }
  }
  
index 2c642403c077827891442fa5c264cccabe817ca1,22ab7e499736d74c86c498a262cf5ce4c33e7eac..f9d6c55a1329282e27e6e87a9421a82d5cf4d399
@@@ -3123,6 -3123,7 +3123,6 @@@ static void direct_link_mball(FileData 
        
        mb->disp.first = mb->disp.last = NULL;
        mb->editelems = NULL;
 -      mb->bb = NULL;
  /*    mb->edit_elems.first= mb->edit_elems.last= NULL;*/
        mb->lastelem = NULL;
  }
@@@ -3398,8 -3399,11 +3398,8 @@@ static void direct_link_curve(FileData 
                if (cu->wordspace == 0.0f) cu->wordspace = 1.0f;
        }
  
 -      cu->bev.first = cu->bev.last = NULL;
 -      cu->disp.first = cu->disp.last = NULL;
        cu->editnurb = NULL;
        cu->lastsel = NULL;
 -      cu->path = NULL;
        cu->editfont = NULL;
        
        for (nu = cu->nurb.first; nu; nu = nu->next) {
@@@ -4341,7 -4345,7 +4341,7 @@@ static void lib_link_object(FileData *f
                                /* Only expand so as not to loose any object materials that might be set. */
                                if (totcol_data && (*totcol_data > ob->totcol)) {
                                        /* printf("'%s' %d -> %d\n", ob->id.name, ob->totcol, *totcol_data); */
-                                       resize_object_material(ob, *totcol_data);
+                                       BKE_material_resize_object(ob, *totcol_data, false);
                                }
                        }
                        
@@@ -4825,6 -4829,8 +4825,6 @@@ static void direct_link_object(FileDat
                ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT);
        }
        
 -      ob->disp.first = ob->disp.last = NULL;
 -      
        ob->adt = newdataadr(fd, ob->adt);
        direct_link_animdata(fd, ob->adt);
        
        ob->gpulamp.first= ob->gpulamp.last = NULL;
        link_list(fd, &ob->pc_ids);
  
 +      /* Runtime curve data  */
 +      ob->curve_cache = NULL;
 +
        /* in case this value changes in future, clamp else we get undefined behavior */
        CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
  
@@@ -5524,7 -5527,6 +5524,7 @@@ static void direct_link_windowmanager(F
        wm->winactive = NULL;
        wm->initialized = 0;
        wm->op_undo_depth = 0;
 +      wm->is_interface_locked = 0;
  }
  
  static void lib_link_windowmanager(FileData *fd, Main *main)