Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Tue, 8 May 2018 17:09:35 +0000 (19:09 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 8 May 2018 17:15:58 +0000 (19:15 +0200)
1  2 
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/mesh_convert.c

index 83241d3c4c7fd25e1b79a26c62c1ee66ac9d8342,c2b2fc4f869715f87b8b98e39a702376bb2d907e..a64d35e09bd1b010d72c3c183d8ef880d4be6b27
@@@ -30,7 -30,6 +30,7 @@@ set(IN
        ../blenloader
        ../blentranslation
        ../depsgraph
 +      ../draw
        ../gpu
        ../ikplugin
        ../imbuf
@@@ -82,12 -81,12 +82,12 @@@ set(SR
        intern/boids.c
        intern/bpath.c
        intern/brush.c
 -      intern/bullet.c
        intern/bvhutils.c
        intern/cachefile.c
        intern/camera.c
        intern/cdderivedmesh.c
        intern/cloth.c
 +      intern/collection.c
        intern/collision.c
        intern/colorband.c
        intern/colortools.c
        intern/customdata_file.c
        intern/data_transfer.c
        intern/deform.c
 -      intern/depsgraph.c
        intern/displist.c
        intern/dynamicpaint.c
        intern/editderivedmesh.c
        intern/editlattice.c
        intern/editmesh.c
        intern/editmesh_bvh.c
 +      intern/editmesh_tangent.c
        intern/effect.c
        intern/fcurve.c
        intern/fluidsim.c
        intern/gpencil.c
        intern/group.c
        intern/icons.c
 +      intern/icons_rasterize.c
        intern/idcode.c
        intern/idprop.c
        intern/idprop_utils.c
        intern/lattice.c
        intern/library.c
        intern/library_idmap.c
 +      intern/library_override.c
        intern/library_query.c
        intern/library_remap.c
        intern/linestyle.c
        intern/mball.c
        intern/mball_tessellate.c
        intern/mesh.c
+       intern/mesh_convert.c
        intern/mesh_evaluate.c
        intern/mesh_mapping.c
 +      intern/mesh_merge.c
        intern/mesh_remap.c
 +      intern/mesh_runtime.c
 +      intern/mesh_tangent.c
        intern/mesh_validate.c
        intern/modifier.c
        intern/modifiers_bmesh.c
        intern/nla.c
        intern/node.c
        intern/object.c
 +      intern/object_facemap.c
        intern/object_deform.c
        intern/object_dupli.c
        intern/object_update.c
        intern/pbvh.c
        intern/pbvh_bmesh.c
        intern/pointcache.c
 -      intern/property.c
 +      intern/layer.c
 +      intern/layer_utils.c
 +      intern/lightprobe.c
        intern/report.c
        intern/rigidbody.c
 -      intern/sca.c
        intern/scene.c
        intern/screen.c
        intern/seqcache.c
        intern/seqmodifier.c
        intern/sequencer.c
        intern/shrinkwrap.c
 -      intern/sketch.c
        intern/smoke.c
        intern/softbody.c
        intern/sound.c
        intern/tracking_util.c
        intern/undo_system.c
        intern/unit.c
 +      intern/workspace.c
        intern/world.c
        intern/writeavi.c
        intern/writeframeserver.c
        BKE_boids.h
        BKE_bpath.h
        BKE_brush.h
 -      BKE_bullet.h
        BKE_bvhutils.h
        BKE_cachefile.h
        BKE_camera.h
        BKE_ccg.h
        BKE_cdderivedmesh.h
        BKE_cloth.h
 +      BKE_collection.h
        BKE_collision.h
        BKE_colorband.h
        BKE_colortools.h
        BKE_customdata_file.h
        BKE_data_transfer.h
        BKE_deform.h
 -      BKE_depsgraph.h
        BKE_displist.h
        BKE_dynamicpaint.h
        BKE_editlattice.h
        BKE_editmesh.h
        BKE_editmesh_bvh.h
 +      BKE_editmesh_tangent.h
        BKE_effect.h
        BKE_fcurve.h
        BKE_fluidsim.h
        BKE_lattice.h
        BKE_library.h
        BKE_library_idmap.h
 +      BKE_library_override.h
        BKE_library_query.h
        BKE_library_remap.h
        BKE_linestyle.h
        BKE_mesh.h
        BKE_mesh_mapping.h
        BKE_mesh_remap.h
 +      BKE_mesh_tangent.h
        BKE_modifier.h
        BKE_movieclip.h
        BKE_multires.h
        BKE_nla.h
        BKE_node.h
        BKE_object.h
 +      BKE_object_facemap.h
        BKE_object_deform.h
        BKE_ocean.h
        BKE_outliner_treehash.h
        BKE_particle.h
        BKE_pbvh.h
        BKE_pointcache.h
 -      BKE_property.h
 +      BKE_layer.h
 +      BKE_lightprobe.h
        BKE_report.h
        BKE_rigidbody.h
 -      BKE_sca.h
        BKE_scene.h
        BKE_screen.h
        BKE_sequencer.h
        BKE_shrinkwrap.h
 -      BKE_sketch.h
        BKE_smoke.h
        BKE_softbody.h
        BKE_sound.h
        BKE_tracking.h
        BKE_undo_system.h
        BKE_unit.h
 +      BKE_workspace.h
        BKE_world.h
        BKE_writeavi.h
        BKE_writeframeserver.h
  
 -      depsgraph_private.h
        nla_private.h
        tracking_private.h
        particle_private.h
@@@ -341,7 -332,7 +342,7 @@@ if(WIN32
  endif()
  
  if(WITH_AUDASPACE)
 -      add_definitions(${AUDASPACE_DEFINITIONS})
 +      add_definitions(-DWITH_AUDASPACE)
  
        list(APPEND INC_SYS
                ${AUDASPACE_C_INCLUDE_DIRS}
@@@ -429,10 -420,6 +430,10 @@@ if(WITH_PYTHON
        )
        add_definitions(-DWITH_PYTHON)
  
 +      if(WITH_PYTHON_SAFETY)
 +              add_definitions(-DWITH_PYTHON_SAFETY)
 +      endif()
 +
        if(WITH_PYTHON_SECURITY)
                add_definitions(-DWITH_PYTHON_SECURITY)
        endif()
@@@ -485,6 -472,18 +486,6 @@@ if(WITH_LZMA
        add_definitions(-DWITH_LZMA)
  endif()
  
 -if(WITH_GAMEENGINE)
 -      list(APPEND INC_SYS
 -              ../../../extern/recastnavigation
 -      )
 -      list(APPEND SRC
 -              intern/navmesh_conversion.c
 -              BKE_navmesh_conversion.h
 -      )
 -
 -      add_definitions(-DWITH_GAMEENGINE)
 -endif()
 -
  if(WITH_LIBMV)
        add_definitions(-DWITH_LIBMV)
  endif()
@@@ -537,4 -536,8 +538,4 @@@ endif(
  #     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
  #endif()
  
 -if(WITH_LEGACY_DEPSGRAPH)
 -      add_definitions(-DWITH_LEGACY_DEPSGRAPH)
 -endif()
 -
  blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}")
index 0879c3e028dd12c7c4cdd206e10c31a7f1c0ad0b,688700748ed35f3be405ff1b1387b4aaf8233ef6..cca51190d269c673bc438ed1c3758f052ac3fdef
  
  #include "MEM_guardedalloc.h"
  
- #include "DNA_scene_types.h"
- #include "DNA_material_types.h"
- #include "DNA_meta_types.h"
  #include "DNA_object_types.h"
  #include "DNA_key_types.h"
  #include "DNA_mesh_types.h"
- #include "DNA_curve_types.h"
  
  #include "BLI_utildefines.h"
  #include "BLI_math.h"
  #include "BLI_linklist.h"
- #include "BLI_listbase.h"
  #include "BLI_memarena.h"
  #include "BLI_edgehash.h"
  #include "BLI_string.h"
- #include "BLI_utildefines_stack.h"
  
  #include "BKE_animsys.h"
 +#include "BKE_idcode.h"
  #include "BKE_main.h"
  #include "BKE_DerivedMesh.h"
  #include "BKE_global.h"
  #include "BKE_mesh.h"
- #include "BKE_mesh_mapping.h"
- #include "BKE_displist.h"
  #include "BKE_library.h"
- #include "BKE_library_query.h"
- #include "BKE_library_remap.h"
  #include "BKE_material.h"
  #include "BKE_modifier.h"
  #include "BKE_multires.h"
- #include "BKE_key.h"
- #include "BKE_mball.h"
- /* these 2 are only used by conversion functions */
- #include "BKE_curve.h"
- /* -- */
 -#include "BKE_depsgraph.h"
  #include "BKE_object.h"
  #include "BKE_editmesh.h"
  
  #include "DEG_depsgraph.h"
- #include "DEG_depsgraph_query.h"
  
 +/* Define for cases when you want extra validation of mesh
 + * after certain modifications.
 + */
 +// #undef VALIDATE_MESH
 +
  enum {
        MESHCMP_DVERT_WEIGHTMISMATCH = 1,
        MESHCMP_DVERT_GROUPMISMATCH,
@@@ -130,7 -109,7 +114,7 @@@ static int customdata_compare(CustomDat
        
        for (i = 0; i < c1->totlayer; i++) {
                if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
 -                       CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
 +                       CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
                {
                        i1++;
                }
  
        for (i = 0; i < c2->totlayer; i++) {
                if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
 -                       CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
 +                       CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
                {
                        i2++;
                }
        i1 = 0; i2 = 0;
        for (i = 0; i < tot; i++) {
                while (i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
 -                                                CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
 +                                                CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
                {
                        i1++;
                        l1++;
                }
  
                while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
 -                                                CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
 +                                                CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
                {
                        i2++;
                        l2++;
@@@ -327,7 -306,7 +311,7 @@@ static void mesh_ensure_tessellation_cu
                 * Callers could also check but safer to do here - campbell */
        }
        else {
 -              const int tottex_original = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
 +              const int tottex_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
                const int totcol_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
  
                const int tottex_tessface = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
                {
                        BKE_mesh_tessface_clear(me);
  
 -                      CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface);
 +                      CustomData_from_bmeshpoly(&me->fdata, &me->ldata, me->totface);
  
                        /* TODO - add some --debug-mesh option */
                        if (G.debug & G_DEBUG) {
                                 * and check if there was any data to begin with, for now just print the warning with
                                 * some info to help troubleshoot whats going on - campbell */
                                printf("%s: warning! Tessellation uvs or vcol data got out of sync, "
 -                                     "had to reset!\n    CD_MTFACE: %d != CD_MTEXPOLY: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n",
 +                                     "had to reset!\n    CD_MTFACE: %d != CD_MLOOPUV: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n",
                                       __func__, tottex_tessface, tottex_original, totcol_tessface, totcol_original);
                        }
                }
@@@ -391,78 -370,6 +375,78 @@@ void BKE_mesh_ensure_skin_customdata(Me
        }
  }
  
 +bool BKE_mesh_ensure_edit_data(struct Mesh *me)
 +{
 +      if (me->runtime.edit_data != NULL) {
 +              return false;
 +      }
 +
 +      me->runtime.edit_data = MEM_callocN(sizeof(EditMeshData), "EditMeshData");
 +      return true;
 +}
 +
 +bool BKE_mesh_clear_edit_data(struct Mesh *me)
 +{
 +      if (me->runtime.edit_data == NULL) {
 +              return false;
 +      }
 +
 +      if (me->runtime.edit_data->polyCos != NULL)
 +              MEM_freeN((void *)me->runtime.edit_data->polyCos);
 +      if (me->runtime.edit_data->polyNos != NULL)
 +              MEM_freeN((void *)me->runtime.edit_data->polyNos);
 +      if (me->runtime.edit_data->vertexCos != NULL)
 +              MEM_freeN((void *)me->runtime.edit_data->vertexCos);
 +      if (me->runtime.edit_data->vertexNos != NULL)
 +              MEM_freeN((void *)me->runtime.edit_data->vertexNos);
 +
 +      MEM_SAFE_FREE(me->runtime.edit_data);
 +      return true;
 +}
 +
 +
 +bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me)
 +{
 +      BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL;
 +      bool changed = false;
 +      if (bm) {
 +              if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
 +                      BM_data_layer_add(bm, &bm->pdata, CD_FACEMAP);
 +                      changed = true;
 +              }
 +      }
 +      else {
 +              if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
 +                      CustomData_add_layer(&me->pdata,
 +                                                CD_FACEMAP,
 +                                                CD_DEFAULT,
 +                                                NULL,
 +                                                me->totpoly);
 +                      changed = true;
 +              }
 +      }
 +      return changed;
 +}
 +
 +bool BKE_mesh_clear_facemap_customdata(struct Mesh *me)
 +{
 +      BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL;
 +      bool changed = false;
 +      if (bm) {
 +              if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
 +                      BM_data_layer_free(bm, &bm->pdata, CD_FACEMAP);
 +                      changed = true;
 +              }
 +      }
 +      else {
 +              if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
 +                      CustomData_free_layers(&me->pdata, CD_FACEMAP, me->totpoly);
 +                      changed = true;
 +              }
 +      }
 +      return changed;
 +}
 +
  /* this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or
   * mloopcol and mcol) have the same relative active/render/clone/mask indices.
   *
   * versions of the mesh. - campbell*/
  static void mesh_update_linked_customdata(Mesh *me, const bool do_ensure_tess_cd)
  {
 -      if (me->edit_btmesh)
 -              BKE_editmesh_update_linked_customdata(me->edit_btmesh);
 -
        if (do_ensure_tess_cd) {
                mesh_ensure_tessellation_customdata(me);
        }
  
 -      CustomData_bmesh_update_active_layers(&me->fdata, &me->pdata, &me->ldata);
 +      CustomData_bmesh_update_active_layers(&me->fdata, &me->ldata);
  }
  
  void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd)
        me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
        me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
  
 -      me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY);
        me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
        me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
  }
@@@ -513,9 -424,6 +497,9 @@@ void BKE_mesh_free(Mesh *me
  {
        BKE_animdata_free(&me->id, false);
  
 +      BKE_mesh_batch_cache_free(me);
 +      BKE_mesh_clear_edit_data(me);
 +
        CustomData_free(&me->vdata, me->totvert);
        CustomData_free(&me->edata, me->totedge);
        CustomData_free(&me->fdata, me->totface);
@@@ -603,7 -511,6 +587,7 @@@ void BKE_mesh_copy_data(Main *bmain, Me
        BKE_mesh_update_customdata_pointers(me_dst, do_tessface);
  
        me_dst->edit_btmesh = NULL;
 +      me_dst->runtime.batch_cache = NULL;
  
        me_dst->mselect = MEM_dupallocN(me_dst->mselect);
        me_dst->bb = MEM_dupallocN(me_dst->bb);
        }
  }
  
 +Mesh *BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
 +{
 +      Mesh *mesh = BKE_libblock_alloc(
 +              NULL, ID_ME,
 +              BKE_idcode_to_name(ID_ME),
 +              LIB_ID_CREATE_NO_MAIN |
 +              LIB_ID_CREATE_NO_USER_REFCOUNT |
 +              LIB_ID_CREATE_NO_DEG_TAG);
 +      BKE_libblock_init_empty(&mesh->id);
 +
 +      /* don't use CustomData_reset(...); because we dont want to touch customdata */
 +      copy_vn_i(mesh->vdata.typemap, CD_NUMTYPES, -1);
 +      copy_vn_i(mesh->edata.typemap, CD_NUMTYPES, -1);
 +      copy_vn_i(mesh->fdata.typemap, CD_NUMTYPES, -1);
 +      copy_vn_i(mesh->ldata.typemap, CD_NUMTYPES, -1);
 +      copy_vn_i(mesh->pdata.typemap, CD_NUMTYPES, -1);
 +
 +      CustomData_add_layer(&mesh->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, verts_len);
 +      CustomData_add_layer(&mesh->edata, CD_ORIGINDEX, CD_CALLOC, NULL, edges_len);
 +      CustomData_add_layer(&mesh->fdata, CD_ORIGINDEX, CD_CALLOC, NULL, tessface_len);
 +      CustomData_add_layer(&mesh->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, polys_len);
 +
 +      CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, verts_len);
 +      CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, edges_len);
 +      CustomData_add_layer(&mesh->fdata, CD_MFACE, CD_CALLOC, NULL, tessface_len);
 +      CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, loops_len);
 +      CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, polys_len);
 +
 +      mesh->mvert = CustomData_get_layer(&mesh->vdata, CD_MVERT);
 +      mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);
 +      mesh->mface = CustomData_get_layer(&mesh->fdata, CD_MFACE);
 +      mesh->mloop = CustomData_get_layer(&mesh->ldata, CD_MLOOP);
 +      mesh->mpoly = CustomData_get_layer(&mesh->pdata, CD_MPOLY);
 +
 +      return mesh;
 +}
 +
 +static Mesh *mesh_new_nomain_from_template_ex(
 +        const Mesh *me_src,
 +        int verts_len, int edges_len, int tessface_len,
 +        int loops_len, int polys_len,
 +        CustomDataMask mask)
 +{
 +      const bool do_tessface = ((me_src->totface != 0) && (me_src->totpoly == 0)); /* only do tessface if we have no polys */
 +
 +      Mesh *me_dst = BKE_id_new_nomain(ID_ME, NULL);
 +
 +      me_dst->mat = MEM_dupallocN(me_src->mat);
 +      me_dst->mselect = MEM_dupallocN(me_dst->mselect);
 +
 +      me_dst->totvert = verts_len;
 +      me_dst->totedge = edges_len;
 +      me_dst->totloop = loops_len;
 +      me_dst->totpoly = polys_len;
 +
 +      CustomData_copy(&me_src->vdata, &me_dst->vdata, mask, CD_CALLOC, verts_len);
 +      CustomData_copy(&me_src->edata, &me_dst->edata, mask, CD_CALLOC, edges_len);
 +      CustomData_copy(&me_src->ldata, &me_dst->ldata, mask, CD_CALLOC, loops_len);
 +      CustomData_copy(&me_src->pdata, &me_dst->pdata, mask, CD_CALLOC, polys_len);
 +      if (do_tessface) {
 +              CustomData_copy(&me_src->fdata, &me_dst->fdata, mask, CD_CALLOC, tessface_len);
 +      }
 +      else {
 +              mesh_tessface_clear_intern(me_dst, false);
 +      }
 +
 +      BKE_mesh_update_customdata_pointers(me_dst, false);
 +
 +      if (!CustomData_get_layer(&me_dst->vdata, CD_ORIGINDEX))
 +              CustomData_add_layer(&me_dst->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, verts_len);
 +      if (!CustomData_get_layer(&me_dst->edata, CD_ORIGINDEX))
 +              CustomData_add_layer(&me_dst->edata, CD_ORIGINDEX, CD_CALLOC, NULL, edges_len);
 +      if (!CustomData_get_layer(&me_dst->pdata, CD_ORIGINDEX))
 +              CustomData_add_layer(&me_dst->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, polys_len);
 +
 +      return me_dst;
 +}
 +
 +Mesh * BKE_mesh_new_nomain_from_template(
 +        const Mesh *me_src,
 +        int verts_len, int edges_len, int tessface_len,
 +        int loops_len, int polys_len)
 +{
 +      return mesh_new_nomain_from_template_ex(
 +              me_src,
 +              verts_len, edges_len, tessface_len,
 +              loops_len, polys_len,
 +              CD_MASK_EVERYTHING);
 +}
 +
  Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me)
  {
        Mesh *me_copy;
        return me_copy;
  }
  
 -BMesh *BKE_mesh_to_bmesh(
 -        Mesh *me, Object *ob,
 -        const bool add_key_index, const struct BMeshCreateParams *params)
 +BMesh *BKE_mesh_to_bmesh_ex(
 +        Mesh *me,
 +        const struct BMeshCreateParams *create_params,
 +        const struct BMeshFromMeshParams *convert_params)
  {
        BMesh *bm;
        const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
  
 -      bm = BM_mesh_create(&allocsize, params);
 -
 -      BM_mesh_bm_from_me(
 -              bm, me, (&(struct BMeshFromMeshParams){
 -                  .add_key_index = add_key_index, .use_shapekey = true, .active_shapekey = ob->shapenr,
 -              }));
 +      bm = BM_mesh_create(&allocsize, create_params);
 +      BM_mesh_bm_from_me(bm, me, convert_params);
  
        return bm;
  }
  
 +BMesh *BKE_mesh_to_bmesh(
 +        Mesh *me, Object *ob,
 +        const bool add_key_index, const struct BMeshCreateParams *params)
 +{
 +      return BKE_mesh_to_bmesh_ex(
 +              me, params,
 +              &(struct BMeshFromMeshParams){
 +                  .calc_face_normal = false,
 +                  .add_key_index = add_key_index,
 +                  .use_shapekey = true,
 +                  .active_shapekey = ob->shapenr,
 +              });
 +}
 +
 +Mesh *BKE_bmesh_to_mesh_nomain(BMesh *bm, const struct BMeshToMeshParams *params)
 +{
 +      Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL);
 +      BM_mesh_bm_to_me(bm, mesh, params);
 +      return mesh;
 +}
 +
  void BKE_mesh_make_local(Main *bmain, Mesh *me, const bool lib_local)
  {
        BKE_id_make_local_generic(bmain, &me->id, true, lib_local);
  }
  
 -bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int loop_index, const int face_index,
 -                                      const char *new_name, const bool do_tessface)
 +bool BKE_mesh_uv_cdlayer_rename_index(
 +        Mesh *me, const int loop_index, const int face_index,
 +        const char *new_name, const bool do_tessface)
  {
 -      CustomData *pdata, *ldata, *fdata;
 -      CustomDataLayer *cdlp, *cdlu, *cdlf;
 -      const int step = do_tessface ? 3 : 2;
 -      int i;
 +      CustomData *ldata, *fdata;
 +      CustomDataLayer *cdlu, *cdlf;
  
        if (me->edit_btmesh) {
 -              pdata = &me->edit_btmesh->bm->pdata;
                ldata = &me->edit_btmesh->bm->ldata;
                fdata = NULL;  /* No tessellated data in BMesh! */
        }
        else {
 -              pdata = &me->pdata;
                ldata = &me->ldata;
                fdata = &me->fdata;
        }
 -      cdlp = &pdata->layers[poly_index];
 +
        cdlu = &ldata->layers[loop_index];
 -      cdlf = fdata && do_tessface ? &fdata->layers[face_index] : NULL;
 +      cdlf = (face_index != -1) && fdata && do_tessface ? &fdata->layers[face_index] : NULL;
  
 -      if (cdlp->name != new_name) {
 +      if (cdlu->name != new_name) {
                /* Mesh validate passes a name from the CD layer as the new name,
                 * Avoid memcpy from self to self in this case.
                 */
 -              BLI_strncpy(cdlp->name, new_name, sizeof(cdlp->name));
 -              CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
 +              BLI_strncpy(cdlu->name, new_name, sizeof(cdlu->name));
 +              CustomData_set_layer_unique_name(ldata, loop_index);
        }
  
 -      /* Loop until we do have exactly the same name for all layers! */
 -      for (i = 1; !STREQ(cdlp->name, cdlu->name) || (cdlf && !STREQ(cdlp->name, cdlf->name)); i++) {
 -              switch (i % step) {
 -                      case 0:
 -                              BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name));
 -                              CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
 -                              break;
 -                      case 1:
 -                              BLI_strncpy(cdlu->name, cdlp->name, sizeof(cdlu->name));
 -                              CustomData_set_layer_unique_name(ldata, cdlu - ldata->layers);
 -                              break;
 -                      case 2:
 -                              if (cdlf) {
 -                                      BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name));
 -                                      CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers);
 -                              }
 -                              break;
 -              }
 +      if (cdlf == NULL) {
 +              return false;
        }
  
 +      BLI_strncpy(cdlf->name, cdlu->name, sizeof(cdlf->name));
 +      CustomData_set_layer_unique_name(fdata, face_index);
 +
        return true;
  }
  
  bool BKE_mesh_uv_cdlayer_rename(Mesh *me, const char *old_name, const char *new_name, bool do_tessface)
  {
 -      CustomData *pdata, *ldata, *fdata;
 +      CustomData *ldata, *fdata;
        if (me->edit_btmesh) {
 -              pdata = &me->edit_btmesh->bm->pdata;
                ldata = &me->edit_btmesh->bm->ldata;
                /* No tessellated data in BMesh! */
                fdata = NULL;
                do_tessface = false;
        }
        else {
 -              pdata = &me->pdata;
                ldata = &me->ldata;
                fdata = &me->fdata;
                do_tessface = (do_tessface && fdata->totlayer);
        }
  
        {
 -              const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY);
                const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV);
                const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1;
 -              int pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name);
                int lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name);
                int fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1;
  
                /* None of those cases should happen, in theory!
                 * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers!
                 */
 -              if (pidx == -1) {
 -                      if (lidx == -1) {
 -                              if (fidx == -1) {
 -                                      /* No layer found with this name! */
 -                                      return false;
 -                              }
 -                              else {
 -                                      lidx = fidx;
 -                              }
 -                      }
 -                      pidx = lidx;
 -              }
 -              else {
 -                      if (lidx == -1) {
 -                              lidx = pidx;
 +              if (lidx == -1) {
 +                      if (fidx == -1) {
 +                              /* No layer found with this name! */
 +                              return false;
                        }
 -                      if (fidx == -1 && do_tessface) {
 -                              fidx = pidx;
 +                      else {
 +                              lidx = fidx;
                        }
                }
 -#if 0
 -              /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */
 -              else if (pidx != lidx) {
 -                      lidx = pidx;
 -              }
 -#endif
  
                /* Go back to absolute indices! */
 -              pidx += pidx_start;
                lidx += lidx_start;
                if (fidx != -1)
                        fidx += fidx_start;
  
 -              return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface);
 +              return BKE_mesh_uv_cdlayer_rename_index(me, lidx, fidx, new_name, do_tessface);
        }
  }
  
