Python API: add loop triangles access, remove tessfaces.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 6 Sep 2018 12:28:14 +0000 (14:28 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Wed, 10 Oct 2018 15:43:44 +0000 (17:43 +0200)
Loop triangles are tessellated triangles create from polygons, for renderers
or exporters that need to match Blender's polygon tesselation exactly. These
are a read-only runtime cache.

Tessfaces are a legacy data structure from before Blender supported n-gons,
and were already mostly removed from the C code.

Details on porting code to loop triangles is in the release notes.

Differential Revision: https://developer.blender.org/D3539

21 files changed:
doc/python_api/rst/include__bmesh.rst
doc/python_api/rst/info_best_practice.rst
doc/python_api/rst/info_gotcha.rst
intern/cycles/blender/blender_curves.cpp
intern/cycles/blender/blender_mesh.cpp
intern/cycles/blender/blender_util.h
release/scripts/modules/bpy_extras/mesh_utils.py
release/scripts/modules/bpy_types.py
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/mesh_convert.c
source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
source/blender/makesdna/DNA_meshdata_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_internal.h
source/blender/makesrna/intern/rna_main_api.c
source/blender/makesrna/intern/rna_mesh.c
source/blender/makesrna/intern/rna_mesh_api.c
source/blender/makesrna/intern/rna_object_api.c
source/blender/python/bmesh/bmesh_py_api.c
source/blender/python/bmesh/bmesh_py_types.c
source/blender/render/intern/source/bake_api.c

index bed374bf7b6b93c405890f09f2ea60d4cafbee24..d1356a5e5d9a9722d2e6d95811dcf5287d241fd4 100644 (file)
@@ -83,7 +83,7 @@ When writing scripts that operate on editmode data you will normally want to re-
 running the  script, this needs to be called explicitly.
 
 The BMesh its self does not store the triangulated faces, they are stored in the :class:`bpy.types.Mesh`,
-to refresh tessellation faces call :class:`bpy.types.Mesh.calc_tessface`.
+to refresh tessellation triangles call :class:`bpy.types.Mesh.calc_loop_triangles`.
 
 
 CustomData Access
index 418f636030c9f45fac1f5681e1874c58da9cdc30..b9c9f234b725f958b02390b401dc11654b51a1fd 100644 (file)
@@ -164,26 +164,26 @@ for list removal, but these are slower.
 Sometimes its faster (but more memory hungry) to just rebuild the list.
 
 
-Say you want to remove all triangular faces in a list.
+Say you want to remove all triangular polygons in a list.
 
 Rather than...
 
 .. code-block:: python
 
-   faces = mesh.tessfaces[:]  # make a list copy of the meshes faces
-   f_idx = len(faces)     # Loop backwards
-   while f_idx:           # while the value is not 0
-       f_idx -= 1
+   polygons = mesh.polygons[:]  # make a list copy of the meshes polygons
+   p_idx = len(polygons)     # Loop backwards
+   while p_idx:           # while the value is not 0
+       p_idx -= 1
 
-       if len(faces[f_idx].vertices) == 3:
-           faces.pop(f_idx)  # remove the triangle
+       if len(polygons[p_idx].vertices) == 3:
+           polygons.pop(p_idx)  # remove the triangle
 
 
 It's faster to build a new list with list comprehension.
 
 .. code-block:: python
 
-   faces = [f for f in mesh.tessfaces if len(f.vertices) != 3]
+   polygons = [p for p in mesh.polygons if len(p.vertices) != 3]
 
 
 Adding List Items
index 1917273d85c5b11d5fa096c436022714d6f47183..bbccc27b2273afff355b535d040a6452020c0dea 100644 (file)
@@ -173,25 +173,25 @@ In this situation you can...
 
 .. _info_gotcha_mesh_faces:
 
-N-Gons and Tessellation Faces
-=============================
+N-Gons and Tessellation
+=======================
 
 Since 2.63 NGons are supported, this adds some complexity
-since in some cases you need to access triangles/quads still (some exporters for example).
+since in some cases you need to access triangles still (some exporters for example).
 
 There are now 3 ways to access faces:
 
 - :class:`bpy.types.MeshPolygon` -
   this is the data structure which now stores faces in object mode
   (access as ``mesh.polygons`` rather than ``mesh.faces``).
-- :class:`bpy.types.MeshTessFace` -
-  the result of triangulating (tessellated) polygons,
-  the main method of face access in 2.62 or older (access as ``mesh.tessfaces``).
+- :class:`bpy.types.MeshLoopTriangle` -
+  the result of tessellating polygons into triangles
+  (access as ``mesh.loop_triangles``).
 - :class:`bmesh.types.BMFace` -
   the polygons as used in editmode.
 
 For the purpose of the following documentation,
-these will be referred to as polygons, tessfaces and bmesh-faces respectively.
+these will be referred to as polygons, loop triangles and bmesh-faces respectively.
 
 5+ sided faces will be referred to as ``ngons``.
 
@@ -234,13 +234,8 @@ All 3 datatypes can be used for face creation.
 
 - polygons are the most efficient way to create faces but the data structure is _very_ rigid and inflexible,
   you must have all your vertes and faces ready and create them all at once.
-  This is further complicated by the fact that each polygon does not store its own verts (as with tessfaces),
+  This is further complicated by the fact that each polygon does not store its own verts,
   rather they reference an index and size in :class:`bpy.types.Mesh.loops` which are a fixed array too.
-- tessfaces ideally should not be used for creating faces since they are really only tessellation cache of polygons,
-  however for scripts upgrading from 2.62 this is by far the most straightforward option.
-  This works by creating tessfaces and when finished -
-  they can be converted into polygons by calling :class:`bpy.types.Mesh.update`.
-  The obvious limitation is ngons can't be created this way.
 - bmesh-faces are most likely the easiest way for new scripts to create faces,
   since faces can be added one by one and the api has features intended for mesh manipulation.
   While :class:`bmesh.types.BMesh` uses more memory it can be managed by only operating on one mesh at a time.
@@ -271,30 +266,6 @@ the choice mostly depends on whether the target format supports ngons or not.
   since using bmesh gives some overhead because its not the native storage format in object mode.
 
 
-Upgrading Importers from 2.62
------------------------------
-
-Importers can be upgraded to work with only minor changes.
-
-The main change to be made is used the tessellation versions of each attribute.
-
-- mesh.faces --> :class:`bpy.types.Mesh.tessfaces`
-- mesh.uv_textures --> :class:`bpy.types.Mesh.tessface_uv_textures`
-- mesh.vertex_colors --> :class:`bpy.types.Mesh.tessface_vertex_colors`
-
-Once the data is created call :class:`bpy.types.Mesh.update` to convert the tessfaces into polygons.
-
-
-Upgrading Exporters from 2.62
------------------------------
-
-For exporters the most direct way to upgrade is to use tessfaces as with importing
-however its important to know that tessfaces may **not** exist for a mesh,
-the array will be empty as if there are no faces.
-
-So before accessing tessface data call: :class:`bpy.types.Mesh.update` ``(calc_tessface=True)``.
-
-
 EditBones, PoseBones, Bone... Bones
 ===================================
 
index 0bf90297263fd0422f7c943b74997053215c4793..5e4522af6e194a065eac46924eda387954a1eea5 100644 (file)
@@ -247,11 +247,11 @@ static bool ObtainCacheParticleUV(Mesh *mesh,
                                b_psys.particles.begin(b_pa);
                                for(; pa_no < totparts+totchild; pa_no++) {
                                        /* Add UVs */
-                                       BL::Mesh::tessface_uv_textures_iterator l;
-                                       b_mesh->tessface_uv_textures.begin(l);
+                                       BL::Mesh::uv_layers_iterator l;
+                                       b_mesh->uv_layers.begin(l);
 
                                        float3 uv = make_float3(0.0f, 0.0f, 0.0f);
-                                       if(b_mesh->tessface_uv_textures.length())
+                                       if(b_mesh->uv_layers.length())
                                                b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
                                        CData->curve_uv.push_back_slow(uv);
 
@@ -306,11 +306,11 @@ static bool ObtainCacheParticleVcol(Mesh *mesh,
                                b_psys.particles.begin(b_pa);
                                for(; pa_no < totparts+totchild; pa_no++) {
                                        /* Add vertex colors */
-                                       BL::Mesh::tessface_vertex_colors_iterator l;
-                                       b_mesh->tessface_vertex_colors.begin(l);
+                                       BL::Mesh::vertex_colors_iterator l;
+                                       b_mesh->vertex_colors.begin(l);
 
                                        float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
-                                       if(b_mesh->tessface_vertex_colors.length())
+                                       if(b_mesh->vertex_colors.length())
                                                b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
                                        CData->curve_vcol.push_back_slow(vcol);
 
@@ -968,10 +968,10 @@ void BlenderSync::sync_curves(Mesh *mesh,
 
        /* create vertex color attributes */
        if(!motion) {
-               BL::Mesh::tessface_vertex_colors_iterator l;
+               BL::Mesh::vertex_colors_iterator l;
                int vcol_num = 0;
 
-               for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) {
+               for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) {
                        if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
                                continue;
 
@@ -1005,10 +1005,10 @@ void BlenderSync::sync_curves(Mesh *mesh,
 
        /* create UV attributes */
        if(!motion) {
-               BL::Mesh::tessface_uv_textures_iterator l;
+               BL::Mesh::uv_layers_iterator l;
                int uv_num = 0;
 
-               for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l, uv_num++) {
+               for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, uv_num++) {
                        bool active_render = l->active_render();
                        AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
                        ustring name = ustring(l->name().c_str());
index c7378e711835b6aa98d9aad7091e20bb253848d0..b97c250adf678b45c1691e927ef49b686b153899 100644 (file)
 
 CCL_NAMESPACE_BEGIN
 
-/* Per-face bit flags. */
-enum {
-       /* Face has no special flags. */
-       FACE_FLAG_NONE      = (0 << 0),
-       /* Quad face was split using 1-3 diagonal. */
-       FACE_FLAG_DIVIDE_13 = (1 << 0),
-       /* Quad face was split using 2-4 diagonal. */
-       FACE_FLAG_DIVIDE_24 = (1 << 1),
-};
-
-/* Get vertex indices to create triangles from a given face.
- *
- * Two triangles has vertex indices in the original Blender-side face.
- * If face is already a quad tri_b will not be initialized.
- */
-inline void face_split_tri_indices(const int face_flag,
-                                   int tri_a[3],
-                                   int tri_b[3])
-{
-       if(face_flag & FACE_FLAG_DIVIDE_24) {
-               tri_a[0] = 0;
-               tri_a[1] = 1;
-               tri_a[2] = 3;
-
-               tri_b[0] = 2;
-               tri_b[1] = 3;
-               tri_b[2] = 1;
-       }
-       else {
-               /* Quad with FACE_FLAG_DIVIDE_13 or single triangle. */
-               tri_a[0] = 0;
-               tri_a[1] = 1;
-               tri_a[2] = 2;
-
-               tri_b[0] = 0;
-               tri_b[1] = 2;
-               tri_b[2] = 3;
-       }
-}
-
 /* Tangent Space */
 
 struct MikkUserData {
@@ -379,8 +339,6 @@ static void create_mesh_volume_attributes(Scene *scene,
 static void attr_create_vertex_color(Scene *scene,
                                      Mesh *mesh,
                                      BL::Mesh& b_mesh,
-                                     const vector<int>& nverts,
-                                     const vector<int>& face_flags,
                                      bool subdivision)
 {
        if(subdivision) {
@@ -401,15 +359,15 @@ static void attr_create_vertex_color(Scene *scene,
                                int n = p->loop_total();
                                for(int i = 0; i < n; i++) {
                                        float3 color = get_float3(l->data[p->loop_start() + i].color());
-                                       /* Encode vertex color using the sRGB curve. */
+                                       /* Compress/encode vertex color using the sRGB curve. */
                                        *(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color));
                                }
                        }
                }
        }
        else {
-               BL::Mesh::tessface_vertex_colors_iterator l;
-               for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
+               BL::Mesh::vertex_colors_iterator l;
+               for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
                        if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
                                continue;
 
@@ -417,35 +375,20 @@ static void attr_create_vertex_color(Scene *scene,
                                                               TypeDesc::TypeColor,
                                                               ATTR_ELEMENT_CORNER_BYTE);
 
-                       BL::MeshColorLayer::data_iterator c;
+                       BL::Mesh::loop_triangles_iterator t;
                        uchar4 *cdata = attr->data_uchar4();
-                       size_t i = 0;
-
-                       for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
-                               int tri_a[3], tri_b[3];
-                               face_split_tri_indices(face_flags[i], tri_a, tri_b);
-
-                               /* Encode vertex color using the sRGB curve. */
-                               uchar4 colors[4];
-                               colors[0] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color1())));
-                               colors[1] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color2())));
-                               colors[2] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color3())));
-                               if(nverts[i] == 4) {
-                                       colors[3] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color4())));
-                               }
 