@@@ -905,18 -742,6 +889,18 @@@ void BKE_mesh_texspace_get(Mesh *me, fl
        if (r_size) copy_v3_v3(r_size, me->size);
  }
  
 +void BKE_mesh_texspace_get_reference(Mesh *me, short **r_texflag,  float **r_loc, float **r_rot, float **r_size)
 +{
 +      if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
 +              BKE_mesh_texspace_calc(me);
 +      }
 +
 +      if (r_texflag != NULL) *r_texflag = &me->texflag;
 +      if (r_loc != NULL) *r_loc = me->loc;
 +      if (r_rot != NULL) *r_rot = me->rot;
 +      if (r_size != NULL) *r_size = me->size;
 +}
 +
  void BKE_mesh_texspace_copy_from_object(Mesh *me, Object *ob)
  {
        float *texloc, *texrot, *texsize;
@@@ -1076,779 -901,7 +1060,6 @@@ void BKE_mesh_assign_object(Object *ob
        test_object_modifiers(ob);
  }
  
- void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
- {
-       DispList *dl;
-       MVert *mvert;
-       MLoop *mloop, *allloop;
-       MPoly *mpoly;
-       const float *nors, *verts;
-       int a, *index;
-       
-       dl = lb->first;
-       if (dl == NULL) return;
-       if (dl->type == DL_INDEX4) {
-               mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, dl->nr);
-               allloop = mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, dl->parts * 4);
-               mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, dl->parts);
-               me->mvert = mvert;
-               me->mloop = mloop;
-               me->mpoly = mpoly;
-               me->totvert = dl->nr;
-               me->totpoly = dl->parts;
-               a = dl->nr;
-               nors = dl->nors;
-               verts = dl->verts;
-               while (a--) {
-                       copy_v3_v3(mvert->co, verts);
-                       normal_float_to_short_v3(mvert->no, nors);
-                       mvert++;
-                       nors += 3;
-                       verts += 3;
-               }
-               
-               a = dl->parts;
-               index = dl->index;
-               while (a--) {
-                       int count = index[2] != index[3] ? 4 : 3;
-                       mloop[0].v = index[0];
-                       mloop[1].v = index[1];
-                       mloop[2].v = index[2];
-                       if (count == 4)
-                               mloop[3].v = index[3];
-                       mpoly->totloop = count;
-                       mpoly->loopstart = (int)(mloop - allloop);
-                       mpoly->flag = ME_SMOOTH;
-                       mpoly++;
-                       mloop += count;
-                       me->totloop += count;
-                       index += 4;
-               }
-               BKE_mesh_update_customdata_pointers(me, true);
-               BKE_mesh_calc_normals(me);
-               BKE_mesh_calc_edges(me, true, false);
-       }
- }
- /**
-  * Specialized function to use when we _know_ existing edges don't overlap with poly edges.
-  */
- static void make_edges_mdata_extend(MEdge **r_alledge, int *r_totedge,
-                                     const MPoly *mpoly, MLoop *mloop,
-                                     const int totpoly)
- {
-       int totedge = *r_totedge;
-       int totedge_new;
-       EdgeHash *eh;
-       unsigned int eh_reserve;
-       const MPoly *mp;
-       int i;
-       eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly));
-       eh = BLI_edgehash_new_ex(__func__, eh_reserve);
-       for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
-               BKE_mesh_poly_edgehash_insert(eh, mp, mloop + mp->loopstart);
-       }
-       totedge_new = BLI_edgehash_len(eh);
- #ifdef DEBUG
-       /* ensure that theres no overlap! */
-       if (totedge_new) {
-               MEdge *medge = *r_alledge;
-               for (i = 0; i < totedge; i++, medge++) {
-                       BLI_assert(BLI_edgehash_haskey(eh, medge->v1, medge->v2) == false);
-               }
-       }
- #endif
-       if (totedge_new) {
-               EdgeHashIterator *ehi;
-               MEdge *medge;
-               unsigned int e_index = totedge;
-               *r_alledge = medge = (*r_alledge ? MEM_reallocN(*r_alledge, sizeof(MEdge) * (totedge + totedge_new)) :
-                                                  MEM_calloc_arrayN(totedge_new, sizeof(MEdge), __func__));
-               medge += totedge;
-               totedge += totedge_new;
-               /* --- */
-               for (ehi = BLI_edgehashIterator_new(eh);
-                    BLI_edgehashIterator_isDone(ehi) == false;
-                    BLI_edgehashIterator_step(ehi), ++medge, e_index++)
-               {
-                       BLI_edgehashIterator_getKey(ehi, &medge->v1, &medge->v2);
-                       BLI_edgehashIterator_setValue(ehi, SET_UINT_IN_POINTER(e_index));
-                       medge->crease = medge->bweight = 0;
-                       medge->flag = ME_EDGEDRAW | ME_EDGERENDER;
-               }
-               BLI_edgehashIterator_free(ehi);
-               *r_totedge = totedge;
-               for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
-                       MLoop *l = &mloop[mp->loopstart];
-                       MLoop *l_prev = (l + (mp->totloop - 1));
-                       int j;
-                       for (j = 0; j < mp->totloop; j++, l++) {
-                               /* lookup hashed edge index */
-                               l_prev->e = GET_UINT_FROM_POINTER(BLI_edgehash_lookup(eh, l_prev->v, l->v));
-                               l_prev = l;
-                       }
-               }
-       }
-       BLI_edgehash_free(eh, NULL);
- }
- /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
- /* return non-zero on error */
- int BKE_mesh_nurbs_to_mdata(
-         Object *ob, MVert **r_allvert, int *r_totvert,
-         MEdge **r_alledge, int *r_totedge, MLoop **r_allloop, MPoly **r_allpoly,
-         int *r_totloop, int *r_totpoly)
- {
-       ListBase disp = {NULL, NULL};
-       if (ob->curve_cache) {
-               disp = ob->curve_cache->disp;
-       }
-       return BKE_mesh_nurbs_displist_to_mdata(
-               ob, &disp,
-               r_allvert, r_totvert,
-               r_alledge, r_totedge,
-               r_allloop, r_allpoly, NULL,
-               r_totloop, r_totpoly);
- }
- /* BMESH: this doesn't calculate all edges from polygons,
-  * only free standing edges are calculated */
- /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
- /* use specified dispbase */
- int BKE_mesh_nurbs_displist_to_mdata(
-         Object *ob, const ListBase *dispbase,
-         MVert **r_allvert, int *r_totvert,
-         MEdge **r_alledge, int *r_totedge,
-         MLoop **r_allloop, MPoly **r_allpoly,
-         MLoopUV **r_alluv,
-         int *r_totloop, int *r_totpoly)
- {
-       Curve *cu = ob->data;
-       DispList *dl;
-       MVert *mvert;
-       MPoly *mpoly;
-       MLoop *mloop;
-       MLoopUV *mloopuv = NULL;
-       MEdge *medge;
-       const float *data;
-       int a, b, ofs, vertcount, startvert, totvert = 0, totedge = 0, totloop = 0, totpoly = 0;
-       int p1, p2, p3, p4, *index;
-       const bool conv_polys = ((CU_DO_2DFILL(cu) == false) ||  /* 2d polys are filled with DL_INDEX3 displists */
-                                (ob->type == OB_SURF));  /* surf polys are never filled */
-       /* count */
-       dl = dispbase->first;
-       while (dl) {
-               if (dl->type == DL_SEGM) {
-                       totvert += dl->parts * dl->nr;
-                       totedge += dl->parts * (dl->nr - 1);
-               }
-               else if (dl->type == DL_POLY) {
-                       if (conv_polys) {
-                               totvert += dl->parts * dl->nr;
-                               totedge += dl->parts * dl->nr;
-                       }
-               }
-               else if (dl->type == DL_SURF) {
-                       int tot;
-                       totvert += dl->parts * dl->nr;
-                       tot = (dl->parts - 1 + ((dl->flag & DL_CYCL_V) == 2)) * (dl->nr - 1 + (dl->flag & DL_CYCL_U));
-                       totpoly += tot;
-                       totloop += tot * 4;
-               }
-               else if (dl->type == DL_INDEX3) {
-                       int tot;
-                       totvert += dl->nr;
-                       tot = dl->parts;
-                       totpoly += tot;
-                       totloop += tot * 3;
-               }
-               dl = dl->next;
-       }
-       if (totvert == 0) {
-               /* error("can't convert"); */
-               /* Make Sure you check ob->data is a curve */
-               return -1;
-       }
-       *r_allvert = mvert = MEM_calloc_arrayN(totvert, sizeof(MVert), "nurbs_init mvert");
-       *r_alledge = medge = MEM_calloc_arrayN(totedge, sizeof(MEdge), "nurbs_init medge");
-       *r_allloop = mloop = MEM_calloc_arrayN(totpoly, 4 * sizeof(MLoop), "nurbs_init mloop"); // totloop
-       *r_allpoly = mpoly = MEM_calloc_arrayN(totpoly, sizeof(MPoly), "nurbs_init mloop");
-       if (r_alluv)
-               *r_alluv = mloopuv = MEM_calloc_arrayN(totpoly, 4 * sizeof(MLoopUV), "nurbs_init mloopuv");
-       
-       /* verts and faces */
-       vertcount = 0;
-       dl = dispbase->first;
-       while (dl) {
-               const bool is_smooth = (dl->rt & CU_SMOOTH) != 0;
-               if (dl->type == DL_SEGM) {
-                       startvert = vertcount;
-                       a = dl->parts * dl->nr;
-                       data = dl->verts;
-                       while (a--) {
-                               copy_v3_v3(mvert->co, data);
-                               data += 3;
-                               vertcount++;
-                               mvert++;
-                       }
-                       for (a = 0; a < dl->parts; a++) {
-                               ofs = a * dl->nr;
-                               for (b = 1; b < dl->nr; b++) {
-                                       medge->v1 = startvert + ofs + b - 1;
-                                       medge->v2 = startvert + ofs + b;
-                                       medge->flag = ME_LOOSEEDGE | ME_EDGERENDER | ME_EDGEDRAW;
-                                       medge++;
-                               }
-                       }
-               }
-               else if (dl->type == DL_POLY) {
-                       if (conv_polys) {
-                               startvert = vertcount;
-                               a = dl->parts * dl->nr;
-                               data = dl->verts;
-                               while (a--) {
-                                       copy_v3_v3(mvert->co, data);
-                                       data += 3;
-                                       vertcount++;
-                                       mvert++;
-                               }
-                               for (a = 0; a < dl->parts; a++) {
-                                       ofs = a * dl->nr;
-                                       for (b = 0; b < dl->nr; b++) {
-                                               medge->v1 = startvert + ofs + b;
-                                               if (b == dl->nr - 1) medge->v2 = startvert + ofs;
-                                               else medge->v2 = startvert + ofs + b + 1;
-                                               medge->flag = ME_LOOSEEDGE | ME_EDGERENDER | ME_EDGEDRAW;
-                                               medge++;
-                                       }
-                               }
-                       }
-               }
-               else if (dl->type == DL_INDEX3) {
-                       startvert = vertcount;
-                       a = dl->nr;
-                       data = dl->verts;
-                       while (a--) {
-                               copy_v3_v3(mvert->co, data);
-                               data += 3;
-                               vertcount++;
-                               mvert++;
-                       }
-                       a = dl->parts;
-                       index = dl->index;
-                       while (a--) {
-                               mloop[0].v = startvert + index[0];
-                               mloop[1].v = startvert + index[2];
-                               mloop[2].v = startvert + index[1];
-                               mpoly->loopstart = (int)(mloop - (*r_allloop));
-                               mpoly->totloop = 3;
-                               mpoly->mat_nr = dl->col;
-                               if (mloopuv) {
-                                       int i;
-                                       for (i = 0; i < 3; i++, mloopuv++) {
-                                               mloopuv->uv[0] = (mloop[i].v - startvert) / (float)(dl->nr - 1);
-                                               mloopuv->uv[1] = 0.0f;
-                                       }
-                               }
-                               if (is_smooth) mpoly->flag |= ME_SMOOTH;
-                               mpoly++;
-                               mloop += 3;
-                               index += 3;
-                       }
-               }
-               else if (dl->type == DL_SURF) {
-                       startvert = vertcount;
-                       a = dl->parts * dl->nr;
-                       data = dl->verts;
-                       while (a--) {
-                               copy_v3_v3(mvert->co, data);
-                               data += 3;
-                               vertcount++;
-                               mvert++;
-                       }
-                       for (a = 0; a < dl->parts; a++) {
-                               if ( (dl->flag & DL_CYCL_V) == 0 && a == dl->parts - 1) break;
-                               if (dl->flag & DL_CYCL_U) {         /* p2 -> p1 -> */
-                                       p1 = startvert + dl->nr * a;    /* p4 -> p3 -> */
-                                       p2 = p1 + dl->nr - 1;       /* -----> next row */
-                                       p3 = p1 + dl->nr;
-                                       p4 = p2 + dl->nr;
-                                       b = 0;
-                               }
-                               else {
-                                       p2 = startvert + dl->nr * a;
-                                       p1 = p2 + 1;
-                                       p4 = p2 + dl->nr;
-                                       p3 = p1 + dl->nr;
-                                       b = 1;
-                               }
-                               if ( (dl->flag & DL_CYCL_V) && a == dl->parts - 1) {
-                                       p3 -= dl->parts * dl->nr;
-                                       p4 -= dl->parts * dl->nr;
-                               }
-                               for (; b < dl->nr; b++) {
-                                       mloop[0].v = p1;
-                                       mloop[1].v = p3;
-                                       mloop[2].v = p4;
-                                       mloop[3].v = p2;
-                                       mpoly->loopstart = (int)(mloop - (*r_allloop));
-                                       mpoly->totloop = 4;
-                                       mpoly->mat_nr = dl->col;
-                                       if (mloopuv) {
-                                               int orco_sizeu = dl->nr - 1;
-                                               int orco_sizev = dl->parts - 1;
-                                               int i;
-                                               /* exception as handled in convertblender.c too */
-                                               if (dl->flag & DL_CYCL_U) {
-                                                       orco_sizeu++;
-                                                       if (dl->flag & DL_CYCL_V)
-                                                               orco_sizev++;
-                                               }
-                                               else if (dl->flag & DL_CYCL_V) {
-                                                       orco_sizev++;
-                                               }
-                                               for (i = 0; i < 4; i++, mloopuv++) {
-                                                       /* find uv based on vertex index into grid array */
-                                                       int v = mloop[i].v - startvert;
-                                                       mloopuv->uv[0] = (v / dl->nr) / (float)orco_sizev;
-                                                       mloopuv->uv[1] = (v % dl->nr) / (float)orco_sizeu;
-                                                       /* cyclic correction */
-                                                       if ((i == 1 || i == 2) && mloopuv->uv[0] == 0.0f)
-                                                               mloopuv->uv[0] = 1.0f;
-                                                       if ((i == 0 || i == 1) && mloopuv->uv[1] == 0.0f)
-                                                               mloopuv->uv[1] = 1.0f;
-                                               }
-                                       }
-                                       if (is_smooth) mpoly->flag |= ME_SMOOTH;
-                                       mpoly++;
-                                       mloop += 4;
-                                       p4 = p3;
-                                       p3++;
-                                       p2 = p1;
-                                       p1++;
-                               }
-                       }
-               }
-               dl = dl->next;
-       }
-       if (totpoly) {
-               make_edges_mdata_extend(
-                       r_alledge, &totedge,
-                       *r_allpoly, *r_allloop, totpoly);
-       }
-       *r_totpoly = totpoly;
-       *r_totloop = totloop;
-       *r_totedge = totedge;
-       *r_totvert = totvert;
-       return 0;
- }
- Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase)
- {
-       Curve *cu = ob->data;
-       Mesh *mesh;
-       MVert *allvert;
-       MEdge *alledge;
-       MLoop *allloop;
-       MPoly *allpoly;
-       MLoopUV *alluv = NULL;
-       int totvert, totedge, totloop, totpoly;
-       bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
-       if (BKE_mesh_nurbs_displist_to_mdata(
-               ob, dispbase, &allvert, &totvert, &alledge,
-               &totedge, &allloop, &allpoly, (use_orco_uv) ? &alluv : NULL,
-               &totloop, &totpoly) != 0)
-       {
-               /* Error initializing mdata. This often happens when curve is empty */
-               return BKE_mesh_new_nomain(0, 0, 0, 0, 0);
-       }
-       mesh = BKE_mesh_new_nomain(totvert, totedge, 0, totloop, totpoly);
-       mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
-       memcpy(mesh->mvert, allvert, totvert * sizeof(MVert));
-       memcpy(mesh->medge, alledge, totedge * sizeof(MEdge));
-       memcpy(mesh->mloop, allloop, totloop * sizeof(MLoop));
-       memcpy(mesh->mpoly, allpoly, totpoly * sizeof(MPoly));
-       if (alluv) {
-               const char *uvname = "Orco";
-               CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname);
-       }
-       MEM_freeN(allvert);
-       MEM_freeN(alledge);
-       MEM_freeN(allloop);
-       MEM_freeN(allpoly);
-       return mesh;
- }
- Mesh *BKE_mesh_new_nomain_from_curve(Object *ob)
- {
-       ListBase disp = {NULL, NULL};
-       if (ob->curve_cache) {
-               disp = ob->curve_cache->disp;
-       }
-       return BKE_mesh_new_nomain_from_curve_displist(ob, &disp);
- }
- /* this may fail replacing ob->data, be sure to check ob->type */
- void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use_orco_uv, const char *obdata_name)
- {
-       Main *bmain = G.main;
-       Object *ob1;
-       DerivedMesh *dm = ob->derivedFinal;
-       Mesh *me;
-       Curve *cu;
-       MVert *allvert = NULL;
-       MEdge *alledge = NULL;
-       MLoop *allloop = NULL;
-       MLoopUV *alluv = NULL;
-       MPoly *allpoly = NULL;
-       int totvert, totedge, totloop, totpoly;
-       cu = ob->data;
-       if (dm == NULL) {
-               if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert,
-                                                    &alledge, &totedge, &allloop,
-                                                    &allpoly, (use_orco_uv) ? &alluv : NULL,
-                                                    &totloop, &totpoly) != 0)
-               {
-                       /* Error initializing */
-                       return;
-               }
-               /* make mesh */
-               me = BKE_mesh_add(bmain, obdata_name);
-               me->totvert = totvert;
-               me->totedge = totedge;
-               me->totloop = totloop;
-               me->totpoly = totpoly;
-               me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert);
-               me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge);
-               me->mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop);
-               me->mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly);
-               if (alluv) {
-                       const char *uvname = "Orco";
-                       me->mloopuv = CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, uvname);
-               }
-               BKE_mesh_calc_normals(me);
-       }
-       else {
-               me = BKE_mesh_add(bmain, obdata_name);
-               DM_to_mesh(dm, me, ob, CD_MASK_MESH, false);
-       }
-       me->totcol = cu->totcol;
-       me->mat = cu->mat;
-       /* Copy evaluated texture space from curve to mesh.
-        *
-        * Note that we disable auto texture space feature since that will cause
-        * texture space to evaluate differently for curve and mesh, since curve
-        * uses CV to calculate bounding box, and mesh uses what is coming from
-        * tessellated curve.
-        */
-       me->texflag = cu->texflag & ~CU_AUTOSPACE;
-       copy_v3_v3(me->loc, cu->loc);
-       copy_v3_v3(me->size, cu->size);
-       copy_v3_v3(me->rot, cu->rot);
-       BKE_mesh_texspace_calc(me);
-       cu->mat = NULL;
-       cu->totcol = 0;
-       /* Do not decrement ob->data usercount here, it's done at end of func with BKE_libblock_free_us() call. */
-       ob->data = me;
-       ob->type = OB_MESH;
-       /* other users */
-       ob1 = bmain->object.first;
-       while (ob1) {
-               if (ob1->data == cu) {
-                       ob1->type = OB_MESH;
-               
-                       id_us_min((ID *)ob1->data);
-                       ob1->data = ob->data;
-                       id_us_plus((ID *)ob1->data);
-               }
-               ob1 = ob1->id.next;
-       }
-       BKE_libblock_free_us(bmain, cu);
- }
- 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, &disp, use_orco_uv, cu->id.name);
- }
- typedef struct EdgeLink {
-       struct EdgeLink *next, *prev;
-       void *edge;
- } EdgeLink;
- typedef struct VertLink {
-       Link *next, *prev;
-       unsigned int index;
- } VertLink;
- static void prependPolyLineVert(ListBase *lb, unsigned int index)
- {
-       VertLink *vl = MEM_callocN(sizeof(VertLink), "VertLink");
-       vl->index = index;
-       BLI_addhead(lb, vl);
- }
- static void appendPolyLineVert(ListBase *lb, unsigned int index)
- {
-       VertLink *vl = MEM_callocN(sizeof(VertLink), "VertLink");
-       vl->index = index;
-       BLI_addtail(lb, vl);
- }
- void BKE_mesh_to_curve_nurblist(DerivedMesh *dm, ListBase *nurblist, const int edge_users_test)
- {
-       MVert       *mvert = dm->getVertArray(dm);
-       MEdge *med, *medge = dm->getEdgeArray(dm);
-       MPoly *mp,  *mpoly = dm->getPolyArray(dm);
-       MLoop       *mloop = dm->getLoopArray(dm);
-       int dm_totedge = dm->getNumEdges(dm);
-       int dm_totpoly = dm->getNumPolys(dm);
-       int totedges = 0;
-       int i;
-       /* only to detect edge polylines */
-       int *edge_users;
-       ListBase edges = {NULL, NULL};
-       /* get boundary edges */
-       edge_users = MEM_calloc_arrayN(dm_totedge, sizeof(int), __func__);
-       for (i = 0, mp = mpoly; i < dm_totpoly; i++, mp++) {
-               MLoop *ml = &mloop[mp->loopstart];
-               int j;
-               for (j = 0; j < mp->totloop; j++, ml++) {
-                       edge_users[ml->e]++;
-               }
-       }
-       /* create edges from all faces (so as to find edges not in any faces) */
-       med = medge;
-       for (i = 0; i < dm_totedge; i++, med++) {
-               if (edge_users[i] == edge_users_test) {
-                       EdgeLink *edl = MEM_callocN(sizeof(EdgeLink), "EdgeLink");
-                       edl->edge = med;
-                       BLI_addtail(&edges, edl);   totedges++;
-               }
-       }
-       MEM_freeN(edge_users);
-       if (edges.first) {
-               while (edges.first) {
-                       /* each iteration find a polyline and add this as a nurbs poly spline */
-                       ListBase polyline = {NULL, NULL}; /* store a list of VertLink's */
-                       bool closed = false;
-                       int totpoly = 0;
-                       MEdge *med_current = ((EdgeLink *)edges.last)->edge;
-                       unsigned int startVert = med_current->v1;
-                       unsigned int endVert = med_current->v2;
-                       bool ok = true;
-                       appendPolyLineVert(&polyline, startVert);   totpoly++;
-                       appendPolyLineVert(&polyline, endVert);     totpoly++;
-                       BLI_freelinkN(&edges, edges.last);          totedges--;
-                       while (ok) { /* while connected edges are found... */
-                               EdgeLink *edl = edges.last;
-                               ok = false;
-                               while (edl) {
-                                       EdgeLink *edl_prev = edl->prev;
-                                       med = edl->edge;
-                                       if (med->v1 == endVert) {
-                                               endVert = med->v2;
-                                               appendPolyLineVert(&polyline, med->v2); totpoly++;
-                                               BLI_freelinkN(&edges, edl);             totedges--;
-                                               ok = true;
-                                       }
-                                       else if (med->v2 == endVert) {
-                                               endVert = med->v1;
-                                               appendPolyLineVert(&polyline, endVert); totpoly++;
-                                               BLI_freelinkN(&edges, edl);             totedges--;
-                                               ok = true;
-                                       }
-                                       else if (med->v1 == startVert) {
-                                               startVert = med->v2;
-                                               prependPolyLineVert(&polyline, startVert);  totpoly++;
-                                               BLI_freelinkN(&edges, edl);                 totedges--;
-                                               ok = true;
-                                       }
-                                       else if (med->v2 == startVert) {
-                                               startVert = med->v1;
-                                               prependPolyLineVert(&polyline, startVert);  totpoly++;
-                                               BLI_freelinkN(&edges, edl);                 totedges--;
-                                               ok = true;
-                                       }
-                                       edl = edl_prev;
-                               }
-                       }
-                       /* Now we have a polyline, make into a curve */
-                       if (startVert == endVert) {
-                               BLI_freelinkN(&polyline, polyline.last);
-                               totpoly--;
-                               closed = true;
-                       }
-                       /* --- nurbs --- */
-                       {
-                               Nurb *nu;
-                               BPoint *bp;
-                               VertLink *vl;
-                               /* create new 'nurb' within the curve */
-                               nu = (Nurb *)MEM_callocN(sizeof(Nurb), "MeshNurb");
-                               nu->pntsu = totpoly;
-                               nu->pntsv = 1;
-                               nu->orderu = 4;
-                               nu->flagu = CU_NURB_ENDPOINT | (closed ? CU_NURB_CYCLIC : 0);  /* endpoint */
-                               nu->resolu = 12;
-                               nu->bp = (BPoint *)MEM_calloc_arrayN(totpoly, sizeof(BPoint), "bpoints");
-                               /* add points */
-                               vl = polyline.first;
-                               for (i = 0, bp = nu->bp; i < totpoly; i++, bp++, vl = (VertLink *)vl->next) {
-                                       copy_v3_v3(bp->vec, mvert[vl->index].co);
-                                       bp->f1 = SELECT;
-                                       bp->radius = bp->weight = 1.0;
-                               }
-                               BLI_freelistN(&polyline);
-                               /* add nurb to curve */
-                               BLI_addtail(nurblist, nu);
-                       }
-                       /* --- done with nurbs --- */
-               }
-       }
- }
- void BKE_mesh_to_curve(Depsgraph *depsgraph, Scene *scene, Object *ob)
- {
-       /* make new mesh data from the original copy */
-       DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_MESH);
-       ListBase nurblist = {NULL, NULL};
-       bool needsFree = false;
-       BKE_mesh_to_curve_nurblist(dm, &nurblist, 0);
-       BKE_mesh_to_curve_nurblist(dm, &nurblist, 1);
-       if (nurblist.first) {
-               Curve *cu = BKE_curve_add(G.main, ob->id.name + 2, OB_CURVE);
-               cu->flag |= CU_3D;
-               cu->nurb = nurblist;
-               id_us_min(&((Mesh *)ob->data)->id);
-               ob->data = cu;
-               ob->type = OB_CURVE;
-               /* curve objects can't contain DM in usual cases, we could free memory */
-               needsFree = true;
-       }
-       dm->needsFree = needsFree;
-       dm->release(dm);
-       if (needsFree) {
-               ob->derivedFinal = NULL;
-               /* curve object could have got bounding box only in special cases */
-               if (ob->bb) {
-                       MEM_freeN(ob->bb);
-                       ob->bb = NULL;
-               }
-       }
- }
--
  void BKE_mesh_material_index_remove(Mesh *me, short index)
  {
        MPoly *mp;
@@@ -1943,15 -996,15 +1154,15 @@@ void BKE_mesh_smooth_flag_set(Object *m
  
  /**
   * Return a newly MEM_malloc'd array of all the mesh vertex locations
 - * \note \a r_numVerts may be NULL
 + * \note \a r_verts_len may be NULL
   */
 -float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_numVerts))[3]
 +float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_verts_len))[3]
  {
 -      int i, numVerts = me->totvert;
 -      float (*cos)[3] = MEM_malloc_arrayN(numVerts, sizeof(*cos), "vertexcos1");
 +      int i, verts_len = me->totvert;
 +      float (*cos)[3] = MEM_malloc_arrayN(verts_len, sizeof(*cos), "vertexcos1");
  
 -      if (r_numVerts) *r_numVerts = numVerts;
 -      for (i = 0; i < numVerts; i++)
 +      if (r_verts_len) *r_verts_len = verts_len;
 +      for (i = 0; i < verts_len; i++)
                copy_v3_v3(cos[i], me->mvert[i].co);
  
        return cos;
@@@ -2082,13 -1135,13 +1293,13 @@@ void BKE_mesh_ensure_navmesh(Mesh *me
  {
        if (!CustomData_has_layer(&me->pdata, CD_RECAST)) {
                int i;
 -              int numFaces = me->totpoly;
 +              int polys_len = me->totpoly;
                int *recastData;
 -              recastData = (int *)MEM_malloc_arrayN(numFaces, sizeof(int), __func__);
 -              for (i = 0; i < numFaces; i++) {
 +              recastData = (int *)MEM_malloc_arrayN(polys_len, sizeof(int), __func__);
 +              for (i = 0; i < polys_len; i++) {
                        recastData[i] = i + 1;
                }
 -              CustomData_add_layer_named(&me->pdata, CD_RECAST, CD_ASSIGN, recastData, numFaces, "recastData");
 +              CustomData_add_layer_named(&me->pdata, CD_RECAST, CD_ASSIGN, recastData, polys_len, "recastData");
        }
  }
  
@@@ -2279,22 -1332,6 +1490,22 @@@ void BKE_mesh_mselect_active_set(Mesh *
                   (me->mselect[me->totselect - 1].type  == type));
  }
  
 +
 +void BKE_mesh_apply_vert_coords(Mesh *mesh, float (*vertCoords)[3])
 +{
 +      MVert *vert;
 +      int i;
 +
 +      /* this will just return the pointer if it wasn't a referenced layer */
 +      vert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
 +      mesh->mvert = vert;
 +
 +      for (i = 0; i < mesh->totvert; ++i, ++vert)
 +              copy_v3_v3(vert->co, vertCoords[i]);
 +
 +      mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
 +}
 +
  /**
   * Compute 'split' (aka loop, or per face corner's) normals.
   *
@@@ -2346,8 -1383,6 +1557,8 @@@ void BKE_mesh_calc_normals_split_ex(Mes
        if (free_polynors) {
                MEM_freeN(polynors);
        }
 +
 +      mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
  }
  
  void BKE_mesh_calc_normals_split(Mesh *mesh)
@@@ -2381,25 -1416,25 +1592,25 @@@ static int split_faces_prepare_new_vert
         * dealing with smooth/flat faces one can find cases that no simple algorithm can handle properly. */
        BLI_assert(lnors_spacearr != NULL);
  
 -      const int num_loops = mesh->totloop;
 -      int num_verts = mesh->totvert;
 +      const int loops_len = mesh->totloop;
 +      int verts_len = mesh->totvert;
        MVert *mvert = mesh->mvert;
        MLoop *mloop = mesh->mloop;
  
 -      BLI_bitmap *verts_used = BLI_BITMAP_NEW(num_verts, __func__);
 -      BLI_bitmap *done_loops = BLI_BITMAP_NEW(num_loops, __func__);
 +      BLI_bitmap *verts_used = BLI_BITMAP_NEW(verts_len, __func__);
 +      BLI_bitmap *done_loops = BLI_BITMAP_NEW(loops_len, __func__);
  
        MLoop *ml = mloop;
        MLoopNorSpace **lnor_space = lnors_spacearr->lspacearr;
  
        BLI_assert(lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX);
  
 -      for (int loop_idx = 0; loop_idx < num_loops; loop_idx++, ml++, lnor_space++) {
 +      for (int loop_idx = 0; loop_idx < loops_len; loop_idx++, ml++, lnor_space++) {
                if (!BLI_BITMAP_TEST(done_loops, loop_idx)) {
                        const int vert_idx = ml->v;
                        const bool vert_used = BLI_BITMAP_TEST_BOOL(verts_used, vert_idx);
                        /* If vert is already used by another smooth fan, we need a new vert for this one. */
 -                      const int new_vert_idx = vert_used ? num_verts++ : vert_idx;
 +                      const int new_vert_idx = vert_used ? verts_len++ : vert_idx;
  
                        BLI_assert(*lnor_space);
  
        MEM_freeN(done_loops);
        MEM_freeN(verts_used);
  
 -      return num_verts - mesh->totvert;
 +      return verts_len - mesh->totvert;
  }
  
  /* Detect needed new edges, and update accordingly loops' edge indices.
@@@ -2512,12 -1547,12 +1723,12 @@@ static int split_faces_prepare_new_edge
  static void split_faces_split_new_verts(
          Mesh *mesh, SplitFaceNewVert *new_verts, const int num_new_verts)
  {
 -      const int num_verts = mesh->totvert - num_new_verts;
 +      const int verts_len = mesh->totvert - num_new_verts;
        MVert *mvert = mesh->mvert;
  
        /* Remember new_verts is a single linklist, so its items are in reversed order... */
        MVert *new_mv = &mvert[mesh->totvert - 1];
 -      for (int i = mesh->totvert - 1; i >= num_verts ; i--, new_mv--, new_verts = new_verts->next) {
 +      for (int i = mesh->totvert - 1; i >= verts_len ; i--, new_mv--, new_verts = new_verts->next) {
                BLI_assert(new_verts->new_index == i);
                BLI_assert(new_verts->new_index != new_verts->orig_index);
                CustomData_copy_data(&mesh->vdata, &mesh->vdata, new_verts->orig_index, i, 1);
@@@ -2612,270 -1647,14 +1823,30 @@@ void BKE_mesh_split_faces(Mesh *mesh, b
  #endif
  }
  
- /* settings: 1 - preview, 2 - render */
- Mesh *BKE_mesh_new_from_object(
-         Depsgraph *depsgraph, Main *bmain, Scene *sce, Object *ob,
-         const bool apply_modifiers, const bool calc_tessface, const bool calc_undeformed)
- {
-       Mesh *tmpmesh;
-       Curve *tmpcu = NULL, *copycu;
-       int i;
-       const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
-       const bool cage = !apply_modifiers;
-       bool do_mat_id_data_us = true;
-       /* perform the mesh extraction based on type */
-       switch (ob->type) {
-               case OB_FONT:
-               case OB_CURVE:
-               case OB_SURF:
-               {
-                       ListBase dispbase = {NULL, NULL};
-                       DerivedMesh *derivedFinal = NULL;
-                       int uv_from_orco;
-                       /* copies object and modifiers (but not the data) */
-                       Object *tmpobj;
-                       /* TODO: make it temp copy outside bmain! */
-                       BKE_id_copy_ex(bmain, &ob->id, (ID **)&tmpobj, LIB_ID_COPY_CACHES, false);
-                       tmpcu = (Curve *)tmpobj->data;
-                       id_us_min(&tmpcu->id);
-                       /* Copy cached display list, it might be needed by the stack evaluation.
-                        * Ideally stack should be able to use render-time display list, but doing
-                        * so is quite tricky and not safe so close to the release.
-                        *
-                        * TODO(sergey): Look into more proper solution.
-                        */
-                       if (ob->curve_cache != NULL) {
-                               if (tmpobj->curve_cache == NULL) {
-                                       tmpobj->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
-                               }
-                               BKE_displist_copy(&tmpobj->curve_cache->disp, &ob->curve_cache->disp);
-                       }
-                       /* if getting the original caged mesh, delete object modifiers */
-                       if (cage)
-                               BKE_object_free_modifiers(tmpobj, 0);
-                       /* copies the data */
-                       copycu = tmpobj->data = BKE_curve_copy(bmain, (Curve *) ob->data);
-                       /* make sure texture space is calculated for a copy of curve,
-                        * it will be used for the final result.
-                        */
-                       BKE_curve_texspace_calc(copycu);
-                       /* temporarily set edit so we get updates from edit mode, but
-                        * also because for text datablocks copying it while in edit
-                        * mode gives invalid data structures */
-                       copycu->editfont = tmpcu->editfont;
-                       copycu->editnurb = tmpcu->editnurb;
-                       /* get updated display list, and convert to a mesh */
-                       BKE_displist_make_curveTypes_forRender(depsgraph, sce, tmpobj, &dispbase, &derivedFinal, false, render);
-                       copycu->editfont = NULL;
-                       copycu->editnurb = NULL;
-                       tmpobj->derivedFinal = derivedFinal;
-                       /* convert object type to mesh */
-                       uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
-                       BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2);
-                       tmpmesh = tmpobj->data;
-                       BKE_displist_free(&dispbase);
-                       /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked.
-                        * if it didn't the curve did not have any segments or otherwise 
-                        * would have generated an empty mesh */
-                       if (tmpobj->type != OB_MESH) {
-                               BKE_libblock_free_us(bmain, tmpobj);
-                               return NULL;
-                       }
-                       BKE_libblock_free_us(bmain, tmpobj);
-                       /* XXX The curve to mesh conversion is convoluted... But essentially, BKE_mesh_from_nurbs_displist()
-                        *     already transfers the ownership of materials from the temp copy of the Curve ID to the new
-                        *     Mesh ID, so we do not want to increase materials' usercount later. */
-                       do_mat_id_data_us = false;
-                       break;
-               }
-               case OB_MBALL:
-               {
-                       /* metaballs don't have modifiers, so just convert to mesh */
-                       Object *basis_ob = BKE_mball_basis_find(sce, ob);
-                       /* todo, re-generatre for render-res */
-                       /* metaball_polygonize(scene, ob) */
-                       if (ob != basis_ob)
-                               return NULL;  /* only do basis metaball */
-                       tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2);
-                       /* BKE_mesh_add gives us a user count we don't need */
-                       id_us_min(&tmpmesh->id);
-                       if (render) {
-                               ListBase disp = {NULL, NULL};
-                               BKE_displist_make_mball_forRender(depsgraph, sce, ob, &disp);
-                               BKE_mesh_from_metaball(&disp, tmpmesh);
-                               BKE_displist_free(&disp);
-                       }
-                       else {
-                               ListBase disp = {NULL, NULL};
-                               if (ob->curve_cache) {
-                                       disp = ob->curve_cache->disp;
-                               }
-                               BKE_mesh_from_metaball(&disp, tmpmesh);
-                       }
-                       BKE_mesh_texspace_copy_from_object(tmpmesh, ob);
-                       break;
-               }
-               case OB_MESH:
-                       /* copies object and modifiers (but not the data) */
-                       if (cage) {
-                               /* copies the data */
-                               tmpmesh = BKE_mesh_copy(bmain, ob->data);
-                               /* XXX BKE_mesh_copy() already handles materials usercount. */
-                               do_mat_id_data_us = false;
-                       }
-                       /* if not getting the original caged mesh, get final derived mesh */
-                       else {
-                               /* Make a dummy mesh, saves copying */
-                               DerivedMesh *dm;
-                               /* CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; */
-                               CustomDataMask mask = CD_MASK_MESH; /* this seems more suitable, exporter,
-                                                                    * for example, needs CD_MASK_MDEFORMVERT */
-                               if (calc_undeformed)
-                                       mask |= CD_MASK_ORCO;
-                               /* Write the display mesh into the dummy mesh */
-                               if (render)
-                                       dm = mesh_create_derived_render(depsgraph, sce, ob, mask);
-                               else
-                                       dm = mesh_create_derived_view(depsgraph, sce, ob, mask);
-                               tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2);
-                               DM_to_mesh(dm, tmpmesh, ob, mask, true);
-                               /* Copy autosmooth settings from original mesh. */
-                               Mesh *me = (Mesh *)ob->data;
-                               tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH);
-                               tmpmesh->smoothresh = me->smoothresh;
-                       }
-                       /* BKE_mesh_add/copy gives us a user count we don't need */
-                       id_us_min(&tmpmesh->id);
-                       break;
-               default:
-                       /* "Object does not have geometry data") */
-                       return NULL;
-       }
-       /* Copy materials to new mesh */
-       switch (ob->type) {
-               case OB_SURF:
-               case OB_FONT:
-               case OB_CURVE:
-                       tmpmesh->totcol = tmpcu->totcol;
-                       /* free old material list (if it exists) and adjust user counts */
-                       if (tmpcu->mat) {
-                               for (i = tmpcu->totcol; i-- > 0; ) {
-                                       /* are we an object material or data based? */
-                                       tmpmesh->mat[i] = give_current_material(ob, i + 1);
-                                       if (((ob->matbits && ob->matbits[i]) || do_mat_id_data_us)  && tmpmesh->mat[i]) {
-                                               id_us_plus(&tmpmesh->mat[i]->id);
-                                       }
-                               }
-                       }
-                       break;
-               case OB_MBALL:
-               {
-                       MetaBall *tmpmb = (MetaBall *)ob->data;
-                       tmpmesh->mat = MEM_dupallocN(tmpmb->mat);
-                       tmpmesh->totcol = tmpmb->totcol;
-                       /* free old material list (if it exists) and adjust user counts */
-                       if (tmpmb->mat) {
-                               for (i = tmpmb->totcol; i-- > 0; ) {
-                                       /* are we an object material or data based? */
-                                       tmpmesh->mat[i] = give_current_material(ob, i + 1);
-                                       if (((ob->matbits && ob->matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) {
-                                               id_us_plus(&tmpmesh->mat[i]->id);
-                                       }
-                               }
-                       }
-                       break;
-               }
-               case OB_MESH:
-                       if (!cage) {
-                               Mesh *origmesh = ob->data;
-                               tmpmesh->flag = origmesh->flag;
-                               tmpmesh->mat = MEM_dupallocN(origmesh->mat);
-                               tmpmesh->totcol = origmesh->totcol;
-                               tmpmesh->smoothresh = origmesh->smoothresh;
-                               if (origmesh->mat) {
-                                       for (i = origmesh->totcol; i-- > 0; ) {
-                                               /* are we an object material or data based? */
-                                               tmpmesh->mat[i] = give_current_material(ob, i + 1);
-                                               if (((ob->matbits && ob->matbits[i]) || do_mat_id_data_us)  && tmpmesh->mat[i]) {
-                                                       id_us_plus(&tmpmesh->mat[i]->id);
-                                               }
-                                       }
-                               }
-                       }
-                       break;
-       } /* end copy materials */
-       if (calc_tessface) {
-               /* cycles and exporters rely on this still */
-               BKE_mesh_tessface_ensure(tmpmesh);
-       }
-       return tmpmesh;
- }
--
  /* **** Depsgraph evaluation **** */
  
 -void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
 +void BKE_mesh_eval_geometry(Depsgraph *depsgraph,
                              Mesh *mesh)
  {
 -      DEG_debug_print_eval(__func__, mesh->id.name, mesh);
 +      DEG_debug_print_eval(depsgraph, __func__, mesh->id.name, mesh);
        if (mesh->bb == NULL || (mesh->bb->flag & BOUNDBOX_DIRTY)) {
                BKE_mesh_texspace_calc(mesh);
        }
  }
 +
 +/* Draw Engine */
 +void (*BKE_mesh_batch_cache_dirty_cb)(Mesh *me, int mode) = NULL;
 +void (*BKE_mesh_batch_cache_free_cb)(Mesh *me) = NULL;
 +
 +void BKE_mesh_batch_cache_dirty(Mesh *me, int mode)
 +{
 +      if (me->runtime.batch_cache) {
 +              BKE_mesh_batch_cache_dirty_cb(me, mode);
 +      }
 +}
 +void BKE_mesh_batch_cache_free(Mesh *me)
 +{
 +      if (me->runtime.batch_cache) {
 +              BKE_mesh_batch_cache_free_cb(me);
 +      }
 +}
index 0000000000000000000000000000000000000000,17071b6d7ea5db892dfd751e3c62c9061922cb65..a48a74f2d67e73b8894621b95042adfcba272f2d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1026 +1,1072 @@@
 -#include "BKE_modifier.h"
+ /*
+  * ***** BEGIN GPL LICENSE BLOCK *****
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+  * as published by the Free Software Foundation; either version 2
+  * of the License, or (at your option) any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License
+  * along with this program; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+  *
+  * ***** END GPL LICENSE BLOCK *****
+  */
+ /** \file blender/blenkernel/intern/mesh_convert.c
+  *  \ingroup bke
+  */
++
+ #include "MEM_guardedalloc.h"
+ #include "DNA_scene_types.h"
+ #include "DNA_material_types.h"
+ #include "DNA_meta_types.h"
+ #include "DNA_object_types.h"
+ #include "DNA_mesh_types.h"
+ #include "DNA_curve_types.h"
+ #include "BLI_utildefines.h"
+ #include "BLI_math.h"
+ #include "BLI_listbase.h"
+ #include "BLI_edgehash.h"
+ #include "BKE_main.h"
+ #include "BKE_DerivedMesh.h"
+ #include "BKE_global.h"
+ #include "BKE_mesh.h"
+ #include "BKE_displist.h"
+ #include "BKE_library.h"
+ #include "BKE_material.h"
 -#include "BKE_depsgraph.h"
+ #include "BKE_mball.h"
 -                      me->mtpoly = CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname);
++/* these 2 are only used by conversion functions */
+ #include "BKE_curve.h"
+ /* -- */
+ #include "BKE_object.h"
+ #include "DEG_depsgraph.h"
++#include "DEG_depsgraph_query.h"
+ /* Define for cases when you want extra validation of mesh
+  * after certain modifications.
+  */
+ // #undef VALIDATE_MESH
+ void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
+ {
+       DispList *dl;
+       MVert *mvert;
+       MLoop *mloop, *allloop;
+       MPoly *mpoly;
+       const float *nors, *verts;
+       int a, *index;
+       dl = lb->first;
+       if (dl == NULL) return;
+       if (dl->type == DL_INDEX4) {
+               mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, dl->nr);
+               allloop = mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, dl->parts * 4);
+               mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, dl->parts);
+               me->mvert = mvert;
+               me->mloop = mloop;
+               me->mpoly = mpoly;
+               me->totvert = dl->nr;
+               me->totpoly = dl->parts;
+               a = dl->nr;
+               nors = dl->nors;
+               verts = dl->verts;
+               while (a--) {
+                       copy_v3_v3(mvert->co, verts);
+                       normal_float_to_short_v3(mvert->no, nors);
+                       mvert++;
+                       nors += 3;
+                       verts += 3;
+               }
+               a = dl->parts;
+               index = dl->index;
+               while (a--) {
+                       int count = index[2] != index[3] ? 4 : 3;
+                       mloop[0].v = index[0];
+                       mloop[1].v = index[1];
+                       mloop[2].v = index[2];
+                       if (count == 4)
+                               mloop[3].v = index[3];
+                       mpoly->totloop = count;
+                       mpoly->loopstart = (int)(mloop - allloop);
+                       mpoly->flag = ME_SMOOTH;
+                       mpoly++;
+                       mloop += count;
+                       me->totloop += count;
+                       index += 4;
+               }
+               BKE_mesh_update_customdata_pointers(me, true);
+               BKE_mesh_calc_normals(me);
+               BKE_mesh_calc_edges(me, true, false);
+       }
+ }
+ /**
+  * Specialized function to use when we _know_ existing edges don't overlap with poly edges.
+  */
+ static void make_edges_mdata_extend(MEdge **r_alledge, int *r_totedge,
+                                     const MPoly *mpoly, MLoop *mloop,
+                                     const int totpoly)
+ {
+       int totedge = *r_totedge;
+       int totedge_new;
+       EdgeHash *eh;
+       unsigned int eh_reserve;
+       const MPoly *mp;
+       int i;
+       eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly));
+       eh = BLI_edgehash_new_ex(__func__, eh_reserve);
+       for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
+               BKE_mesh_poly_edgehash_insert(eh, mp, mloop + mp->loopstart);
+       }
+       totedge_new = BLI_edgehash_len(eh);
+ #ifdef DEBUG
+       /* ensure that theres no overlap! */
+       if (totedge_new) {
+               MEdge *medge = *r_alledge;
+               for (i = 0; i < totedge; i++, medge++) {
+                       BLI_assert(BLI_edgehash_haskey(eh, medge->v1, medge->v2) == false);
+               }
+       }
+ #endif
+       if (totedge_new) {
+               EdgeHashIterator *ehi;
+               MEdge *medge;
+               unsigned int e_index = totedge;
+               *r_alledge = medge = (*r_alledge ? MEM_reallocN(*r_alledge, sizeof(MEdge) * (totedge + totedge_new)) :
+                                                  MEM_calloc_arrayN(totedge_new, sizeof(MEdge), __func__));
+               medge += totedge;
+               totedge += totedge_new;
+               /* --- */
+               for (ehi = BLI_edgehashIterator_new(eh);
+                    BLI_edgehashIterator_isDone(ehi) == false;
+                    BLI_edgehashIterator_step(ehi), ++medge, e_index++)
+               {
+                       BLI_edgehashIterator_getKey(ehi, &medge->v1, &medge->v2);
+                       BLI_edgehashIterator_setValue(ehi, SET_UINT_IN_POINTER(e_index));
+                       medge->crease = medge->bweight = 0;
+                       medge->flag = ME_EDGEDRAW | ME_EDGERENDER;
+               }
+               BLI_edgehashIterator_free(ehi);
+               *r_totedge = totedge;
+               for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
+                       MLoop *l = &mloop[mp->loopstart];
+                       MLoop *l_prev = (l + (mp->totloop - 1));
+                       int j;
+                       for (j = 0; j < mp->totloop; j++, l++) {
+                               /* lookup hashed edge index */
+                               l_prev->e = GET_UINT_FROM_POINTER(BLI_edgehash_lookup(eh, l_prev->v, l->v));
+                               l_prev = l;
+                       }
+               }
+       }
+       BLI_edgehash_free(eh, NULL);
+ }
+ /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
+ /* return non-zero on error */
+ int BKE_mesh_nurbs_to_mdata(
+         Object *ob, MVert **r_allvert, int *r_totvert,
+         MEdge **r_alledge, int *r_totedge, MLoop **r_allloop, MPoly **r_allpoly,
+         int *r_totloop, int *r_totpoly)
+ {
+       ListBase disp = {NULL, NULL};
+       if (ob->curve_cache) {
+               disp = ob->curve_cache->disp;
+       }
+       return BKE_mesh_nurbs_displist_to_mdata(
+               ob, &disp,
+               r_allvert, r_totvert,
+               r_alledge, r_totedge,
+               r_allloop, r_allpoly, NULL,
+               r_totloop, r_totpoly);
+ }
+ /* BMESH: this doesn't calculate all edges from polygons,
+  * only free standing edges are calculated */
+ /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
+ /* use specified dispbase */
+ int BKE_mesh_nurbs_displist_to_mdata(
+         Object *ob, const ListBase *dispbase,
+         MVert **r_allvert, int *r_totvert,
+         MEdge **r_alledge, int *r_totedge,
+         MLoop **r_allloop, MPoly **r_allpoly,
+         MLoopUV **r_alluv,
+         int *r_totloop, int *r_totpoly)
+ {
+       Curve *cu = ob->data;
+       DispList *dl;
+       MVert *mvert;
+       MPoly *mpoly;
+       MLoop *mloop;
+       MLoopUV *mloopuv = NULL;
+       MEdge *medge;
+       const float *data;
+       int a, b, ofs, vertcount, startvert, totvert = 0, totedge = 0, totloop = 0, totpoly = 0;
+       int p1, p2, p3, p4, *index;
+       const bool conv_polys = ((CU_DO_2DFILL(cu) == false) ||  /* 2d polys are filled with DL_INDEX3 displists */
+                                (ob->type == OB_SURF));  /* surf polys are never filled */
+       /* count */
+       dl = dispbase->first;
+       while (dl) {
+               if (dl->type == DL_SEGM) {
+                       totvert += dl->parts * dl->nr;
+                       totedge += dl->parts * (dl->nr - 1);
+               }
+               else if (dl->type == DL_POLY) {
+                       if (conv_polys) {
+                               totvert += dl->parts * dl->nr;
+                               totedge += dl->parts * dl->nr;
+                       }
+               }
+               else if (dl->type == DL_SURF) {
+                       int tot;
+                       totvert += dl->parts * dl->nr;
+                       tot = (dl->parts - 1 + ((dl->flag & DL_CYCL_V) == 2)) * (dl->nr - 1 + (dl->flag & DL_CYCL_U));
+                       totpoly += tot;
+                       totloop += tot * 4;
+               }
+               else if (dl->type == DL_INDEX3) {
+                       int tot;
+                       totvert += dl->nr;
+                       tot = dl->parts;
+                       totpoly += tot;
+                       totloop += tot * 3;
+               }
+               dl = dl->next;
+       }
+       if (totvert == 0) {
+               /* error("can't convert"); */
+               /* Make Sure you check ob->data is a curve */
+               return -1;
+       }
+       *r_allvert = mvert = MEM_calloc_arrayN(totvert, sizeof(MVert), "nurbs_init mvert");
+       *r_alledge = medge = MEM_calloc_arrayN(totedge, sizeof(MEdge), "nurbs_init medge");
+       *r_allloop = mloop = MEM_calloc_arrayN(totpoly, 4 * sizeof(MLoop), "nurbs_init mloop"); // totloop
+       *r_allpoly = mpoly = MEM_calloc_arrayN(totpoly, sizeof(MPoly), "nurbs_init mloop");
+       if (r_alluv)
+               *r_alluv = mloopuv = MEM_calloc_arrayN(totpoly, 4 * sizeof(MLoopUV), "nurbs_init mloopuv");
+       /* verts and faces */
+       vertcount = 0;
+       dl = dispbase->first;
+       while (dl) {
+               const bool is_smooth = (dl->rt & CU_SMOOTH) != 0;
+               if (dl->type == DL_SEGM) {
+                       startvert = vertcount;
+                       a = dl->parts * dl->nr;
+                       data = dl->verts;
+                       while (a--) {
+                               copy_v3_v3(mvert->co, data);
+                               data += 3;
+                               vertcount++;
+                               mvert++;
+                       }
+                       for (a = 0; a < dl->parts; a++) {
+                               ofs = a * dl->nr;
+                               for (b = 1; b < dl->nr; b++) {
+                                       medge->v1 = startvert + ofs + b - 1;
+                                       medge->v2 = startvert + ofs + b;
+                                       medge->flag = ME_LOOSEEDGE | ME_EDGERENDER | ME_EDGEDRAW;
+                                       medge++;
+                               }
+                       }
+               }
+               else if (dl->type == DL_POLY) {
+                       if (conv_polys) {
+                               startvert = vertcount;
+                               a = dl->parts * dl->nr;
+                               data = dl->verts;
+                               while (a--) {
+                                       copy_v3_v3(mvert->co, data);
+                                       data += 3;
+                                       vertcount++;
+                                       mvert++;
+                               }
+                               for (a = 0; a < dl->parts; a++) {
+                                       ofs = a * dl->nr;
+                                       for (b = 0; b < dl->nr; b++) {
+                                               medge->v1 = startvert + ofs + b;
+                                               if (b == dl->nr - 1) medge->v2 = startvert + ofs;
+                                               else medge->v2 = startvert + ofs + b + 1;
+                                               medge->flag = ME_LOOSEEDGE | ME_EDGERENDER | ME_EDGEDRAW;
+                                               medge++;
+                                       }
+                               }
+                       }
+               }
+               else if (dl->type == DL_INDEX3) {
+                       startvert = vertcount;
+                       a = dl->nr;
+                       data = dl->verts;
+                       while (a--) {
+                               copy_v3_v3(mvert->co, data);
+                               data += 3;
+                               vertcount++;
+                               mvert++;
+                       }
+                       a = dl->parts;
+                       index = dl->index;
+                       while (a--) {
+                               mloop[0].v = startvert + index[0];
+                               mloop[1].v = startvert + index[2];
+                               mloop[2].v = startvert + index[1];
+                               mpoly->loopstart = (int)(mloop - (*r_allloop));
+                               mpoly->totloop = 3;
+                               mpoly->mat_nr = dl->col;
+                               if (mloopuv) {
+                                       int i;
+                                       for (i = 0; i < 3; i++, mloopuv++) {
+                                               mloopuv->uv[0] = (mloop[i].v - startvert) / (float)(dl->nr - 1);
+                                               mloopuv->uv[1] = 0.0f;
+                                       }
+                               }
+                               if (is_smooth) mpoly->flag |= ME_SMOOTH;
+                               mpoly++;
+                               mloop += 3;
+                               index += 3;
+                       }
+               }
+               else if (dl->type == DL_SURF) {
+                       startvert = vertcount;
+                       a = dl->parts * dl->nr;
+                       data = dl->verts;
+                       while (a--) {
+                               copy_v3_v3(mvert->co, data);
+                               data += 3;
+                               vertcount++;
+                               mvert++;
+                       }
+                       for (a = 0; a < dl->parts; a++) {
+                               if ( (dl->flag & DL_CYCL_V) == 0 && a == dl->parts - 1) break;
+                               if (dl->flag & DL_CYCL_U) {         /* p2 -> p1 -> */
+                                       p1 = startvert + dl->nr * a;    /* p4 -> p3 -> */
+                                       p2 = p1 + dl->nr - 1;       /* -----> next row */
+                                       p3 = p1 + dl->nr;
+                                       p4 = p2 + dl->nr;
+                                       b = 0;
+                               }
+                               else {
+                                       p2 = startvert + dl->nr * a;
+                                       p1 = p2 + 1;
+                                       p4 = p2 + dl->nr;
+                                       p3 = p1 + dl->nr;
+                                       b = 1;
+                               }
+                               if ( (dl->flag & DL_CYCL_V) && a == dl->parts - 1) {
+                                       p3 -= dl->parts * dl->nr;
+                                       p4 -= dl->parts * dl->nr;
+                               }
+                               for (; b < dl->nr; b++) {
+                                       mloop[0].v = p1;
+                                       mloop[1].v = p3;
+                                       mloop[2].v = p4;
+                                       mloop[3].v = p2;
+                                       mpoly->loopstart = (int)(mloop - (*r_allloop));
+                                       mpoly->totloop = 4;
+                                       mpoly->mat_nr = dl->col;
+                                       if (mloopuv) {
+                                               int orco_sizeu = dl->nr - 1;
+                                               int orco_sizev = dl->parts - 1;
+                                               int i;
+                                               /* exception as handled in convertblender.c too */
+                                               if (dl->flag & DL_CYCL_U) {
+                                                       orco_sizeu++;
+                                                       if (dl->flag & DL_CYCL_V)
+                                                               orco_sizev++;
+                                               }
+                                               else if (dl->flag & DL_CYCL_V) {
+                                                       orco_sizev++;
+                                               }
+                                               for (i = 0; i < 4; i++, mloopuv++) {
+                                                       /* find uv based on vertex index into grid array */
+                                                       int v = mloop[i].v - startvert;
+                                                       mloopuv->uv[0] = (v / dl->nr) / (float)orco_sizev;
+                                                       mloopuv->uv[1] = (v % dl->nr) / (float)orco_sizeu;
+                                                       /* cyclic correction */
+                                                       if ((i == 1 || i == 2) && mloopuv->uv[0] == 0.0f)
+                                                               mloopuv->uv[0] = 1.0f;
+                                                       if ((i == 0 || i == 1) && mloopuv->uv[1] == 0.0f)
+                                                               mloopuv->uv[1] = 1.0f;
+                                               }
+                                       }
+                                       if (is_smooth) mpoly->flag |= ME_SMOOTH;
+                                       mpoly++;
+                                       mloop += 4;
+                                       p4 = p3;
+                                       p3++;
+                                       p2 = p1;
+                                       p1++;
+                               }
+                       }
+               }
+               dl = dl->next;
+       }
+       if (totpoly) {
+               make_edges_mdata_extend(
+                       r_alledge, &totedge,
+                       *r_allpoly, *r_allloop, totpoly);
+       }
+       *r_totpoly = totpoly;
+       *r_totloop = totloop;
+       *r_totedge = totedge;
+       *r_totvert = totvert;
+       return 0;
+ }
++Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase)
++{
++      Curve *cu = ob->data;
++      Mesh *mesh;
++      MVert *allvert;
++      MEdge *alledge;
++      MLoop *allloop;
++      MPoly *allpoly;
++      MLoopUV *alluv = NULL;
++      int totvert, totedge, totloop, totpoly;
++      bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
++
++      if (BKE_mesh_nurbs_displist_to_mdata(
++              ob, dispbase, &allvert, &totvert, &alledge,
++              &totedge, &allloop, &allpoly, (use_orco_uv) ? &alluv : NULL,
++              &totloop, &totpoly) != 0)
++      {
++              /* Error initializing mdata. This often happens when curve is empty */
++              return BKE_mesh_new_nomain(0, 0, 0, 0, 0);
++      }
++
++      mesh = BKE_mesh_new_nomain(totvert, totedge, 0, totloop, totpoly);
++      mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
++
++      memcpy(mesh->mvert, allvert, totvert * sizeof(MVert));
++      memcpy(mesh->medge, alledge, totedge * sizeof(MEdge));
++      memcpy(mesh->mloop, allloop, totloop * sizeof(MLoop));
++      memcpy(mesh->mpoly, allpoly, totpoly * sizeof(MPoly));
++
++      if (alluv) {
++              const char *uvname = "Orco";
++              CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname);
++      }
++
++      MEM_freeN(allvert);
++      MEM_freeN(alledge);
++      MEM_freeN(allloop);
++      MEM_freeN(allpoly);
++
++      return mesh;
++}
++
++Mesh *BKE_mesh_new_nomain_from_curve(Object *ob)
++{
++      ListBase disp = {NULL, NULL};
++
++      if (ob->curve_cache) {
++              disp = ob->curve_cache->disp;
++      }
++
++      return BKE_mesh_new_nomain_from_curve_displist(ob, &disp);
++}
+ /* this may fail replacing ob->data, be sure to check ob->type */
+ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use_orco_uv, const char *obdata_name)
+ {
+       Main *bmain = G.main;
+       Object *ob1;
+       DerivedMesh *dm = ob->derivedFinal;
+       Mesh *me;
+       Curve *cu;
+       MVert *allvert = NULL;
+       MEdge *alledge = NULL;
+       MLoop *allloop = NULL;
+       MLoopUV *alluv = NULL;
+       MPoly *allpoly = NULL;
+       int totvert, totedge, totloop, totpoly;
+       cu = ob->data;
+       if (dm == NULL) {
+               if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert,
+                                                    &alledge, &totedge, &allloop,
+                                                    &allpoly, (use_orco_uv) ? &alluv : NULL,
+                                                    &totloop, &totpoly) != 0)
+               {
+                       /* Error initializing */
+                       return;
+               }
+               /* make mesh */
+               me = BKE_mesh_add(bmain, obdata_name);
+               me->totvert = totvert;
+               me->totedge = totedge;
+               me->totloop = totloop;
+               me->totpoly = totpoly;
+               me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert);
+               me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge);
+               me->mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop);
+               me->mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly);
+               if (alluv) {
+                       const char *uvname = "Orco";
 -void BKE_mesh_to_curve(Scene *scene, Object *ob)
+                       me->mloopuv = CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, uvname);
+               }
+               BKE_mesh_calc_normals(me);
+       }
+       else {
+               me = BKE_mesh_add(bmain, obdata_name);
+               DM_to_mesh(dm, me, ob, CD_MASK_MESH, false);
+       }
+       me->totcol = cu->totcol;
+       me->mat = cu->mat;
+       /* Copy evaluated texture space from curve to mesh.
+        *
+        * Note that we disable auto texture space feature since that will cause
+        * texture space to evaluate differently for curve and mesh, since curve
+        * uses CV to calculate bounding box, and mesh uses what is coming from
+        * tessellated curve.
+        */
+       me->texflag = cu->texflag & ~CU_AUTOSPACE;
+       copy_v3_v3(me->loc, cu->loc);
+       copy_v3_v3(me->size, cu->size);
+       copy_v3_v3(me->rot, cu->rot);
+       BKE_mesh_texspace_calc(me);
+       cu->mat = NULL;
+       cu->totcol = 0;
+       /* Do not decrement ob->data usercount here, it's done at end of func with BKE_libblock_free_us() call. */
+       ob->data = me;
+       ob->type = OB_MESH;
+       /* other users */
+       ob1 = bmain->object.first;
+       while (ob1) {
+               if (ob1->data == cu) {
+                       ob1->type = OB_MESH;
+                       id_us_min((ID *)ob1->data);
+                       ob1->data = ob->data;
+                       id_us_plus((ID *)ob1->data);
+               }
+               ob1 = ob1->id.next;
+       }
+       BKE_libblock_free_us(bmain, cu);
+ }
+ 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, &disp, use_orco_uv, cu->id.name);
+ }
+ typedef struct EdgeLink {
+       struct EdgeLink *next, *prev;
+       void *edge;
+ } EdgeLink;
+ typedef struct VertLink {
+       Link *next, *prev;
+       unsigned int index;
+ } VertLink;
+ static void prependPolyLineVert(ListBase *lb, unsigned int index)
+ {
+       VertLink *vl = MEM_callocN(sizeof(VertLink), "VertLink");
+       vl->index = index;
+       BLI_addhead(lb, vl);
+ }
+ static void appendPolyLineVert(ListBase *lb, unsigned int index)
+ {
+       VertLink *vl = MEM_callocN(sizeof(VertLink), "VertLink");
+       vl->index = index;
+       BLI_addtail(lb, vl);
+ }
+ void BKE_mesh_to_curve_nurblist(DerivedMesh *dm, ListBase *nurblist, const int edge_users_test)
+ {
+       MVert       *mvert = dm->getVertArray(dm);
+       MEdge *med, *medge = dm->getEdgeArray(dm);
+       MPoly *mp,  *mpoly = dm->getPolyArray(dm);
+       MLoop       *mloop = dm->getLoopArray(dm);
+       int dm_totedge = dm->getNumEdges(dm);
+       int dm_totpoly = dm->getNumPolys(dm);
+       int totedges = 0;
+       int i;
+       /* only to detect edge polylines */
+       int *edge_users;
+       ListBase edges = {NULL, NULL};
+       /* get boundary edges */
+       edge_users = MEM_calloc_arrayN(dm_totedge, sizeof(int), __func__);
+       for (i = 0, mp = mpoly; i < dm_totpoly; i++, mp++) {
+               MLoop *ml = &mloop[mp->loopstart];
+               int j;
+               for (j = 0; j < mp->totloop; j++, ml++) {
+                       edge_users[ml->e]++;
+               }
+       }
+       /* create edges from all faces (so as to find edges not in any faces) */
+       med = medge;
+       for (i = 0; i < dm_totedge; i++, med++) {
+               if (edge_users[i] == edge_users_test) {
+                       EdgeLink *edl = MEM_callocN(sizeof(EdgeLink), "EdgeLink");
+                       edl->edge = med;
+                       BLI_addtail(&edges, edl);   totedges++;
+               }
+       }
+       MEM_freeN(edge_users);
+       if (edges.first) {
+               while (edges.first) {
+                       /* each iteration find a polyline and add this as a nurbs poly spline */
+                       ListBase polyline = {NULL, NULL}; /* store a list of VertLink's */
+                       bool closed = false;
+                       int totpoly = 0;
+                       MEdge *med_current = ((EdgeLink *)edges.last)->edge;
+                       unsigned int startVert = med_current->v1;
+                       unsigned int endVert = med_current->v2;
+                       bool ok = true;
+                       appendPolyLineVert(&polyline, startVert);   totpoly++;
+                       appendPolyLineVert(&polyline, endVert);     totpoly++;
+                       BLI_freelinkN(&edges, edges.last);          totedges--;
+                       while (ok) { /* while connected edges are found... */
+                               EdgeLink *edl = edges.last;
+                               ok = false;
+                               while (edl) {
+                                       EdgeLink *edl_prev = edl->prev;
+                                       med = edl->edge;
+                                       if (med->v1 == endVert) {
+                                               endVert = med->v2;
+                                               appendPolyLineVert(&polyline, med->v2); totpoly++;
+                                               BLI_freelinkN(&edges, edl);             totedges--;
+                                               ok = true;
+                                       }
+                                       else if (med->v2 == endVert) {
+                                               endVert = med->v1;
+                                               appendPolyLineVert(&polyline, endVert); totpoly++;
+                                               BLI_freelinkN(&edges, edl);             totedges--;
+                                               ok = true;
+                                       }
+                                       else if (med->v1 == startVert) {
+                                               startVert = med->v2;
+                                               prependPolyLineVert(&polyline, startVert);  totpoly++;
+                                               BLI_freelinkN(&edges, edl);                 totedges--;
+                                               ok = true;
+                                       }
+                                       else if (med->v2 == startVert) {
+                                               startVert = med->v1;
+                                               prependPolyLineVert(&polyline, startVert);  totpoly++;
+                                               BLI_freelinkN(&edges, edl);                 totedges--;
+                                               ok = true;
+                                       }
+                                       edl = edl_prev;
+                               }
+                       }
+                       /* Now we have a polyline, make into a curve */
+                       if (startVert == endVert) {
+                               BLI_freelinkN(&polyline, polyline.last);
+                               totpoly--;
+                               closed = true;
+                       }
+                       /* --- nurbs --- */
+                       {
+                               Nurb *nu;
+                               BPoint *bp;
+                               VertLink *vl;
+                               /* create new 'nurb' within the curve */
+                               nu = (Nurb *)MEM_callocN(sizeof(Nurb), "MeshNurb");
+                               nu->pntsu = totpoly;
+                               nu->pntsv = 1;
+                               nu->orderu = 4;
+                               nu->flagu = CU_NURB_ENDPOINT | (closed ? CU_NURB_CYCLIC : 0);  /* endpoint */
+                               nu->resolu = 12;
+                               nu->bp = (BPoint *)MEM_calloc_arrayN(totpoly, sizeof(BPoint), "bpoints");
+                               /* add points */
+                               vl = polyline.first;
+                               for (i = 0, bp = nu->bp; i < totpoly; i++, bp++, vl = (VertLink *)vl->next) {
+                                       copy_v3_v3(bp->vec, mvert[vl->index].co);
+                                       bp->f1 = SELECT;
+                                       bp->radius = bp->weight = 1.0;
+                               }
+                               BLI_freelistN(&polyline);
+                               /* add nurb to curve */
+                               BLI_addtail(nurblist, nu);
+                       }
+                       /* --- done with nurbs --- */
+               }
+       }
+ }
 -      DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_MESH);
++void BKE_mesh_to_curve(Depsgraph *depsgraph, Scene *scene, Object *ob)
+ {
+       /* make new mesh data from the original copy */
 -        Main *bmain, Scene *sce, Object *ob,
 -        int apply_modifiers, int settings, int calc_tessface, int calc_undeformed)
++      DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_MESH);
+       ListBase nurblist = {NULL, NULL};
+       bool needsFree = false;
+       BKE_mesh_to_curve_nurblist(dm, &nurblist, 0);
+       BKE_mesh_to_curve_nurblist(dm, &nurblist, 1);
+       if (nurblist.first) {
+               Curve *cu = BKE_curve_add(G.main, ob->id.name + 2, OB_CURVE);
+               cu->flag |= CU_3D;
+               cu->nurb = nurblist;
+               id_us_min(&((Mesh *)ob->data)->id);
+               ob->data = cu;
+               ob->type = OB_CURVE;
+               /* curve objects can't contain DM in usual cases, we could free memory */
+               needsFree = true;
+       }
+       dm->needsFree = needsFree;
+       dm->release(dm);
+       if (needsFree) {
+               ob->derivedFinal = NULL;
+               /* curve object could have got bounding box only in special cases */
+               if (ob->bb) {
+                       MEM_freeN(ob->bb);
+                       ob->bb = NULL;
+               }
+       }
+ }
+ /* settings: 1 - preview, 2 - render */
+ Mesh *BKE_mesh_new_from_object(
 -      const bool render = (settings == eModifierMode_Render);
++        Depsgraph *depsgraph, Main *bmain, Scene *sce, Object *ob,
++        const bool apply_modifiers, const bool calc_tessface, const bool calc_undeformed)
+ {
+       Mesh *tmpmesh;
+       Curve *tmpcu = NULL, *copycu;
+       int i;
 -                      BKE_displist_make_curveTypes_forRender(sce, tmpobj, &dispbase, &derivedFinal, false, render);
++      const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+       const bool cage = !apply_modifiers;
+       bool do_mat_id_data_us = true;
+       /* perform the mesh extraction based on type */
+       switch (ob->type) {
+               case OB_FONT:
+               case OB_CURVE:
+               case OB_SURF:
+               {
+                       ListBase dispbase = {NULL, NULL};
+                       DerivedMesh *derivedFinal = NULL;
+                       int uv_from_orco;
+                       /* copies object and modifiers (but not the data) */
+                       Object *tmpobj;
+                       /* TODO: make it temp copy outside bmain! */
+                       BKE_id_copy_ex(bmain, &ob->id, (ID **)&tmpobj, LIB_ID_COPY_CACHES, false);
+                       tmpcu = (Curve *)tmpobj->data;
+                       id_us_min(&tmpcu->id);
+                       /* Copy cached display list, it might be needed by the stack evaluation.
+                        * Ideally stack should be able to use render-time display list, but doing
+                        * so is quite tricky and not safe so close to the release.
+                        *
+                        * TODO(sergey): Look into more proper solution.
+                        */
+                       if (ob->curve_cache != NULL) {
+                               if (tmpobj->curve_cache == NULL) {
+                                       tmpobj->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
+                               }
+                               BKE_displist_copy(&tmpobj->curve_cache->disp, &ob->curve_cache->disp);
+                       }
+                       /* if getting the original caged mesh, delete object modifiers */
+                       if (cage)
+                               BKE_object_free_modifiers(tmpobj, 0);
+                       /* copies the data */
+                       copycu = tmpobj->data = BKE_curve_copy(bmain, (Curve *) ob->data);
+                       /* make sure texture space is calculated for a copy of curve,
+                        * it will be used for the final result.
+                        */
+                       BKE_curve_texspace_calc(copycu);
+                       /* temporarily set edit so we get updates from edit mode, but
+                        * also because for text datablocks copying it while in edit
+                        * mode gives invalid data structures */
+                       copycu->editfont = tmpcu->editfont;
+                       copycu->editnurb = tmpcu->editnurb;
+                       /* get updated display list, and convert to a mesh */
 -                       * if it didn't the curve did not have any segments or otherwise 
++                      BKE_displist_make_curveTypes_forRender(depsgraph, sce, tmpobj, &dispbase, &derivedFinal, false, render);
+                       copycu->editfont = NULL;
+                       copycu->editnurb = NULL;
+                       tmpobj->derivedFinal = derivedFinal;
+                       /* convert object type to mesh */
+                       uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
+                       BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2);
+                       tmpmesh = tmpobj->data;
+                       BKE_displist_free(&dispbase);
+                       /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked.
 -                              /* TODO(sergey): This is gonna to work for until EvaluationContext
 -                               *               only contains for_render flag. As soon as CoW is
 -                               *               implemented, this is to be rethought.
 -                               */
 -                              EvaluationContext eval_ctx;
 -                              DEG_evaluation_context_init(&eval_ctx, DAG_EVAL_RENDER);
 -                              BKE_displist_make_mball_forRender(&eval_ctx, sce, ob, &disp);
++                       * if it didn't the curve did not have any segments or otherwise
+                        * would have generated an empty mesh */
+                       if (tmpobj->type != OB_MESH) {
+                               BKE_libblock_free_us(bmain, tmpobj);
+                               return NULL;
+                       }
+                       BKE_libblock_free_us(bmain, tmpobj);
+                       /* XXX The curve to mesh conversion is convoluted... But essentially, BKE_mesh_from_nurbs_displist()
+                        *     already transfers the ownership of materials from the temp copy of the Curve ID to the new
+                        *     Mesh ID, so we do not want to increase materials' usercount later. */
+                       do_mat_id_data_us = false;
+                       break;
+               }
+               case OB_MBALL:
+               {
+                       /* metaballs don't have modifiers, so just convert to mesh */
+                       Object *basis_ob = BKE_mball_basis_find(sce, ob);
+                       /* todo, re-generatre for render-res */
+                       /* metaball_polygonize(scene, ob) */
+                       if (ob != basis_ob)
+                               return NULL;  /* only do basis metaball */
+                       tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2);
+                       /* BKE_mesh_add gives us a user count we don't need */
+                       id_us_min(&tmpmesh->id);
+                       if (render) {
+                               ListBase disp = {NULL, NULL};
 -                                      dm = mesh_create_derived_render(sce, ob, mask);
++                              BKE_displist_make_mball_forRender(depsgraph, sce, ob, &disp);
+                               BKE_mesh_from_metaball(&disp, tmpmesh);
+                               BKE_displist_free(&disp);
+                       }
+                       else {
+                               ListBase disp = {NULL, NULL};
+                               if (ob->curve_cache) {
+                                       disp = ob->curve_cache->disp;
+                               }
+                               BKE_mesh_from_metaball(&disp, tmpmesh);
+                       }
+                       BKE_mesh_texspace_copy_from_object(tmpmesh, ob);
+                       break;
+               }
+               case OB_MESH:
+                       /* copies object and modifiers (but not the data) */
+                       if (cage) {
+                               /* copies the data */
+                               tmpmesh = BKE_mesh_copy(bmain, ob->data);
+                               /* XXX BKE_mesh_copy() already handles materials usercount. */
+                               do_mat_id_data_us = false;
+                       }
+                       /* if not getting the original caged mesh, get final derived mesh */
+                       else {
+                               /* Make a dummy mesh, saves copying */
+                               DerivedMesh *dm;
+                               /* CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; */
+                               CustomDataMask mask = CD_MASK_MESH; /* this seems more suitable, exporter,
+                                                                    * for example, needs CD_MASK_MDEFORMVERT */
+                               if (calc_undeformed)
+                                       mask |= CD_MASK_ORCO;
+                               /* Write the display mesh into the dummy mesh */
+                               if (render)
 -                                      dm = mesh_create_derived_view(sce, ob, mask);
++                                      dm = mesh_create_derived_render(depsgraph, sce, ob, mask);
+                               else
++                                      dm = mesh_create_derived_view(depsgraph, sce, ob, mask);
+                               tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2);
+                               DM_to_mesh(dm, tmpmesh, ob, mask, true);
+                               /* Copy autosmooth settings from original mesh. */
+                               Mesh *me = (Mesh *)ob->data;
+                               tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH);
+                               tmpmesh->smoothresh = me->smoothresh;
+                       }
+                       /* BKE_mesh_add/copy gives us a user count we don't need */
+                       id_us_min(&tmpmesh->id);
+                       break;
+               default:
+                       /* "Object does not have geometry data") */
+                       return NULL;
+       }
+       /* Copy materials to new mesh */
+       switch (ob->type) {
+               case OB_SURF:
+               case OB_FONT:
+               case OB_CURVE:
+                       tmpmesh->totcol = tmpcu->totcol;
+                       /* free old material list (if it exists) and adjust user counts */
+                       if (tmpcu->mat) {
+                               for (i = tmpcu->totcol; i-- > 0; ) {
+                                       /* are we an object material or data based? */
+                                       tmpmesh->mat[i] = give_current_material(ob, i + 1);
+                                       if (((ob->matbits && ob->matbits[i]) || do_mat_id_data_us)  && tmpmesh->mat[i]) {
+                                               id_us_plus(&tmpmesh->mat[i]->id);
+                                       }
+                               }
+                       }
+                       break;
+               case OB_MBALL:
+               {
+                       MetaBall *tmpmb = (MetaBall *)ob->data;
+                       tmpmesh->mat = MEM_dupallocN(tmpmb->mat);
+                       tmpmesh->totcol = tmpmb->totcol;
+                       /* free old material list (if it exists) and adjust user counts */
+                       if (tmpmb->mat) {
+                               for (i = tmpmb->totcol; i-- > 0; ) {
+                                       /* are we an object material or data based? */
+                                       tmpmesh->mat[i] = give_current_material(ob, i + 1);
+                                       if (((ob->matbits && ob->matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) {
+                                               id_us_plus(&tmpmesh->mat[i]->id);
+                                       }
+                               }
+                       }
+                       break;
+               }
+               case OB_MESH:
+                       if (!cage) {
+                               Mesh *origmesh = ob->data;
+                               tmpmesh->flag = origmesh->flag;
+                               tmpmesh->mat = MEM_dupallocN(origmesh->mat);
+                               tmpmesh->totcol = origmesh->totcol;
+                               tmpmesh->smoothresh = origmesh->smoothresh;
+                               if (origmesh->mat) {
+                                       for (i = origmesh->totcol; i-- > 0; ) {
+                                               /* are we an object material or data based? */
+                                               tmpmesh->mat[i] = give_current_material(ob, i + 1);
+                                               if (((ob->matbits && ob->matbits[i]) || do_mat_id_data_us)  && tmpmesh->mat[i]) {
+                                                       id_us_plus(&tmpmesh->mat[i]->id);
+                                               }
+                                       }
+                               }
+                       }
+                       break;
+       } /* end copy materials */
+       if (calc_tessface) {
+               /* cycles and exporters rely on this still */
+               BKE_mesh_tessface_ensure(tmpmesh);
+       }
+       return tmpmesh;
+ }