-                               cdata[0] = colors[tri_a[0]];
-                               cdata[1] = colors[tri_a[1]];
-                               cdata[2] = colors[tri_a[2]];
-
-                               if(nverts[i] == 4) {
-                                       cdata[3] = colors[tri_b[0]];
-                                       cdata[4] = colors[tri_b[1]];
-                                       cdata[5] = colors[tri_b[2]];
-                                       cdata += 6;
-                               }
-                               else
-                                       cdata += 3;
+                       for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
+                               int3 li = get_int3(t->loops());
+                               float3 c1 = get_float3(l->data[li[0]].color());
+                               float3 c2 = get_float3(l->data[li[1]].color());
+                               float3 c3 = get_float3(l->data[li[2]].color());
+
+                               /* Compress/encode vertex color using the sRGB curve. */
+                               cdata[0] = color_float_to_byte(color_srgb_to_linear_v3(c1));
+                               cdata[1] = color_float_to_byte(color_srgb_to_linear_v3(c2));
+                               cdata[2] = color_float_to_byte(color_srgb_to_linear_v3(c3));
+                               cdata += 3;
                        }
                }
        }
@@ -454,14 +397,12 @@ static void attr_create_vertex_color(Scene *scene,
 /* Create uv map attributes. */
 static void attr_create_uv_map(Scene *scene,
                                Mesh *mesh,
-                               BL::Mesh& b_mesh,
-                               const vector<int>& nverts,
-                               const vector<int>& face_flags)
+                               BL::Mesh& b_mesh)
 {
-       if(b_mesh.tessface_uv_textures.length() != 0) {
-               BL::Mesh::tessface_uv_textures_iterator l;
+       if(b_mesh.uv_layers.length() != 0) {
+               BL::Mesh::uv_layers_iterator l;
 
-               for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
+               for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l) {
                        const bool active_render = l->active_render();
                        AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
                        ustring uv_name = ustring(l->name().c_str());
@@ -493,33 +434,15 @@ static void attr_create_uv_map(Scene *scene,
                                                                       ATTR_ELEMENT_CORNER);
                                }
 
-                               BL::MeshTextureFaceLayer::data_iterator t;
+                               BL::Mesh::loop_triangles_iterator t;
                                float3 *fdata = uv_attr->data_float3();
-                               size_t i = 0;
-
-                               for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
-                                       int tri_a[3], tri_b[3];
-                                       face_split_tri_indices(face_flags[i], tri_a, tri_b);
-
-                                       float3 uvs[4];
-                                       uvs[0] = get_float3(t->uv1());
-                                       uvs[1] = get_float3(t->uv2());
-                                       uvs[2] = get_float3(t->uv3());
-                                       if(nverts[i] == 4) {
-                                               uvs[3] = get_float3(t->uv4());
-                                       }
 
-                                       fdata[0] = uvs[tri_a[0]];
-                                       fdata[1] = uvs[tri_a[1]];
-                                       fdata[2] = uvs[tri_a[2]];
+                               for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
+                                       int3 li = get_int3(t->loops());
+                                       fdata[0] = get_float3(l->data[li[0]].uv());
+                                       fdata[1] = get_float3(l->data[li[1]].uv());
+                                       fdata[2] = get_float3(l->data[li[2]].uv());
                                        fdata += 3;
-
-                                       if(nverts[i] == 4) {
-                                               fdata[0] = uvs[tri_b[0]];
-                                               fdata[1] = uvs[tri_b[1]];
-                                               fdata[2] = uvs[tri_b[2]];
-                                               fdata += 3;
-                                       }
                                }
                        }
 
@@ -822,7 +745,7 @@ static void create_mesh(Scene *scene,
 {
        /* count vertices and faces */
        int numverts = b_mesh.vertices.length();
-       int numfaces = (!subdivision) ? b_mesh.tessfaces.length() : b_mesh.polygons.length();
+       int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length();
        int numtris = 0;
        int numcorners = 0;
        int numngons = 0;
@@ -834,14 +757,10 @@ static void create_mesh(Scene *scene,
        }
 
        BL::Mesh::vertices_iterator v;
-       BL::Mesh::tessfaces_iterator f;
        BL::Mesh::polygons_iterator p;
 
        if(!subdivision) {
-               for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
-                       int4 vi = get_int4(f->vertices_raw());
-                       numtris += (vi[3] == 0)? 1: 2;
-               }
+               numtris = numfaces;
        }
        else {
                for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
@@ -869,7 +788,7 @@ static void create_mesh(Scene *scene,
        /* create generated coordinates from undeformed coordinates */
        const bool need_default_tangent =
                (subdivision == false) &&
-               (b_mesh.tessface_uv_textures.length() == 0) &&
+               (b_mesh.uv_layers.length() == 0) &&
                (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT));
        if(mesh->need_attribute(scene, ATTR_STD_GENERATED) ||
           need_default_tangent)
@@ -890,19 +809,21 @@ static void create_mesh(Scene *scene,
 
        /* create faces */
        vector<int> nverts(numfaces);
-       vector<int> face_flags(numfaces, FACE_FLAG_NONE);
-       int fi = 0;
 
        if(!subdivision) {
-               for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
-                       int4 vi = get_int4(f->vertices_raw());
-                       int n = (vi[3] == 0)? 3: 4;
-                       int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
-                       bool smooth = f->use_smooth() || use_loop_normals;
+               BL::Mesh::loop_triangles_iterator t;
+               int ti = 0;
+
+               for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t, ++ti) {
+                       BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()];
+                       int3 vi = get_int3(t->vertices());
+
+                       int shader = clamp(p.material_index(), 0, used_shaders.size()-1);
+                       bool smooth = p.use_smooth() || use_loop_normals;
 
                        if(use_loop_normals) {
-                               BL::Array<float, 12> loop_normals = f->split_normals();
-                               for(int i = 0; i < n; i++) {
+                               BL::Array<float, 9> loop_normals = t->split_normals();
+                               for(int i = 0; i < 3; i++) {
                                        N[vi[i]] = make_float3(loop_normals[i * 3],
                                                               loop_normals[i * 3 + 1],
                                                               loop_normals[i * 3 + 2]);
@@ -913,25 +834,8 @@ static void create_mesh(Scene *scene,
                         *
                         * NOTE: Autosmooth is already taken care about.
                         */
-                       if(n == 4) {
-                               if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) ||
-                                  is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])))
-                               {
-                                       mesh->add_triangle(vi[0], vi[1], vi[3], shader, smooth);
-                                       mesh->add_triangle(vi[2], vi[3], vi[1], shader, smooth);
-                                       face_flags[fi] |= FACE_FLAG_DIVIDE_24;
-                               }
-                               else {
-                                       mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
-                                       mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
-                                       face_flags[fi] |= FACE_FLAG_DIVIDE_13;
-                               }
-                       }
-                       else {
-                               mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
-                       }
-
-                       nverts[fi] = n;
+                       mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
+                       nverts[ti] = 3;
                }
        }
        else {
@@ -957,13 +861,13 @@ static void create_mesh(Scene *scene,
         * The calculate functions will check whether they're needed or not.
         */
        attr_create_pointiness(scene, mesh, b_mesh, subdivision);
-       attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags, subdivision);
+       attr_create_vertex_color(scene, mesh, b_mesh, subdivision);
 
        if(subdivision) {
                attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs);
        }
        else {
-               attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags);
+               attr_create_uv_map(scene, mesh, b_mesh);
        }
 
        /* for volume objects, create a matrix to transform from object space to
index 7f3bfb7698d978ce427e77ab4a7678752d19d46a..b43a186a9b3d75186dc6ef0ed57dbba86694854c 100644 (file)
@@ -83,7 +83,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
                        }
                }
                if(subdivision_type == Mesh::SUBDIVISION_NONE) {
-                       me.calc_tessface(true);
+                       me.calc_loop_triangles();
                }
        }
        return me;
index a7872daca6703faa6e910ea4661005867abdd6c4..a09282da2fe7b9a30299573a73ab62f425117847 100644 (file)
 
 __all__ = (
     "mesh_linked_uv_islands",
-    "mesh_linked_tessfaces",
+    "mesh_linked_triangles",
     "edge_face_count_dict",
     "edge_face_count",
-    "edge_loops_from_tessfaces",
     "edge_loops_from_edges",
     "ngon_tessellate",
-    "face_random_points",
+    "triangle_random_points",
 )
 
 
@@ -90,41 +89,41 @@ def mesh_linked_uv_islands(mesh):
     return poly_islands
 
 
-def mesh_linked_tessfaces(mesh):
+def mesh_linked_triangles(mesh):
     """
-    Splits the mesh into connected faces, use this for separating cubes from
+    Splits the mesh into connected triangles, use this for separating cubes from
     other mesh elements within 1 mesh datablock.
 
     :arg mesh: the mesh used to group with.
     :type mesh: :class:`bpy.types.Mesh`
-    :return: lists of lists containing faces.
+    :return: lists of lists containing triangles.
     :rtype: list
     """
 
     # Build vert face connectivity
-    vert_faces = [[] for i in range(len(mesh.vertices))]
-    for f in mesh.tessfaces:
-        for v in f.vertices:
-            vert_faces[v].append(f)
+    vert_tris = [[] for i in range(len(mesh.vertices))]
+    for t in mesh.loop_triangles:
+        for v in t.vertices:
+            vert_tris[v].append(t)
 
-    # sort faces into connectivity groups
-    face_groups = [[f] for f in mesh.tessfaces]
-    # map old, new face location
-    face_mapping = list(range(len(mesh.tessfaces)))
+    # sort triangles into connectivity groups
+    tri_groups = [[t] for t in mesh.loop_triangles]
+    # map old, new tri location
+    tri_mapping = list(range(len(mesh.loop_triangles)))
 
-    # Now clump faces iteratively
+    # Now clump triangles iteratively
     ok = True
     while ok:
         ok = False
 
-        for i, f in enumerate(mesh.tessfaces):
-            mapped_index = face_mapping[f.index]
-            mapped_group = face_groups[mapped_index]
+        for i, t in enumerate(mesh.loop_triangles):
+            mapped_index = tri_mapping[t.index]
+            mapped_group = tri_groups[mapped_index]
 
-            for v in f.vertices:
-                for nxt_f in vert_faces[v]:
-                    if nxt_f != f:
-                        nxt_mapped_index = face_mapping[nxt_f.index]
+            for v in t.vertices:
+                for nxt_t in vert_tris[v]:
+                    if nxt_t != t:
+                        nxt_mapped_index = tri_mapping[nxt_t.index]
 
                         # We are not a part of the same group
                         if mapped_index != nxt_mapped_index:
@@ -132,18 +131,18 @@ def mesh_linked_tessfaces(mesh):
 
                             # Assign mapping to this group so they
                             # all map to this group
-                            for grp_f in face_groups[nxt_mapped_index]:
-                                face_mapping[grp_f.index] = mapped_index
+                            for grp_t in tri_groups[nxt_mapped_index]:
+                                tri_mapping[grp_t.index] = mapped_index
 
-                            # Move faces into this group
-                            mapped_group.extend(face_groups[nxt_mapped_index])
+                            # Move triangles into this group
+                            mapped_group.extend(tri_groups[nxt_mapped_index])
 
                             # remove reference to the list
-                            face_groups[nxt_mapped_index] = None
+                            tri_groups[nxt_mapped_index] = None
 
-    # return all face groups that are not null
-    # this is all the faces that are connected in their own lists.
-    return [fg for fg in face_groups if fg]
+    # return all tri groups that are not null
+    # this is all the triangles that are connected in their own lists.
+    return [tg for tg in tri_groups if tg]
 
 
 def edge_face_count_dict(mesh):
@@ -177,87 +176,6 @@ def edge_face_count(mesh):
     return [get(edge_face_count, ed.key, 0) for ed in mesh.edges]
 
 
-def edge_loops_from_tessfaces(mesh, tessfaces=None, seams=()):
-    """
-    Edge loops defined by faces
-
-    Takes me.tessfaces or a list of faces and returns the edge loops
-    These edge loops are the edges that sit between quads, so they don't touch
-    1 quad, note: not connected will make 2 edge loops,
-    both only containing 2 edges.
-
-    return a list of edge key lists
-    [[(0, 1), (4, 8), (3, 8)], ...]
-
-    :arg mesh: the mesh used to get edge loops from.
-    :type mesh: :class:`bpy.types.Mesh`
-    :arg tessfaces: optional face list to only use some of the meshes faces.
-    :type tessfaces: :class:`bpy.types.MeshTessFace`, sequence or or NoneType
-    :return: return a list of edge vertex index lists.
-    :rtype: list
-    """
-
-    OTHER_INDEX = 2, 3, 0, 1  # opposite face index
-
-    if tessfaces is None:
-        tessfaces = mesh.tessfaces
-
-    edges = {}
-
-    for f in tessfaces:
-        if len(f.vertices) == 4:
-            edge_keys = f.edge_keys
-            for i, edkey in enumerate(f.edge_keys):
-                edges.setdefault(edkey, []).append(edge_keys[OTHER_INDEX[i]])
-
-    for edkey in seams:
-        edges[edkey] = []
-
-    # Collect edge loops here
-    edge_loops = []
-
-    for edkey, ed_adj in edges.items():
-        if 0 < len(ed_adj) < 3:  # 1 or 2
-            # Seek the first edge
-            context_loop = [edkey, ed_adj[0]]
-            edge_loops.append(context_loop)
-            if len(ed_adj) == 2:
-                other_dir = ed_adj[1]
-            else:
-                other_dir = None
-
-            del ed_adj[:]
-
-            flipped = False
-
-            while 1:
-                # from knowing the last 2, look for the next.
-                ed_adj = edges[context_loop[-1]]
-                if len(ed_adj) != 2:
-                    # the original edge had 2 other edges
-                    if other_dir and flipped is False:
-                        flipped = True  # only flip the list once
-                        context_loop.reverse()
-                        del ed_adj[:]
-                        context_loop.append(other_dir)  # save 1 look-up
-
-                        ed_adj = edges[context_loop[-1]]
-                        if len(ed_adj) != 2:
-                            del ed_adj[:]
-                            break
-                    else:
-                        del ed_adj[:]
-                        break
-
-                i = ed_adj.index(context_loop[-2])
-                context_loop.append(ed_adj[not i])
-
-                # Don't look at this again
-                del ed_adj[:]
-
-    return edge_loops
-
-
 def edge_loops_from_edges(mesh, edges=None):
     """
     Edge loops defined by edges
@@ -511,54 +429,42 @@ def ngon_tessellate(from_data, indices, fix_loops=True):
     return fill
 
 
-def face_random_points(num_points, tessfaces):
+def triangle_random_points(num_points, loop_triangles):
     """
-    Generates a list of random points over mesh tessfaces.
+    Generates a list of random points over mesh loop triangles.
 
-    :arg num_points: the number of random points to generate on each face.
+    :arg num_points: the number of random points to generate on each triangle.
     :type int:
-    :arg tessfaces: list of the faces to generate points on.
-    :type tessfaces: :class:`bpy.types.MeshTessFace`, sequence
-    :return: list of random points over all faces.
+    :arg loop_triangles: list of the triangles to generate points on.
+    :type loop_triangles: :class:`bpy.types.MeshLoopTriangle`, sequence
+    :return: list of random points over all triangles.
     :rtype: list
     """
 
     from random import random
     from mathutils.geometry import area_tri
 
-    # Split all quads into 2 tris, tris remain unchanged
-    tri_faces = []
-    for f in tessfaces:
-        tris = []
-        verts = f.id_data.vertices
-        fv = f.vertices[:]
-        tris.append((verts[fv[0]].co,
-                     verts[fv[1]].co,
-                     verts[fv[2]].co,
-                     ))
-        if len(fv) == 4:
-            tris.append((verts[fv[0]].co,
-                         verts[fv[3]].co,
-                         verts[fv[2]].co,
-                         ))
-        tri_faces.append(tris)
-
-    # For each face, generate the required number of random points
-    sampled_points = [None] * (num_points * len(tessfaces))
-    for i, tf in enumerate(tri_faces):
+    # For each triangle, generate the required number of random points
+    sampled_points = [None] * (num_points * len(loop_triangles))
+    for i, lt in enumerate(loop_triangles):
+        # Get triangle vertex coordinates
+        verts = lt.id_data.vertices
+        ltv = lt.vertices[:]
+        tv = (verts[ltv[0]].co, verts[ltv[1]].co, verts[ltv[2]].co)
+
         for k in range(num_points):
             # If this is a quad, we need to weight its 2 tris by their area
-            if len(tf) != 1:
-                area1 = area_tri(*tf[0])
-                area2 = area_tri(*tf[1])
+            if len(tv) != 1:
+                area1 = area_tri(*tv[0])
+                area2 = area_tri(*tv[1])
                 area_tot = area1 + area2
 
                 area1 = area1 / area_tot
                 area2 = area2 / area_tot
 
-                vecs = tf[0 if (random() < area1) else 1]
+                vecs = tv[0 if (random() < area1) else 1]
             else:
-                vecs = tf[0]
+                vecs = tv[0]
 
             u1 = random()
             u2 = random()
index 913de92ff6d66c77c79267d7d7c0852d910d6d47..9fe45d223f54ff8437a060e60cb983923d4fb1ae 100644 (file)
@@ -468,7 +468,7 @@ class MeshEdge(StructRNA):
         return ord_ind(*tuple(self.vertices))
 
 
-class MeshTessFace(StructRNA):
+class MeshLoopTriangle(StructRNA):
     __slots__ = ()
 
     @property
@@ -476,32 +476,18 @@ class MeshTessFace(StructRNA):
         """The midpoint of the face."""
         face_verts = self.vertices[:]
         mesh_verts = self.id_data.vertices
-        if len(face_verts) == 3:
-            return (mesh_verts[face_verts[0]].co +
-                    mesh_verts[face_verts[1]].co +
-                    mesh_verts[face_verts[2]].co
-                    ) / 3.0
-        else:
-            return (mesh_verts[face_verts[0]].co +
-                    mesh_verts[face_verts[1]].co +
-                    mesh_verts[face_verts[2]].co +
-                    mesh_verts[face_verts[3]].co
-                    ) / 4.0
+        return (mesh_verts[face_verts[0]].co +
+                mesh_verts[face_verts[1]].co +
+                mesh_verts[face_verts[2]].co
+                ) / 3.0
 
     @property
     def edge_keys(self):
         verts = self.vertices[:]
-        if len(verts) == 3:
-            return (ord_ind(verts[0], verts[1]),
-                    ord_ind(verts[1], verts[2]),
-                    ord_ind(verts[2], verts[0]),
-                    )
-        else:
-            return (ord_ind(verts[0], verts[1]),
-                    ord_ind(verts[1], verts[2]),
-                    ord_ind(verts[2], verts[3]),
-                    ord_ind(verts[3], verts[0]),
-                    )
+        return (ord_ind(verts[0], verts[1]),
+                ord_ind(verts[1], verts[2]),
+                ord_ind(verts[2], verts[0]),
+                )
 
 
 class MeshPolygon(StructRNA):
index 9f86c16bae8172671e45ddb38d003e1a68cc45a5..c723201505907687d9624a09a4e38306d9acf14e 100644 (file)
@@ -179,7 +179,7 @@ void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
 
 struct Mesh *BKE_mesh_new_from_object(
         struct Depsgraph *depsgraph, struct Main *bmain, struct Scene *sce, struct Object *ob,
-        const bool apply_modifiers, const bool calc_tessface, const bool calc_undeformed);
+        const bool apply_modifiers, const bool calc_loop_triangles, const bool calc_undeformed);
 struct Mesh *BKE_mesh_create_derived_for_modifier(
         struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob,
         struct ModifierData *md, int build_shapekey_layers);
index 7cc7095361c38a3fe2ec972c93754364f2924067..bb52ed79b53a3000d87612aa1cbdc4f273c7a4ee 100644 (file)
@@ -840,7 +840,7 @@ void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *
 /* 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)
+        const bool apply_modifiers, const bool calc_loop_triangles, const bool calc_undeformed)
 {
        Mesh *tmpmesh;
        Curve *tmpcu = NULL, *copycu;
@@ -1069,9 +1069,9 @@ Mesh *BKE_mesh_new_from_object(
                        break;
        } /* end copy materials */
 
-       if (calc_tessface) {
+       if (calc_loop_triangles) {
                /* cycles and exporters rely on this still */
-               BKE_mesh_tessface_ensure(tmpmesh);
+               BKE_mesh_runtime_looptri_ensure(tmpmesh);
        }
 
        return tmpmesh;
index a0b97b817fda60a7d9d26eea0510c093e020a743..016637f80027cd3d8849dc1d8e67468c25748299 100644 (file)
@@ -107,13 +107,13 @@ NodeGroup *BlenderFileLoader::Load()
 
                bool apply_modifiers = false;
                bool calc_undeformed = false;
-               bool calc_tessface = false;
+               bool calc_loop_triangles = false;
                Mesh *mesh = BKE_mesh_new_from_object(depsgraph,
                                                      _re->main,
                                                      _re->scene,
                                                      ob,
                                                      apply_modifiers,
-                                                     calc_tessface,
+                                                     calc_loop_triangles,
                                                      calc_undeformed);
 
                if (mesh) {
index 0b24c1cfb67aaeecccf6199d35ba5903390d98ba..636377ffd366b6722f8ed8e6e9fd58f048459309 100644 (file)
@@ -174,8 +174,6 @@ typedef struct MLoop {
  *
  * \note A #MLoopTri may be in the middle of an ngon and not reference **any** edges.
  */
-#
-#
 typedef struct MLoopTri {
        unsigned int tri[3];
        unsigned int poly;
index ccce54227fe87700cf148346b4472a1c79c66bbb..a90248ee53eb5896c445c132b923adb5d8c0c44d 100644 (file)
@@ -390,7 +390,7 @@ extern StructRNA RNA_MeshLoopColorLayer;
 extern StructRNA RNA_MeshDeformModifier;
 extern StructRNA RNA_MeshEdge;
 extern StructRNA RNA_MeshPolygon;
-extern StructRNA RNA_MeshTessFace;
+extern StructRNA RNA_MeshLoopTriangle;
 extern StructRNA RNA_MeshLoop;
 extern StructRNA RNA_MeshFloatProperty;
 extern StructRNA RNA_MeshFloatPropertyLayer;
index 2578f88a52090b68bf173275a404bd4e9852f010..7087be9de2d6de21a4cc18a01e0dac7d9d1889cc 100644 (file)
@@ -490,7 +490,7 @@ int rna_parameter_size(struct PropertyRNA *parm);
 
 struct Mesh *rna_Main_meshes_new_from_object(
         struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph,
-        struct Object *ob, bool apply_modifiers, bool calc_tessface, bool calc_undeformed);
+        struct Object *ob, bool apply_modifiers, bool calc_loop_triangles, bool calc_undeformed);
 
 /* XXX, these should not need to be defined here~! */
 struct MTex *rna_mtex_texture_slots_add(struct ID *self, struct bContext *C, struct ReportList *reports);
index 70dcf20dcc676154d53ae0ab3e5dc47eda21ab79..48ced4df0b495b6fdcfbed16529cf43385a3fe01 100644 (file)
@@ -310,7 +310,7 @@ static Mesh *rna_Main_meshes_new(Main *bmain, const char *name)
 /* copied from Mesh_getFromObject and adapted to RNA interface */
 Mesh *rna_Main_meshes_new_from_object(
         Main *bmain, ReportList *reports, Depsgraph *depsgraph,
-        Object *ob, bool apply_modifiers, bool calc_tessface, bool calc_undeformed)
+        Object *ob, bool apply_modifiers, bool calc_loop_triangles, bool calc_undeformed)
 {
        Scene *sce = DEG_get_evaluated_scene(depsgraph);
 
@@ -326,7 +326,7 @@ Mesh *rna_Main_meshes_new_from_object(
                        return NULL;
        }
 
-       return BKE_mesh_new_from_object(depsgraph, bmain, sce, ob, apply_modifiers, calc_tessface, calc_undeformed);
+       return BKE_mesh_new_from_object(depsgraph, bmain, sce, ob, apply_modifiers, calc_loop_triangles, calc_undeformed);
 }
 
 static Lamp *rna_Main_lights_new(Main *bmain, const char *name, int type)
@@ -893,7 +893,7 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
        RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
        parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
        RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
-       RNA_def_boolean(func, "calc_tessface", true, "Calculate Tessellation", "Calculate tessellation faces");
+       RNA_def_boolean(func, "calc_loop_triangles", true, "Calculate Triangles", "Calculate tesselated triangles");
        RNA_def_boolean(func, "calc_undeformed", false, "Calculate Undeformed", "Calculate undeformed vertex coordinates");
        parm = RNA_def_pointer(func, "mesh", "Mesh", "",
                               "Mesh created from object, remove it if it is only used for export");
index 24896570fb51d700f573dc86591f535927511847..a5bae7115f9b11c1a90330e80861d51c5fba7d5d 100644 (file)
@@ -70,6 +70,7 @@ const EnumPropertyItem rna_enum_mesh_delimit_mode_items[] = {
 #include "BKE_customdata.h"
 #include "BKE_main.h"
 #include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
 #include "BKE_report.h"
 
 #include "DEG_depsgraph.h"
@@ -139,12 +140,6 @@ static CustomData *rna_mesh_ldata(PointerRNA *ptr)
        return rna_mesh_ldata_helper(me);
 }
 
-static CustomData *rna_mesh_fdata(PointerRNA *ptr)
-{
-       Mesh *me = rna_mesh(ptr);
-       return rna_mesh_fdata_helper(me);
-}
-
 
 /* -------------------------------------------------------------------- */
 /* Generic CustomData Layer Functions */
@@ -195,12 +190,6 @@ static void rna_MeshLoopLayer_name_set(PointerRNA *ptr, const char *value)
 {
        rna_cd_layer_name_set(rna_mesh_ldata(ptr), (CustomDataLayer *)ptr->data, value);
 }
-#if 0
-static void rna_MeshTessfaceLayer_name_set(PointerRNA *ptr, const char *value)
-{
-       rna_cd_layer_name_set(rna_mesh_fdata(ptr), (CustomDataLayer *)ptr->data, value);
-}
-#endif
 /* only for layers shared between types */
 static void rna_MeshAnyLayer_name_set(PointerRNA *ptr, const char *value)
 {
@@ -435,232 +424,57 @@ static void rna_MeshPolygon_flip(ID *id, MPoly *mp)
 
        BKE_mesh_polygon_flip(mp, me->mloop, &me->ldata);
        BKE_mesh_tessface_clear(me);
+       BKE_mesh_runtime_clear_geometry(me);
 }
 
-static void rna_MeshTessFace_normal_get(PointerRNA *ptr, float *values)
+static void rna_MeshLoopTriangle_verts_get(PointerRNA *ptr, int *values)
 {
        Mesh *me = rna_mesh(ptr);
-       MFace *mface = (MFace *)ptr->data;
-
-       if (mface->v4)
-               normal_quad_v3(values, me->mvert[mface->v1].co, me->mvert[mface->v2].co,
-                              me->mvert[mface->v3].co, me->mvert[mface->v4].co);
-       else
-               normal_tri_v3(values, me->mvert[mface->v1].co, me->mvert[mface->v2].co, me->mvert[mface->v3].co);
+       MLoopTri *lt = (MLoopTri *)ptr->data;
+       values[0] = me->mloop[lt->tri[0]].v;
+       values[1] = me->mloop[lt->tri[1]].v;
+       values[2] = me->mloop[lt->tri[2]].v;
 }
 
-static void rna_MeshTessFace_split_normals_get(PointerRNA *ptr, float *values)
-{
-       Mesh *me = rna_mesh(ptr);
-       MFace *mface = (MFace *)ptr->data;
-       const short (*vec)[4][3] = CustomData_get(&me->fdata, (int)(mface - me->mface), CD_TESSLOOPNORMAL);
-       int i = 4;
-
-       if (!vec) {
-               while (i--) zero_v3(&values[i * 3]);
-       }
-       else {
-               while (i--) normal_short_to_float_v3(&values[i * 3], (const short *)(*vec)[i]);
-       }
-}
 
-static float rna_MeshTessFace_area_get(PointerRNA *ptr)
+static void rna_MeshLoopTriangle_normal_get(PointerRNA *ptr, float *values)
 {
        Mesh *me = rna_mesh(ptr);
-       MFace *mface = (MFace *)ptr->data;
-
-       if (mface->v4)
-               return area_quad_v3(me->mvert[mface->v1].co, me->mvert[mface->v2].co, me->mvert[mface->v3].co,
-                                   me->mvert[mface->v4].co);
-       else
-               return area_tri_v3(me->mvert[mface->v1].co, me->mvert[mface->v2].co, me->mvert[mface->v3].co);
-}
-
-static void rna_MeshTextureFace_uv1_get(PointerRNA *ptr, float *values)
-{
-       MTFace *mtface = (MTFace *)ptr->data;
-
-       values[0] = mtface->uv[0][0];
-       values[1] = mtface->uv[0][1];
-}
-
-static void rna_MeshTextureFace_uv1_set(PointerRNA *ptr, const float *values)
-{
-       MTFace *mtface = (MTFace *)ptr->data;
-
-       mtface->uv[0][0] = values[0];
-       mtface->uv[0][1] = values[1];
-}
-
-static void rna_MeshTextureFace_uv2_get(PointerRNA *ptr, float *values)
-{
-       MTFace *mtface = (MTFace *)ptr->data;
-
-       values[0] = mtface->uv[1][0];
-       values[1] = mtface->uv[1][1];
-}
-
-static void rna_MeshTextureFace_uv2_set(PointerRNA *ptr, const float *values)
-{
-       MTFace *mtface = (MTFace *)ptr->data;
-
-       mtface->uv[1][0] = values[0];
-       mtface->uv[1][1] = values[1];
-}
-
-static void rna_MeshTextureFace_uv3_get(PointerRNA *ptr, float *values)
-{
-       MTFace *mtface = (MTFace *)ptr->data;
-
-       values[0] = mtface->uv[2][0];
-       values[1] = mtface->uv[2][1];
-}
-
-static void rna_MeshTextureFace_uv3_set(PointerRNA *ptr, const float *values)
-{
-       MTFace *mtface = (MTFace *)ptr->data;
-
-       mtface->uv[2][0] = values[0];
-       mtface->uv[2][1] = values[1];
-}
-
-static void rna_MeshTextureFace_uv4_get(PointerRNA *ptr, float *values)
-{
-       MTFace *mtface = (MTFace *)ptr->data;
-
-       values[0] = mtface->uv[3][0];
-       values[1] = mtface->uv[3][1];
-}
+       MLoopTri *lt = (MLoopTri *)ptr->data;
+       unsigned int v1 = me->mloop[lt->tri[0]].v;
+       unsigned int v2 = me->mloop[lt->tri[1]].v;
+       unsigned int v3 = me->mloop[lt->tri[2]].v;
 
-static void rna_MeshTextureFace_uv4_set(PointerRNA *ptr, const float *values)
-{
-       MTFace *mtface = (MTFace *)ptr->data;
-
-       mtface->uv[3][0] = values[0];
-       mtface->uv[3][1] = values[1];
+       normal_tri_v3(values, me->mvert[v1].co, me->mvert[v2].co, me->mvert[v3].co);
 }
 
-static int rna_CustomDataData_numverts(PointerRNA *ptr, int type)
+static void rna_MeshLoopTriangle_split_normals_get(PointerRNA *ptr, float *values)
 {
        Mesh *me = rna_mesh(ptr);
-       CustomData *fdata = rna_mesh_fdata(ptr);
-       CustomDataLayer *cdl;
-       int a, b;
+       const float (*lnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL);
 
-       for (cdl = fdata->layers, a = 0; a < fdata->totlayer; cdl++, a++) {
-               if (cdl->type == type) {
-                       b = ((char *)ptr->data - ((char *)cdl->data)) / CustomData_sizeof(type);
-                       if (b >= 0 && b < me->totface) {
-                               return (me->mface[b].v4 ? 4 : 3);
-                       }
-               }
+       if (!lnors) {
+               zero_v3(values + 0);
+               zero_v3(values + 3);
+               zero_v3(values + 6);
+       }
+       else {
+               MLoopTri *lt = (MLoopTri *)ptr->data;
+               copy_v3_v3(values + 0, lnors[lt->tri[0]]);
+               copy_v3_v3(values + 3, lnors[lt->tri[1]]);
+               copy_v3_v3(values + 6, lnors[lt->tri[2]]);
        }
-
-       return 0;
-}
-
-static int rna_MeshTextureFace_uv_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
-{
-       length[0] = rna_CustomDataData_numverts(ptr, CD_MTFACE);
-       length[1] = 2;
-       return length[0] * length[1];
-}
-
-static void rna_MeshTextureFace_uv_get(PointerRNA *ptr, float *values)
-{
-       MTFace *mtface = (MTFace *)ptr->data;
-       int totvert = rna_CustomDataData_numverts(ptr, CD_MTFACE);
-
-       memcpy(values, mtface->uv, totvert * 2 * sizeof(float));
-}
-
-static void rna_MeshTextureFace_uv_set(PointerRNA *ptr, const float *values)
-{
-       MTFace *mtface = (MTFace *)ptr->data;
-       int totvert = rna_CustomDataData_numverts(ptr, CD_MTFACE);
-
-       memcpy(mtface->uv, values, totvert * 2 * sizeof(float));
-}
-
-/* notice red and blue are swapped */
-static void rna_MeshColor_color1_get(PointerRNA *ptr, float *values)
-{
-       MCol *mcol = (MCol *)ptr->data;
-
-       values[3] = mcol[0].a / 255.0f;
-       values[2] = mcol[0].r / 255.0f;
-       values[1] = mcol[0].g / 255.0f;
-       values[0] = mcol[0].b / 255.0f;
-}
-
-static void rna_MeshColor_color1_set(PointerRNA *ptr, const float *values)
-{
-       MCol *mcol = (MCol *)ptr->data;
-
-       mcol[0].a = round_fl_to_uchar_clamp(values[3] * 255.0f);
-       mcol[0].r = round_fl_to_uchar_clamp(values[2] * 255.0f);
-       mcol[0].g = round_fl_to_uchar_clamp(values[1] * 255.0f);
-       mcol[0].b = round_fl_to_uchar_clamp(values[0] * 255.0f);
-}
-
-static void rna_MeshColor_color2_get(PointerRNA *ptr, float *values)
-{
-       MCol *mcol = (MCol *)ptr->data;
-
-       values[3] = mcol[1].a / 255.0f;
-       values[2] = mcol[1].r / 255.0f;
-       values[1] = mcol[1].g / 255.0f;
-       values[0] = mcol[1].b / 255.0f;
-}
-
-static void rna_MeshColor_color2_set(PointerRNA *ptr, const float *values)
-{
-       MCol *mcol = (MCol *)ptr->data;
-
-       mcol[1].a = round_fl_to_uchar_clamp(values[3] * 255.0f);
-       mcol[1].r = round_fl_to_uchar_clamp(values[2] * 255.0f);
-       mcol[1].g = round_fl_to_uchar_clamp(values[1] * 255.0f);
-       mcol[1].b = round_fl_to_uchar_clamp(values[0] * 255.0f);
-}
-
-static void rna_MeshColor_color3_get(PointerRNA *ptr, float *values)
-{
-       MCol *mcol = (MCol *)ptr->data;
-
-       values[3] = mcol[2].a / 255.0f;
-       values[2] = mcol[2].r / 255.0f;
-       values[1] = mcol[2].g / 255.0f;
-       values[0] = mcol[2].b / 255.0f;
-}
-
-static void rna_MeshColor_color3_set(PointerRNA *ptr, const float *values)
-{
-       MCol *mcol = (MCol *)ptr->data;
-
-       mcol[2].a = round_fl_to_uchar_clamp(values[3] * 255.0f);
-       mcol[2].r = round_fl_to_uchar_clamp(values[2] * 255.0f);
-       mcol[2].g = round_fl_to_uchar_clamp(values[1] * 255.0f);
-       mcol[2].b = round_fl_to_uchar_clamp(values[0] * 255.0f);
-}
-
-static void rna_MeshColor_color4_get(PointerRNA *ptr, float *values)
-{
-       MCol *mcol = (MCol *)ptr->data;
-
-       values[3] = mcol[3].a / 255.0f;
-       values[2] = mcol[3].r / 255.0f;
-       values[1] = mcol[3].g / 255.0f;
-       values[0] = mcol[3].b / 255.0f;
 }
 
-static void rna_MeshColor_color4_set(PointerRNA *ptr, const float *values)
+static float rna_MeshLoopTriangle_area_get(PointerRNA *ptr)
 {
-       MCol *mcol = (MCol *)ptr->data;
+       Mesh *me = rna_mesh(ptr);
+       MLoopTri *lt = (MLoopTri *)ptr->data;
+       unsigned int v1 = me->mloop[lt->tri[0]].v;
+       unsigned int v2 = me->mloop[lt->tri[1]].v;
+       unsigned int v3 = me->mloop[lt->tri[2]].v;
 
-       mcol[3].a = round_fl_to_uchar_clamp(values[3] * 255.0f);
-       mcol[3].r = round_fl_to_uchar_clamp(values[2] * 255.0f);
-       mcol[3].g = round_fl_to_uchar_clamp(values[1] * 255.0f);
-       mcol[3].b = round_fl_to_uchar_clamp(values[0] * 255.0f);
+       return area_tri_v3(me->mvert[v1].co, me->mvert[v2].co, me->mvert[v3].co);
 }
 
 static void rna_MeshLoopColor_color_get(PointerRNA *ptr, float *values)
@@ -902,93 +716,8 @@ static void rna_MeshUVLoopLayer_clone_set(PointerRNA *ptr, bool value)
        rna_CustomDataLayer_clone_set(ptr, rna_mesh_ldata(ptr), value, CD_MLOOPUV);
 }
 
-/* face uv_textures */
-
-DEFINE_CUSTOMDATA_LAYER_COLLECTION(tessface_uv_texture, fdata, CD_MTFACE)
-DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(tessface_uv_texture, fdata, CD_MTFACE, active, MeshTextureFaceLayer)
-
-static void rna_MeshTextureFaceLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
-{
-       Mesh *me = rna_mesh(ptr);
-       CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
-       rna_iterator_array_begin(iter, layer->data, sizeof(MTFace), (me->edit_btmesh) ? 0 : me->totface, 0, NULL);
-}
-
-static int rna_MeshTextureFaceLayer_data_length(PointerRNA *ptr)
-{
-       Mesh *me = rna_mesh(ptr);
-       return (me->edit_btmesh) ? 0 : me->totface;
-}
-
-static bool rna_MeshTextureFaceLayer_active_render_get(PointerRNA *ptr)
-{
-       return rna_CustomDataLayer_active_get(ptr, rna_mesh_fdata(ptr), CD_MTFACE, 1);
-}
-
-static bool rna_MeshTextureFaceLayer_active_get(PointerRNA *ptr)
-{
-       return rna_CustomDataLayer_active_get(ptr, rna_mesh_fdata(ptr), CD_MTFACE, 0);
-}
-
-static bool rna_MeshTextureFaceLayer_clone_get(PointerRNA *ptr)
-{
-       return rna_CustomDataLayer_clone_get(ptr, rna_mesh_fdata(ptr), CD_MTFACE);
-}
-
-static void rna_MeshTextureFaceLayer_active_render_set(PointerRNA *ptr, bool value)
-{
-       rna_CustomDataLayer_active_set(ptr, rna_mesh_fdata(ptr), value, CD_MTFACE, 1);
-}
-
-static void rna_MeshTextureFaceLayer_active_set(PointerRNA *ptr, int value)
-{
-       rna_CustomDataLayer_active_set(ptr, rna_mesh_fdata(ptr), value, CD_MTFACE, 0);
-}
-
-static void rna_MeshTextureFaceLayer_clone_set(PointerRNA *ptr, int value)
-{
-       rna_CustomDataLayer_clone_set(ptr, rna_mesh_fdata(ptr), value, CD_MTFACE);
-}
-
 /* vertex_color_layers */
 
-DEFINE_CUSTOMDATA_LAYER_COLLECTION(tessface_vertex_color, fdata, CD_MCOL)
-DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(tessface_vertex_color, fdata, CD_MCOL, active, MeshColorLayer)
-DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(tessface_vertex_color, fdata, CD_MCOL, render, MeshColorLayer)
-
-static void rna_MeshColorLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
-{
-       Mesh *me = rna_mesh(ptr);
-       CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
-       rna_iterator_array_begin(iter, layer->data, sizeof(MCol) * 4, me->totface, 0, NULL);
-}
-
-static int rna_MeshColorLayer_data_length(PointerRNA *ptr)
-{
-       Mesh *me = rna_mesh(ptr);
-       return me->totface;
-}
-
-static bool rna_MeshColorLayer_active_render_get(PointerRNA *ptr)
-{
-       return rna_CustomDataLayer_active_get(ptr, rna_mesh_fdata(ptr), CD_MCOL, 1);
-}
-
-static bool rna_MeshColorLayer_active_get(PointerRNA *ptr)
-{
-       return rna_CustomDataLayer_active_get(ptr, rna_mesh_fdata(ptr), CD_MCOL, 0);
-}
-
-static void rna_MeshColorLayer_active_render_set(PointerRNA *ptr, bool value)
-{
-       rna_CustomDataLayer_active_set(ptr, rna_mesh_fdata(ptr), value, CD_MCOL, 1);
-}
-
-static void rna_MeshColorLayer_active_set(PointerRNA *ptr, int value)
-{
-       rna_CustomDataLayer_active_set(ptr, rna_mesh_fdata(ptr), value, CD_MCOL, 0);
-}
-
 DEFINE_CUSTOMDATA_LAYER_COLLECTION(vertex_color, ldata, CD_MLOOPCOL)
 DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(vertex_color, ldata, CD_MLOOPCOL, active, MeshLoopColorLayer)
 DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(vertex_color, ldata, CD_MLOOPCOL, render, MeshLoopColorLayer)
@@ -1242,30 +971,6 @@ static void rna_Mesh_face_map_remove(struct Mesh *me, ReportList *reports, struc
 /* End face maps */
 
 
-static int rna_MeshTessFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
-{
-       MFace *face = (MFace *)ptr->data;
-
-       if (face)
-               length[0] = (face->v4) ? 4 : 3;
-       else
-               length[0] = 4;  /* XXX rna_raw_access wants the length of a dummy face. this needs fixing. - Campbell */
-
-       return length[0];
-}
-
-static void rna_MeshTessFace_verts_get(PointerRNA *ptr, int *values)
-{
-       MFace *face = (MFace *)ptr->data;
-       memcpy(values, &face->v1, (face->v4 ? 4 : 3) * sizeof(int));
-}
-
-static void rna_MeshTessFace_verts_set(PointerRNA *ptr, const int *values)
-{
-       MFace *face = (MFace *)ptr->data;
-       memcpy(&face->v1, values, (face->v4 ? 4 : 3) * sizeof(int));
-}
-
 /* poly.vertices - this is faked loop access for convenience */
 static int rna_MeshPoly_vertices_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
 {
@@ -1320,11 +1025,25 @@ static int rna_MeshEdge_index_get(PointerRNA *ptr)
        return (int)(edge - me->medge);
 }
 
-static int rna_MeshTessFace_index_get(PointerRNA *ptr)
+static int rna_MeshLoopTriangle_index_get(PointerRNA *ptr)
+{
+       Mesh *me = rna_mesh(ptr);
+       MLoopTri *ltri = (MLoopTri *)ptr->data;
+       return (int)(ltri - me->runtime.looptris.array);
+}
+
+static int rna_MeshLoopTriangle_material_index_get(PointerRNA *ptr)
+{
+       Mesh *me = rna_mesh(ptr);
+       MLoopTri *ltri = (MLoopTri *)ptr->data;
+       return me->mpoly[ltri->poly].mat_nr;
+}
+
+static bool rna_MeshLoopTriangle_use_smooth_get(PointerRNA *ptr)
 {
        Mesh *me = rna_mesh(ptr);
-       MFace *face = (MFace *)ptr->data;
-       return (int)(face - me->mface);
+       MLoopTri *ltri = (MLoopTri *)ptr->data;
+       return me->mpoly[ltri->poly].flag & ME_SMOOTH;
 }
 
 static int rna_MeshPolygon_index_get(PointerRNA *ptr)
@@ -1363,9 +1082,9 @@ static char *rna_MeshPolygon_path(PointerRNA *ptr)
        return BLI_sprintfN("polygons[%d]", (int)((MPoly *)ptr->data - rna_mesh(ptr)->mpoly));
 }
 
-static char *rna_MeshTessFace_path(PointerRNA *ptr)
+static char *rna_MeshLoopTriangle_path(PointerRNA *ptr)
 {
-       return BLI_sprintfN("tessfaces[%d]", (int)((MFace *)ptr->data - rna_mesh(ptr)->mface));
+       return BLI_sprintfN("loop_triangles[%d]", (int)((MLoopTri *)ptr->data - rna_mesh(ptr)->runtime.looptris.array));
 }
 
 static char *rna_MeshEdge_path(PointerRNA *ptr)
@@ -1384,14 +1103,6 @@ static char *rna_MeshVertex_path(PointerRNA *ptr)
        return BLI_sprintfN("vertices[%d]", (int)((MVert *)ptr->data - rna_mesh(ptr)->mvert));
 }
 
-static char *rna_MeshTextureFaceLayer_path(PointerRNA *ptr)
-{
-       CustomDataLayer *cdl = ptr->data;
-       char name_esc[sizeof(cdl->name) * 2];
-       BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
-       return BLI_sprintfN("tessface_uv_textures[\"%s\"]", name_esc);
-}
-
 static char *rna_VertCustomData_data_path(PointerRNA *ptr, const char *collection, int type)
 {
        CustomDataLayer *cdl;
@@ -1455,46 +1166,11 @@ static char *rna_LoopCustomData_data_path(PointerRNA *ptr, const char *collectio
        return NULL;
 }
 
-static char *rna_FaceCustomData_data_path(PointerRNA *ptr, const char *collection, int type)
-{
-       CustomDataLayer *cdl;
-       Mesh *me = rna_mesh(ptr);
-       CustomData *fdata = rna_mesh_fdata(ptr);
-       int a, b, totloop = (me->edit_btmesh) ? 0 : me->totloop;
-
-       for (cdl = fdata->layers, a = 0; a < fdata->totlayer; cdl++, a++) {
-               if (cdl->type == type) {
-                       b = ((char *)ptr->data - ((char *)cdl->data)) / CustomData_sizeof(type);
-                       if (b >= 0 && b < totloop) {
-                               char name_esc[sizeof(cdl->name) * 2];
-                               BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
-                               return BLI_sprintfN("%s[\"%s\"].data[%d]", collection, name_esc, b);
-                       }
-               }
-       }
-
-       return NULL;
-}
-
-
 static char *rna_MeshUVLoop_path(PointerRNA *ptr)
 {
        return rna_LoopCustomData_data_path(ptr, "uv_layers", CD_MLOOPUV);
 }
 
-static char *rna_MeshTextureFace_path(PointerRNA *ptr)
-{
-       return rna_FaceCustomData_data_path(ptr, "tessface_uv_textures", CD_MTFACE);
-}
-
-static char *rna_MeshColorLayer_path(PointerRNA *ptr)
-{
-       CustomDataLayer *cdl = ptr->data;
-       char name_esc[sizeof(cdl->name) * 2];
-       BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
-       return BLI_sprintfN("tessface_vertex_colors[\"%s\"]", name_esc);
-}
-
 static char *rna_MeshLoopColorLayer_path(PointerRNA *ptr)
 {
        CustomDataLayer *cdl = ptr->data;
@@ -1721,34 +1397,6 @@ static void rna_Mesh_vertex_color_remove(struct Mesh *me, ReportList *reports, C
        }
 }
 
-static PointerRNA rna_Mesh_tessface_vertex_color_new(struct Mesh *me, ReportList *reports, const char *name)
-{
-       PointerRNA ptr;
-       CustomData *fdata;
-       CustomDataLayer *cdl = NULL;
-       int index;
-
-       if (me->edit_btmesh) {
-               BKE_report(reports, RPT_ERROR, "Cannot add tessface colors in edit mode");
-               return PointerRNA_NULL;
-       }
-
-       if (me->mpoly) {
-               BKE_report(reports, RPT_ERROR, "Cannot add tessface colors when MPoly's exist");
-               return PointerRNA_NULL;
-       }
-
-       index = ED_mesh_color_add(me, name, false);
-
-       if (index != -1) {
-               fdata = rna_mesh_fdata_helper(me);
-               cdl = &fdata->layers[CustomData_get_layer_index_n(fdata, CD_MCOL, index)];
-       }
-
-       RNA_pointer_create(&me->id, &RNA_MeshColorLayer, cdl, &ptr);
-       return ptr;
-}
-
 #define DEFINE_CUSTOMDATA_PROPERTY_API(elemname, datatype, cd_prop_type, cdata, countvar, layertype) \
 static PointerRNA rna_Mesh_##elemname##_##datatype##_property_new(struct Mesh *me, const char *name) \
 { \
@@ -1796,38 +1444,6 @@ static void rna_Mesh_uv_layers_remove(struct Mesh *me, ReportList *reports, Cust
        }
 }
 
-/* while this is supposed to be readonly,
- * keep it to support importers that only make tessfaces */
-
-static PointerRNA rna_Mesh_tessface_uv_texture_new(struct Mesh *me, ReportList *reports, const char *name)
-{
-       PointerRNA ptr;
-       CustomData *fdata;
-       CustomDataLayer *cdl = NULL;
-       int index;
-
-       if (me->edit_btmesh) {
-               BKE_report(reports, RPT_ERROR, "Cannot add tessface uv's in edit mode");
-               return PointerRNA_NULL;
-       }
-
-       if (me->mpoly) {
-               BKE_report(reports, RPT_ERROR, "Cannot add tessface uv's when MPoly's exist");
-               return PointerRNA_NULL;
-       }
-
-       index = ED_mesh_uv_texture_add(me, name, false);
-
-       if (index != -1) {
-               fdata = rna_mesh_fdata_helper(me);
-               cdl = &fdata->layers[CustomData_get_layer_index_n(fdata, CD_MTFACE, index)];
-       }
-
-       RNA_pointer_create(&me->id, &RNA_MeshTextureFaceLayer, cdl, &ptr);
-       return ptr;
-}
-
-
 static bool rna_Mesh_is_editmode_get(PointerRNA *ptr)
 {
        Mesh *me = rna_mesh(ptr);
@@ -1840,14 +1456,6 @@ static void UNUSED_FUNCTION(rna_mesh_unused)(void)
        /* unused functions made by macros */
        (void)rna_Mesh_skin_vertice_index_range;
        (void)rna_Mesh_vertex_paint_mask_index_range;
-       (void)rna_Mesh_tessface_uv_texture_active_set;
-       (void)rna_Mesh_tessface_uv_texture_index_range;
-       (void)rna_Mesh_tessface_vertex_color_active_set;
-       (void)rna_Mesh_tessface_vertex_color_index_range;
-       (void)rna_Mesh_tessface_vertex_color_render_get;
-       (void)rna_Mesh_tessface_vertex_color_render_index_get;
-       (void)rna_Mesh_tessface_vertex_color_render_index_set;
-       (void)rna_Mesh_tessface_vertex_color_render_set;
        (void)rna_Mesh_uv_layer_render_get;
        (void)rna_Mesh_uv_layer_render_index_get;
        (void)rna_Mesh_uv_layer_render_index_set;
@@ -2009,83 +1617,70 @@ static void rna_def_medge(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Index", "Index of this edge");
 }
 
-static void rna_def_mface(BlenderRNA *brna)
+static void rna_def_mlooptri(BlenderRNA *brna)
 {
        StructRNA *srna;
        PropertyRNA *prop;
-       const int splitnor_dim[] = {4, 3};
+       const int splitnor_dim[] = {3, 3};
 
-       srna = RNA_def_struct(brna, "MeshTessFace", NULL);
-       RNA_def_struct_sdna(srna, "MFace");
-       RNA_def_struct_ui_text(srna, "Mesh TessFace", "TessFace in a Mesh data-block");
-       RNA_def_struct_path_func(srna, "rna_MeshTessFace_path");
+       srna = RNA_def_struct(brna, "MeshLoopTriangle", NULL);
+       RNA_def_struct_sdna(srna, "MLoopTri");
+       RNA_def_struct_ui_text(srna, "Mesh Loop Triangle", "Tessellated triangle in a Mesh data-block");
+       RNA_def_struct_path_func(srna, "rna_MeshLoopTriangle_path");
        RNA_def_struct_ui_icon(srna, ICON_FACESEL);
 
-       /* XXX allows creating invalid meshes */
        prop = RNA_def_property(srna, "vertices", PROP_INT, PROP_UNSIGNED);
-       RNA_def_property_array(prop, 4);
-       RNA_def_property_flag(prop, PROP_DYNAMIC);
-       RNA_def_property_dynamic_array_funcs(prop, "rna_MeshTessFace_verts_get_length");
-       RNA_def_property_int_funcs(prop, "rna_MeshTessFace_verts_get", "rna_MeshTessFace_verts_set", NULL);
-       RNA_def_property_ui_text(prop, "Vertices", "Vertex indices");
-
-       /* leaving this fixed size array for foreach_set used in import scripts */
-       prop = RNA_def_property(srna, "vertices_raw", PROP_INT, PROP_UNSIGNED);
-       RNA_def_property_int_sdna(prop, NULL, "v1");
-       RNA_def_property_array(prop, 4);
-       RNA_def_property_ui_text(prop, "Vertices", "Fixed size vertex indices array");
-
-       prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED);
-       RNA_def_property_int_sdna(prop, NULL, "mat_nr");
-       RNA_def_property_ui_text(prop, "Material Index", "");
-#if 0
-       RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshPoly_material_index_range"); /* reuse for tessface is ok */
-#endif
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FACE_SEL);
-       RNA_def_property_ui_text(prop, "Select", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
+       RNA_def_property_array(prop, 3);
+       RNA_def_property_int_funcs(prop, "rna_MeshLoopTriangle_verts_get", NULL, NULL);
+       RNA_def_property_ui_text(prop, "Vertices", "Indices of triangle vertices");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 
-       prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_HIDE);
-       RNA_def_property_ui_text(prop, "Hide", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
+       prop = RNA_def_property(srna, "loops", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_sdna(prop, NULL, "tri");
+       RNA_def_property_ui_text(prop, "Loops", "Indices of mesh loops that make up the triangle");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 
-       prop = RNA_def_property(srna, "use_smooth", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_SMOOTH);
-       RNA_def_property_ui_text(prop, "Smooth", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+       prop = RNA_def_property(srna, "polygon_index", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_sdna(prop, NULL, "poly");
+       RNA_def_property_ui_text(prop, "Polygon", "Index of mesh polygon that the triangle is a part of");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 
        prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
        RNA_def_property_array(prop, 3);
        RNA_def_property_range(prop, -1.0f, 1.0f);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-       RNA_def_property_float_funcs(prop, "rna_MeshTessFace_normal_get", NULL, NULL);
-       RNA_def_property_ui_text(prop, "Face Normal", "Local space unit length normal vector for this face");
+       RNA_def_property_float_funcs(prop, "rna_MeshLoopTriangle_normal_get", NULL, NULL);
+       RNA_def_property_ui_text(prop, "Triangle Normal", "Local space unit length normal vector for this triangle");
 
        prop = RNA_def_property(srna, "split_normals", PROP_FLOAT, PROP_DIRECTION);
        RNA_def_property_multi_array(prop, 2, splitnor_dim);
        RNA_def_property_range(prop, -1.0f, 1.0f);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-       RNA_def_property_float_funcs(prop, "rna_MeshTessFace_split_normals_get", NULL, NULL);
+       RNA_def_property_float_funcs(prop, "rna_MeshLoopTriangle_split_normals_get", NULL, NULL);
        RNA_def_property_ui_text(prop, "Split Normals",
-                                "Local space unit length split normals vectors of the vertices of this face "
-                                "(must be computed beforehand using calc_normals_split or calc_tangents, "
-                                "and then calc_tessface)");
+                                "Local space unit length split normals vectors of the vertices of this triangle "
+                                "(must be computed beforehand using calc_normals_split or calc_tangents)");
 
        prop = RNA_def_property(srna, "area", PROP_FLOAT, PROP_UNSIGNED);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-       RNA_def_property_float_funcs(prop, "rna_MeshTessFace_area_get", NULL, NULL);
-       RNA_def_property_ui_text(prop, "Face Area", "Read only area of this face");
+       RNA_def_property_float_funcs(prop, "rna_MeshLoopTriangle_area_get", NULL, NULL);
+       RNA_def_property_ui_text(prop, "Triangle Area", "Area of this triangle");
 
        prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-       RNA_def_property_int_funcs(prop, "rna_MeshTessFace_index_get", NULL, NULL);
-       RNA_def_property_ui_text(prop, "Index", "Index of this face");
-}
+       RNA_def_property_int_funcs(prop, "rna_MeshLoopTriangle_index_get", NULL, NULL);
+       RNA_def_property_ui_text(prop, "Index", "Index of this loop triangle");
 
+       prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_int_funcs(prop, "rna_MeshLoopTriangle_material_index_get", NULL, NULL);
+       RNA_def_property_ui_text(prop, "Material Index", "");
+
+       prop = RNA_def_property(srna, "use_smooth", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_boolean_funcs(prop, "rna_MeshLoopTriangle_use_smooth_get", NULL);
+       RNA_def_property_ui_text(prop, "Smooth", "");
+}
 
 static void rna_def_mloop(BlenderRNA *brna)
 {
@@ -2295,179 +1890,6 @@ static void rna_def_mloopuv(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "UV Edge Select", "");
 }
 
-static void rna_def_mtface(BlenderRNA *brna)
-{
-       StructRNA *srna;
-       PropertyRNA *prop;
-       const int uv_dim[] = {4, 2};
-
-       srna = RNA_def_struct(brna, "MeshTextureFaceLayer", NULL);
-       RNA_def_struct_ui_text(srna, "Mesh UV Map", "UV map with assigned image textures in a Mesh data-block");
-       RNA_def_struct_sdna(srna, "CustomDataLayer");
-       RNA_def_struct_path_func(srna, "rna_MeshTextureFaceLayer_path");
-       RNA_def_struct_ui_icon(srna, ICON_GROUP_UVS);
-
-       prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
-       RNA_def_struct_name_property(srna, prop);
-       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshUVLayer_name_set");
-       RNA_def_property_ui_text(prop, "Name", "Name of UV map");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_funcs(prop, "rna_MeshTextureFaceLayer_active_get", "rna_MeshTextureFaceLayer_active_set");
-       RNA_def_property_ui_text(prop, "Active", "Set the map as active for display and editing");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "active_render", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "active_rnd", 0);
-       RNA_def_property_boolean_funcs(prop, "rna_MeshTextureFaceLayer_active_render_get",
-                                      "rna_MeshTextureFaceLayer_active_render_set");
-       RNA_def_property_ui_text(prop, "Active Render", "Set the map as active for rendering");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "active_clone", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "active_clone", 0);
-       RNA_def_property_boolean_funcs(prop, "rna_MeshTextureFaceLayer_clone_get", "rna_MeshTextureFaceLayer_clone_set");
-       RNA_def_property_ui_text(prop, "Active Clone", "Set the map as active for cloning");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
-       RNA_def_property_struct_type(prop, "MeshTextureFace");
-       RNA_def_property_ui_text(prop, "Data", "");
-       RNA_def_property_collection_funcs(prop, "rna_MeshTextureFaceLayer_data_begin", "rna_iterator_array_next",
-                                         "rna_iterator_array_end", "rna_iterator_array_get",
-                                         "rna_MeshTextureFaceLayer_data_length", NULL, NULL, NULL);
-
-       srna = RNA_def_struct(brna, "MeshTextureFace", NULL);
-       RNA_def_struct_sdna(srna, "MTFace");
-       RNA_def_struct_ui_text(srna, "Mesh UV Map Face", "UV map and image texture for a face");
-       RNA_def_struct_path_func(srna, "rna_MeshTextureFace_path");
-       RNA_def_struct_ui_icon(srna, ICON_FACESEL_HLT);
-
-       /* these are for editing only, access at loops now */
-#if 0
-       prop = RNA_def_property(srna, "select_uv", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", TF_SEL1);
-       RNA_def_property_array(prop, 4);
-       RNA_def_property_ui_text(prop, "UV Selected", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
-
-       prop = RNA_def_property(srna, "pin_uv", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "unwrap", TF_PIN1);
-       RNA_def_property_array(prop, 4);
-       RNA_def_property_ui_text(prop, "UV Pinned", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
-#endif
-
-       prop = RNA_def_property(srna, "uv1", PROP_FLOAT, PROP_XYZ);
-       RNA_def_property_array(prop, 2);
-       RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv1_get", "rna_MeshTextureFace_uv1_set", NULL);
-       RNA_def_property_ui_text(prop, "UV 1", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "uv2", PROP_FLOAT, PROP_XYZ);
-       RNA_def_property_array(prop, 2);
-       RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv2_get", "rna_MeshTextureFace_uv2_set", NULL);
-       RNA_def_property_ui_text(prop, "UV 2", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "uv3", PROP_FLOAT, PROP_XYZ);
-       RNA_def_property_array(prop, 2);
-       RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv3_get", "rna_MeshTextureFace_uv3_set", NULL);
-       RNA_def_property_ui_text(prop, "UV 3", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "uv4", PROP_FLOAT, PROP_XYZ);
-       RNA_def_property_array(prop, 2);
-       RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv4_get", "rna_MeshTextureFace_uv4_set", NULL);
-       RNA_def_property_ui_text(prop, "UV 4", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_multi_array(prop, 2, uv_dim);
-       RNA_def_property_flag(prop, PROP_DYNAMIC);
-       RNA_def_property_dynamic_array_funcs(prop, "rna_MeshTextureFace_uv_get_length");
-       RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv_get", "rna_MeshTextureFace_uv_set", NULL);
-       RNA_def_property_ui_text(prop, "UV", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "uv_raw", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_multi_array(prop, 2, uv_dim);
-       RNA_def_property_float_sdna(prop, NULL, "uv");
-       RNA_def_property_ui_text(prop, "UV Raw", "Fixed size UV coordinates array");
-
-}
-
-static void rna_def_mcol(BlenderRNA *brna)
-{
-       StructRNA *srna;
-       PropertyRNA *prop;
-
-       srna = RNA_def_struct(brna, "MeshColorLayer", NULL);
-       RNA_def_struct_ui_text(srna, "Mesh Vertex Color Layer", "Layer of vertex colors in a Mesh data-block");
-       RNA_def_struct_sdna(srna, "CustomDataLayer");
-       RNA_def_struct_path_func(srna, "rna_MeshColorLayer_path");
-       RNA_def_struct_ui_icon(srna, ICON_GROUP_VCOL);
-
-       prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
-       RNA_def_struct_name_property(srna, prop);
-       RNA_def_property_string_funcs(prop, NULL, NULL, NULL);
-       RNA_def_property_ui_text(prop, "Name", "Name of Vertex color layer");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_funcs(prop, "rna_MeshColorLayer_active_get", "rna_MeshColorLayer_active_set");
-       RNA_def_property_ui_text(prop, "Active", "Sets the layer as active for display and editing");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "active_render", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "active_rnd", 0);
-       RNA_def_property_boolean_funcs(prop, "rna_MeshColorLayer_active_render_get",
-                                      "rna_MeshColorLayer_active_render_set");
-       RNA_def_property_ui_text(prop, "Active Render", "Sets the layer as active for rendering");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
-       RNA_def_property_struct_type(prop, "MeshColor");
-       RNA_def_property_ui_text(prop, "Data", "");
-       RNA_def_property_collection_funcs(prop, "rna_MeshColorLayer_data_begin", "rna_iterator_array_next",
-                                         "rna_iterator_array_end", "rna_iterator_array_get",
-                                         "rna_MeshColorLayer_data_length", NULL, NULL, NULL);
-
-       srna = RNA_def_struct(brna, "MeshColor", NULL);
-       RNA_def_struct_sdna(srna, "MCol");
-       RNA_def_struct_ui_text(srna, "Mesh Vertex Color", "Vertex colors for a face in a Mesh");
-       RNA_def_struct_path_func(srna, "rna_MeshColor_path");
-
-       prop = RNA_def_property(srna, "color1", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_array(prop, 4);
-       RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_float_funcs(prop, "rna_MeshColor_color1_get", "rna_MeshColor_color1_set", NULL);
-       RNA_def_property_ui_text(prop, "Color 1", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "color2", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_array(prop, 4);
-       RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_float_funcs(prop, "rna_MeshColor_color2_get", "rna_MeshColor_color2_set", NULL);
-       RNA_def_property_ui_text(prop, "Color 2", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "color3", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_array(prop, 4);
-       RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_float_funcs(prop, "rna_MeshColor_color3_get", "rna_MeshColor_color3_set", NULL);
-       RNA_def_property_ui_text(prop, "Color 3", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "color4", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_array(prop, 4);
-       RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_float_funcs(prop, "rna_MeshColor_color4_get", "rna_MeshColor_color4_set", NULL);
-       RNA_def_property_ui_text(prop, "Color 4", "");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-}
-
 static void rna_def_mloopcol(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -2723,33 +2145,15 @@ static void rna_def_mesh_edges(BlenderRNA *brna, PropertyRNA *cprop)
 #endif
 }
 
-/* mesh.faces */
-static void rna_def_mesh_tessfaces(BlenderRNA *brna, PropertyRNA *cprop)
+/* mesh.loop_triangles */
+static void rna_def_mesh_looptris(BlenderRNA *brna, PropertyRNA *cprop)
 {
        StructRNA *srna;
-       PropertyRNA *prop;
 
-       FunctionRNA *func;
-       PropertyRNA *parm;
-
-       RNA_def_property_srna(cprop, "MeshTessFaces");
-       srna = RNA_def_struct(brna, "MeshTessFaces", NULL);
+       RNA_def_property_srna(cprop, "MeshLoopTriangle");
+       srna = RNA_def_struct(brna, "MeshLoopTriangles", NULL);
        RNA_def_struct_sdna(srna, "Mesh");
-       RNA_def_struct_ui_text(srna, "Mesh Faces", "Collection of mesh faces");
-
-       prop = RNA_def_property(srna, "active", PROP_INT, PROP_NONE);
-       RNA_def_property_int_sdna(prop, NULL, "act_face");
-       RNA_def_property_ui_text(prop, "Active Face", "The active face for this mesh");
-
-       func = RNA_def_function(srna, "add", "ED_mesh_tessfaces_add");
-       RNA_def_function_flag(func, FUNC_USE_REPORTS);
-       parm = RNA_def_int(func, "count", 0, 0, INT_MAX, "Count", "Number of faces to add", 0, INT_MAX);
-       RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
-#if 0 /* BMESH_TODO Remove until BMesh merge */
-       func = RNA_def_function(srna, "remove", "ED_mesh_faces_remove");
-       RNA_def_function_flag(func, FUNC_USE_REPORTS);
-       RNA_def_int(func, "count", 0, 0, INT_MAX, "Count", "Number of faces to remove", 0, INT_MAX);
-#endif
+       RNA_def_struct_ui_text(srna, "Mesh Loop Triangles", "Tessellation of mesh polygons into triangles");
 }
 
 /* mesh.loops */
@@ -2799,43 +2203,6 @@ static void rna_def_mesh_polygons(BlenderRNA *brna, PropertyRNA *cprop)
 }
 
 
-/* mesh.vertex_colors */
-static void rna_def_tessface_vertex_colors(BlenderRNA *brna, PropertyRNA *cprop)
-{
-       StructRNA *srna;
-       PropertyRNA *prop;
-
-       FunctionRNA *func;
-       PropertyRNA *parm;
-
-       RNA_def_property_srna(cprop, "VertexColors");
-       srna = RNA_def_struct(brna, "VertexColors", NULL);
-       RNA_def_struct_sdna(srna, "Mesh");
-       RNA_def_struct_ui_text(srna, "Vertex Colors", "Collection of vertex colors");
-
-       /* eventually deprecate this */
-       func = RNA_def_function(srna, "new", "rna_Mesh_tessface_vertex_color_new");
-       RNA_def_function_flag(func, FUNC_USE_REPORTS);
-       RNA_def_function_ui_description(func, "Add a vertex color layer to Mesh");
-       RNA_def_string(func, "name", "Col", 0, "", "Vertex color name");
-       parm = RNA_def_pointer(func, "layer", "MeshColorLayer", "", "The newly created layer");
-       RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
-       RNA_def_function_return(func, parm);
-
-       prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
-       RNA_def_property_struct_type(prop, "MeshColorLayer");
-       RNA_def_property_pointer_funcs(prop, "rna_Mesh_tessface_vertex_color_active_get",
-                                      "rna_Mesh_tessface_vertex_color_active_set", NULL, NULL);
-       RNA_def_property_ui_text(prop, "Active Vertex Color Layer", "Active vertex color layer");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
-       RNA_def_property_int_funcs(prop, "rna_Mesh_tessface_vertex_color_active_index_get",
-                                  "rna_Mesh_tessface_vertex_color_active_index_set", "rna_Mesh_vertex_color_index_range");
-       RNA_def_property_ui_text(prop, "Active Vertex Color Index", "Active vertex color index");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-}
-
 static void rna_def_loop_colors(BlenderRNA *brna, PropertyRNA *cprop)
 {
        StructRNA *srna;
@@ -3045,43 +2412,6 @@ static void rna_def_polygon_string_layers(BlenderRNA *brna, PropertyRNA *cprop)
        RNA_def_function_return(func, parm);
 }
 
-/* mesh.tessface_uv_layers */
-static void rna_def_tessface_uv_textures(BlenderRNA *brna, PropertyRNA *cprop)
-{
-       StructRNA *srna;
-       PropertyRNA *prop;
-
-       FunctionRNA *func;
-       PropertyRNA *parm;
-
-       RNA_def_property_srna(cprop, "TessfaceUVTextures");
-       srna = RNA_def_struct(brna, "TessfaceUVTextures", NULL);
-       RNA_def_struct_sdna(srna, "Mesh");
-       RNA_def_struct_ui_text(srna, "UV Maps", "Collection of UV maps for tessellated faces");
-
-       /* eventually deprecate this */
-       func = RNA_def_function(srna, "new", "rna_Mesh_tessface_uv_texture_new");
-       RNA_def_function_flag(func, FUNC_USE_REPORTS);
-       RNA_def_function_ui_description(func, "Add a UV tessface-texture layer to Mesh (only for meshes with no polygons)");
-       RNA_def_string(func, "name", "UVMap", 0, "", "UV map name");
-       parm = RNA_def_pointer(func, "layer", "MeshTextureFaceLayer", "", "The newly created layer");
-       RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
-       RNA_def_function_return(func, parm);
-
-       prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
-       RNA_def_property_struct_type(prop, "MeshTextureFaceLayer");
-       RNA_def_property_pointer_funcs(prop, "rna_Mesh_tessface_uv_texture_active_get",
-                                      "rna_Mesh_tessface_uv_texture_active_set", NULL, NULL);
-       RNA_def_property_ui_text(prop, "Active UV Map", "Active UV Map");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-       prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
-       RNA_def_property_int_funcs(prop, "rna_Mesh_tessface_uv_texture_active_index_get",
-                                  "rna_Mesh_tessface_uv_texture_active_index_set", "rna_Mesh_uv_layer_index_range");
-       RNA_def_property_ui_text(prop, "Active UV Map Index", "Active UV Map index");
-       RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-}
-
 static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
 {
        StructRNA *srna;
@@ -3256,12 +2586,6 @@ static void rna_def_mesh(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Edges", "Edges of the mesh");
        rna_def_mesh_edges(brna, prop);
 
-       prop = RNA_def_property(srna, "tessfaces", PROP_COLLECTION, PROP_NONE);
-       RNA_def_property_collection_sdna(prop, NULL, "mface", "totface");
-       RNA_def_property_struct_type(prop, "MeshTessFace");
-       RNA_def_property_ui_text(prop, "TessFaces", "Tessellated faces of the mesh (derived from polygons)");
-       rna_def_mesh_tessfaces(brna, prop);
-
        prop = RNA_def_property(srna, "loops", PROP_COLLECTION, PROP_NONE);
        RNA_def_property_collection_sdna(prop, NULL, "mloop", "totloop");
        RNA_def_property_struct_type(prop, "MeshLoop");
@@ -3274,6 +2598,12 @@ static void rna_def_mesh(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Polygons", "Polygons of the mesh");
        rna_def_mesh_polygons(brna, prop);
 
+       prop = RNA_def_property(srna, "loop_triangles", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_collection_sdna(prop, NULL, "runtime.looptris.array", "runtime.looptris.len");
+       RNA_def_property_struct_type(prop, "MeshLoopTriangle");
+       RNA_def_property_ui_text(prop, "Loop Triangles", "Tessellation of mesh polygons into triangles");
+       rna_def_mesh_looptris(brna, prop);
+
        /* TODO, should this be allowed to be its self? */
        prop = RNA_def_property(srna, "texture_mesh", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "texcomesh");
@@ -3314,27 +2644,6 @@ static void rna_def_mesh(BlenderRNA *brna)
                                   "rna_Mesh_uv_layer_stencil_index_set", "rna_Mesh_uv_layer_index_range");
        RNA_def_property_ui_text(prop, "Mask UV loop layer Index", "Mask UV loop layer index");
 
-       /* Tessellated face UV maps - used by renderers */
-       prop = RNA_def_property(srna, "tessface_uv_textures", PROP_COLLECTION, PROP_NONE);
-       RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
-       RNA_def_property_collection_funcs(prop, "rna_Mesh_tessface_uv_textures_begin", NULL, NULL, NULL,
-                                         "rna_Mesh_tessface_uv_textures_length", NULL, NULL, NULL);
-       RNA_def_property_struct_type(prop, "MeshTextureFaceLayer");
-       RNA_def_property_ui_text(prop, "Tessellated Face UV Maps",
-                                "All UV maps for tessellated faces (read-only, for use by renderers)");
-       rna_def_tessface_uv_textures(brna, prop);
-
-       /* Tessellated face colors - used by renderers */
-
-       prop = RNA_def_property(srna, "tessface_vertex_colors", PROP_COLLECTION, PROP_NONE);
-       RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
-       RNA_def_property_collection_funcs(prop, "rna_Mesh_tessface_vertex_colors_begin", NULL, NULL, NULL,
-                                         "rna_Mesh_tessface_vertex_colors_length", NULL, NULL, NULL);
-       RNA_def_property_struct_type(prop, "MeshColorLayer");
-       RNA_def_property_ui_text(prop, "Tessellated Face Colors",
-                                "All tessellated face colors (read-only, for use by renderers)");
-       rna_def_tessface_vertex_colors(brna, prop);
-
        /* Vertex colors */
 
        prop = RNA_def_property(srna, "vertex_colors", PROP_COLLECTION, PROP_NONE);
@@ -3570,12 +2879,10 @@ void RNA_def_mesh(BlenderRNA *brna)
        rna_def_mvert(brna);
        rna_def_mvert_group(brna);
        rna_def_medge(brna);
-       rna_def_mface(brna);
+       rna_def_mlooptri(brna);
        rna_def_mloop(brna);
        rna_def_mpolygon(brna);
        rna_def_mloopuv(brna);
-       rna_def_mtface(brna);
-       rna_def_mcol(brna);
        rna_def_mloopcol(brna);
        rna_def_mproperties(brna);
        rna_def_face_map(brna);
index 7328686af7fbcd74d9eeeac45e8d099c5697503f..b1556edd4b7cd589ab05d396bc44050bde319ce8 100644 (file)
@@ -50,6 +50,7 @@
 #include "BKE_mesh.h"
 #include "BKE_mesh_tangent.h"
 #include "BKE_mesh_mapping.h"
+#include "BKE_mesh_runtime.h"
 #include "ED_mesh.h"
 
 static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, struct Mesh *mesh2)
@@ -101,9 +102,9 @@ static void rna_Mesh_free_tangents(Mesh *mesh)
        CustomData_free_layers(&mesh->ldata, CD_MLOOPTANGENT, mesh->totloop);
 }
 
-static void rna_Mesh_calc_tessface(Mesh *mesh, bool free_mpoly)
+static void rna_Mesh_calc_looptri(Mesh *mesh)
 {
-       ED_mesh_calc_tessface(mesh, free_mpoly != 0);
+       BKE_mesh_runtime_looptri_ensure(mesh);
 }
 
 static void rna_Mesh_calc_smooth_groups(Mesh *mesh, bool use_bitflags, int *r_poly_group_len,
@@ -206,6 +207,7 @@ static void rna_Mesh_flip_normals(Mesh *mesh)
        BKE_mesh_polygons_flip(mesh->mpoly, mesh->mloop, &mesh->ldata, mesh->totpoly);
        BKE_mesh_tessface_clear(mesh);
        BKE_mesh_calc_normals(mesh);
+       BKE_mesh_runtime_clear_geometry(mesh);
 
        DEG_id_tag_update(&mesh->id, 0);
 }
@@ -269,12 +271,8 @@ void RNA_api_mesh(StructRNA *srna)
        func = RNA_def_function(srna, "free_tangents", "rna_Mesh_free_tangents");
        RNA_def_function_ui_description(func, "Free tangents");
 
-       func = RNA_def_function(srna, "calc_tessface", "rna_Mesh_calc_tessface");
-       RNA_def_function_ui_description(func, "Calculate face tessellation (supports editmode too)");
-       RNA_def_boolean(func, "free_mpoly", 0, "Free MPoly", "Free data used by polygons and loops. "
-                       "WARNING: This destructive operation removes regular faces, "
-                       "only used on temporary mesh data-blocks to reduce memory footprint of render "
-                       "engines and export scripts");
+       func = RNA_def_function(srna, "calc_loop_triangles", "rna_Mesh_calc_looptri");
+       RNA_def_function_ui_description(func, "Calculate loop triangle tessellation (supports editmode too)");
 
        func = RNA_def_function(srna, "calc_smooth_groups", "rna_Mesh_calc_smooth_groups");
        RNA_def_function_ui_description(func, "Calculate smooth groups from sharp edges");
@@ -308,7 +306,7 @@ void RNA_api_mesh(StructRNA *srna)
 
        func = RNA_def_function(srna, "update", "ED_mesh_update");
        RNA_def_boolean(func, "calc_edges", 0, "Calculate Edges", "Force recalculation of edges");
-       RNA_def_boolean(func, "calc_tessface", 0, "Calculate Tessellation", "Force recalculation of tessellation faces");
+       RNA_def_boolean(func, "calc_loop_triangles", 0, "Calculate Triangules", "Force recalculation of triangle tessellation");
        RNA_def_function_flag(func, FUNC_USE_CONTEXT);
 
        RNA_def_function(srna, "update_gpu_tag", "rna_Mesh_update_gpu_tag");
index b5e3ce4fd280728d255801a272df448ef9c3f2d4..de4dfbbdae7770090cc3a7d3d4377ddf44a579e0 100644 (file)
@@ -224,11 +224,11 @@ static void rna_Object_camera_fit_coords(
 /* settings: 0 - preview, 1 - render */
 static Mesh *rna_Object_to_mesh(
         Object *ob, bContext *C, ReportList *reports, Depsgraph *depsgraph,
-        bool apply_modifiers, bool calc_tessface, bool calc_undeformed)
+        bool apply_modifiers, bool calc_loop_triangles, bool calc_undeformed)
 {
        Main *bmain = CTX_data_main(C);
 
-       return rna_Main_meshes_new_from_object(bmain, reports, depsgraph, ob, apply_modifiers, calc_tessface, calc_undeformed);
+       return rna_Main_meshes_new_from_object(bmain, reports, depsgraph, ob, apply_modifiers, calc_loop_triangles, calc_undeformed);
 }
 
 static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *reports,
@@ -594,7 +594,7 @@ void RNA_api_object(StructRNA *srna)
        RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
        parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
        RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
-       RNA_def_boolean(func, "calc_tessface", true, "Calculate Tessellation", "Calculate tessellation faces");
+       RNA_def_boolean(func, "calc_loop_triangles", true, "Calculate Loop Triangles", "Calculate triangle tessellation");
        RNA_def_boolean(func, "calc_undeformed", false, "Calculate Undeformed", "Calculate undeformed vertex coordinates");
        parm = RNA_def_pointer(func, "mesh", "Mesh", "",
                               "Mesh created from object, remove it if it is only used for export");
index 3edd2bac24423a4b50bc063cb81a7cca70e1aefb..235ede1e8fd779d73eeceba62d3061f2a14307b8 100644 (file)
@@ -113,30 +113,30 @@ static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value)
 }
 
 PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc,
-".. method:: update_edit_mesh(mesh, tessface=True, destructive=True)\n"
+".. method:: update_edit_mesh(mesh, loop_triangles=True, destructive=True)\n"
 "\n"
 "   Update the mesh after changes to the BMesh in editmode, \n"
 "   optionally recalculating n-gon tessellation.\n"
 "\n"
 "   :arg mesh: The editmode mesh.\n"
 "   :type mesh: :class:`bpy.types.Mesh`\n"
-"   :arg tessface: Option to recalculate n-gon tessellation.\n"
-"   :type tessface: boolean\n"
+"   :arg loop_triangles: Option to recalculate n-gon tessellation.\n"
+"   :type loop_triangles: boolean\n"
 "   :arg destructive: Use when geometry has been added or removed.\n"
 "   :type destructive: boolean\n"
 );
 static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
 {
-       static const char *kwlist[] = {"mesh", "tessface", "destructive", NULL};
+       static const char *kwlist[] = {"mesh", "loop_triangles", "destructive", NULL};
        PyObject *py_me;
        Mesh *me;
-       bool do_tessface = true;
+       bool do_loop_triangles = true;
        bool is_destructive = true;
 
        if (!PyArg_ParseTupleAndKeywords(
                args, kw, "O|O&O&:update_edit_mesh", (char **)kwlist,
                &py_me,
-               PyC_ParseBool, &do_tessface,
+               PyC_ParseBool, &do_loop_triangles,
                PyC_ParseBool, &is_destructive))
        {
                return NULL;
@@ -157,7 +157,7 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args,
        {
                extern void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive);
 
-               EDBM_update_generic(me->edit_btmesh, do_tessface, is_destructive);
+               EDBM_update_generic(me->edit_btmesh, do_loop_triangles, is_destructive);
        }
 
        Py_RETURN_NONE;
index b380fbd416e74abc2c7eff98d3c2b60dfe362e93..3ce5a26de90942509f95543595b35629bd286512 100644 (file)
@@ -1246,15 +1246,15 @@ static PyObject *bpy_bmesh_calc_volume(BPy_BMElem *self, PyObject *args, PyObjec
        }
 }
 
-PyDoc_STRVAR(bpy_bmesh_calc_tessface_doc,
-".. method:: calc_tessface()\n"
+PyDoc_STRVAR(bpy_bmesh_calc_loop_triangles_doc,
+".. method:: calc_loop_triangles()\n"
 "\n"
 "   Calculate triangle tessellation from quads/ngons.\n"
 "\n"
 "   :return: The triangulated faces.\n"
 "   :rtype: list of :class:`BMLoop` tuples\n"
 );
-static PyObject *bpy_bmesh_calc_tessface(BPy_BMElem *self)
+static PyObject *bpy_bmesh_calc_loop_triangles(BPy_BMElem *self)
 {
        BMesh *bm;
 
@@ -2733,7 +2733,7 @@ static struct PyMethodDef bpy_bmesh_methods[] = {
 
        /* calculations */
        {"calc_volume", (PyCFunction)bpy_bmesh_calc_volume, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_calc_volume_doc},
-       {"calc_tessface", (PyCFunction)bpy_bmesh_calc_tessface, METH_NOARGS, bpy_bmesh_calc_tessface_doc},
+       {"calc_loop_triangles", (PyCFunction)bpy_bmesh_calc_loop_triangles, METH_NOARGS, bpy_bmesh_calc_loop_triangles_doc},
        {NULL, NULL, 0, NULL}
 };
 
index f60105e029d61fac2cc130fadc3cff817b76a2ec..12c13bcac8135e6b346ab27a8e9f70521fff3722 100644 (file)
@@ -86,9 +86,6 @@
 #include "render_types.h"
 #include "zbuf.h"
 
-/* Remove when Cycles moves from MFace to MLoopTri */
-#define USE_MFACE_WORKAROUND
-
 typedef struct BakeDataZSpan {
        BakePixel *pixel_array;
        int primitive_id;
@@ -393,27 +390,6 @@ static bool cast_ray_highpoly(
        return hit_mesh != -1;
 }
 
-#ifdef USE_MFACE_WORKAROUND
-/**
- * Until cycles moves to #MLoopTri, we need to keep face-rotation in sync with #test_index_face
- *
- * We only need to consider quads since #BKE_mesh_recalc_tessellation doesn't execute this on triangles.
- */
-static void test_index_face_looptri(const MPoly *mp, MLoop *mloop, MLoopTri *lt)
-{
-       if (mp->totloop == 4) {
-               if (UNLIKELY((mloop[mp->loopstart + 2].v == 0) ||
-                            (mloop[mp->loopstart + 3].v == 0)))
-               {
-                       /* remap: (2, 3, 0, 1) */
-                       unsigned int l = mp->loopstart;
-                       ARRAY_SET_ITEMS(lt[0].tri, l + 2, l + 3, l + 0);
-                       ARRAY_SET_ITEMS(lt[1].tri, l + 2, l + 0, l + 1);
-               }
-       }
-}
-#endif
-
 /**
  * This function populates an array of verts for the triangles of a mesh
  * Tangent and Normals are also stored
@@ -433,10 +409,6 @@ static TriTessFace *mesh_calc_tri_tessface(
        unsigned int mpoly_prev = UINT_MAX;
        float no[3];
 
-#ifdef USE_MFACE_WORKAROUND
-       unsigned int mpoly_prev_testindex = UINT_MAX;
-#endif
-
        mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
        looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
        triangles = MEM_mallocN(sizeof(TriTessFace) * tottri, __func__);
@@ -463,13 +435,6 @@ static TriTessFace *mesh_calc_tri_tessface(
                const MLoopTri *lt = &looptri[i];
                const MPoly *mp = &me->mpoly[lt->poly];
 
-#ifdef USE_MFACE_WORKAROUND
-               if (lt->poly != mpoly_prev_testindex) {
-                       test_index_face_looptri(mp, me->mloop, &looptri[i]);
-                       mpoly_prev_testindex = lt->poly;
-               }
-#endif
-
                triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v];
                triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v];
                triangles[i].mverts[2] = &mvert[me->mloop[lt->tri[2]].v];
@@ -662,9 +627,6 @@ void RE_bake_pixels_populate(
        const MLoopUV *mloopuv;
        const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
        MLoopTri *looptri;
-#ifdef USE_MFACE_WORKAROUND
-       unsigned int mpoly_prev_testindex = UINT_MAX;
-#endif
 
        if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
                mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
@@ -714,13 +676,6 @@ void RE_bake_pixels_populate(
                bd.bk_image = &bake_images->data[image_id];
                bd.primitive_id = ++p_id;
 
-#ifdef USE_MFACE_WORKAROUND
-               if (lt->poly != mpoly_prev_testindex) {
-                       test_index_face_looptri(mp, me->mloop, &looptri[i]);
-                       mpoly_prev_testindex = lt->poly;
-               }
-#endif
-
                for (a = 0; a < 3; a++) {
                        const float *uv = mloopuv[lt->tri[a]].uv;